hive-nectar 0.0.6__py3-none-any.whl → 0.0.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of hive-nectar might be problematic. Click here for more details.
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/METADATA +5 -3
- hive_nectar-0.0.9.dist-info/RECORD +91 -0
- nectar/__init__.py +1 -0
- nectar/account.py +44 -48
- nectar/amount.py +6 -11
- nectar/block.py +8 -9
- nectar/blockchain.py +4 -5
- nectar/blockchaininstance.py +4 -4
- nectar/blockchainobject.py +5 -6
- nectar/blurt.py +3 -4
- nectar/cli.py +14 -14
- nectar/comment.py +10 -11
- nectar/community.py +527 -181
- nectar/conveyor.py +3 -4
- nectar/exceptions.py +30 -24
- nectar/hive.py +3 -4
- nectar/hivesigner.py +2 -2
- nectar/imageuploader.py +2 -3
- nectar/nodelist.py +83 -7
- nectar/price.py +6 -13
- nectar/rc.py +1 -2
- nectar/steem.py +3 -4
- nectar/storage.py +3 -4
- nectar/transactionbuilder.py +12 -3
- nectar/version.py +1 -1
- nectar/vote.py +8 -9
- nectar/wallet.py +1 -1
- nectarapi/__init__.py +1 -0
- nectarapi/exceptions.py +20 -14
- nectarapi/version.py +1 -1
- nectarbase/__init__.py +1 -0
- nectarbase/ledgertransactions.py +2 -3
- nectarbase/memo.py +9 -10
- nectarbase/objects.py +4 -5
- nectarbase/operations.py +3 -7
- nectarbase/version.py +1 -1
- nectargraphenebase/__init__.py +1 -1
- nectargraphenebase/account.py +16 -37
- nectargraphenebase/base58.py +5 -8
- nectargraphenebase/bip32.py +5 -11
- nectargraphenebase/bip38.py +6 -7
- nectargraphenebase/ecdsasig.py +32 -37
- nectargraphenebase/objects.py +6 -7
- nectargraphenebase/operations.py +2 -0
- nectargraphenebase/signedtransactions.py +10 -9
- nectargraphenebase/types.py +9 -19
- nectargraphenebase/unsignedtransactions.py +21 -28
- nectargraphenebase/version.py +1 -1
- nectarstorage/__init__.py +21 -1
- nectarstorage/masterpassword.py +2 -3
- nectarstorage/sqlite.py +1 -1
- hive_nectar-0.0.6.dist-info/RECORD +0 -92
- nectargraphenebase/py23.py +0 -38
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/licenses/LICENSE.txt +0 -0
nectarapi/__init__.py
CHANGED
nectarapi/exceptions.py
CHANGED
|
@@ -19,37 +19,43 @@ def decodeRPCErrorMsg(e):
|
|
|
19
19
|
return str(e)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class
|
|
22
|
+
class NectarApiException(Exception):
|
|
23
|
+
"""NectarApiException base Exception."""
|
|
24
|
+
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class UnauthorizedError(NectarApiException):
|
|
23
29
|
"""UnauthorizedError Exception."""
|
|
24
30
|
|
|
25
31
|
pass
|
|
26
32
|
|
|
27
33
|
|
|
28
|
-
class RPCConnection(
|
|
34
|
+
class RPCConnection(NectarApiException):
|
|
29
35
|
"""RPCConnection Exception."""
|
|
30
36
|
|
|
31
37
|
pass
|
|
32
38
|
|
|
33
39
|
|
|
34
|
-
class RPCError(
|
|
40
|
+
class RPCError(NectarApiException):
|
|
35
41
|
"""RPCError Exception."""
|
|
36
42
|
|
|
37
43
|
pass
|
|
38
44
|
|
|
39
45
|
|
|
40
|
-
class RPCErrorDoRetry(
|
|
46
|
+
class RPCErrorDoRetry(NectarApiException):
|
|
41
47
|
"""RPCErrorDoRetry Exception."""
|
|
42
48
|
|
|
43
49
|
pass
|
|
44
50
|
|
|
45
51
|
|
|
46
|
-
class NumRetriesReached(
|
|
52
|
+
class NumRetriesReached(NectarApiException):
|
|
47
53
|
"""NumRetriesReached Exception."""
|
|
48
54
|
|
|
49
55
|
pass
|
|
50
56
|
|
|
51
57
|
|
|
52
|
-
class CallRetriesReached(
|
|
58
|
+
class CallRetriesReached(NectarApiException):
|
|
53
59
|
"""CallRetriesReached Exception. Only for internal use"""
|
|
54
60
|
|
|
55
61
|
pass
|
|
@@ -91,33 +97,33 @@ class FilteredItemNotFound(RPCError):
|
|
|
91
97
|
pass
|
|
92
98
|
|
|
93
99
|
|
|
94
|
-
class InvalidEndpointUrl(
|
|
100
|
+
class InvalidEndpointUrl(NectarApiException):
|
|
95
101
|
pass
|
|
96
102
|
|
|
97
103
|
|
|
98
|
-
class InvalidParameters(
|
|
104
|
+
class InvalidParameters(NectarApiException):
|
|
99
105
|
pass
|
|
100
106
|
|
|
101
107
|
|
|
102
|
-
class SupportedByHivemind(
|
|
108
|
+
class SupportedByHivemind(NectarApiException):
|
|
103
109
|
pass
|
|
104
110
|
|
|
105
111
|
|
|
106
|
-
class UnnecessarySignatureDetected(
|
|
112
|
+
class UnnecessarySignatureDetected(NectarApiException):
|
|
107
113
|
pass
|
|
108
114
|
|
|
109
115
|
|
|
110
|
-
class WorkingNodeMissing(
|
|
116
|
+
class WorkingNodeMissing(NectarApiException):
|
|
111
117
|
pass
|
|
112
118
|
|
|
113
119
|
|
|
114
|
-
class TimeoutException(
|
|
120
|
+
class TimeoutException(NectarApiException):
|
|
115
121
|
pass
|
|
116
122
|
|
|
117
123
|
|
|
118
|
-
class VotedBeforeWaitTimeReached(
|
|
124
|
+
class VotedBeforeWaitTimeReached(NectarApiException):
|
|
119
125
|
pass
|
|
120
126
|
|
|
121
127
|
|
|
122
|
-
class UnknownTransaction(
|
|
128
|
+
class UnknownTransaction(NectarApiException):
|
|
123
129
|
pass
|
nectarapi/version.py
CHANGED
nectarbase/__init__.py
CHANGED
nectarbase/ledgertransactions.py
CHANGED
|
@@ -3,7 +3,6 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
from nectargraphenebase.account import PublicKey
|
|
5
5
|
from nectargraphenebase.chains import known_chains
|
|
6
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
7
6
|
from nectargraphenebase.types import (
|
|
8
7
|
Array,
|
|
9
8
|
Signature,
|
|
@@ -54,7 +53,7 @@ class Ledger_Transaction(GrapheneUnsigned_Transaction):
|
|
|
54
53
|
dongle = getDongle(True)
|
|
55
54
|
apdu_list = self.build_apdu(path, chain)
|
|
56
55
|
for apdu in apdu_list:
|
|
57
|
-
result = dongle.exchange(
|
|
56
|
+
result = dongle.exchange(bytes(apdu))
|
|
58
57
|
dongle.close()
|
|
59
58
|
sigs = []
|
|
60
59
|
signature = result
|
|
@@ -67,7 +66,7 @@ class Ledger_Transaction(GrapheneUnsigned_Transaction):
|
|
|
67
66
|
|
|
68
67
|
dongle = getDongle(True)
|
|
69
68
|
apdu = self.build_apdu_pubkey(path, request_screen_approval)
|
|
70
|
-
result = dongle.exchange(
|
|
69
|
+
result = dongle.exchange(bytes(apdu))
|
|
71
70
|
dongle.close()
|
|
72
71
|
offset = 1 + result[0]
|
|
73
72
|
address = result[offset + 1 : offset + 1 + result[offset]]
|
nectarbase/memo.py
CHANGED
|
@@ -3,7 +3,6 @@ import hashlib
|
|
|
3
3
|
from binascii import hexlify, unhexlify
|
|
4
4
|
|
|
5
5
|
from nectargraphenebase.base58 import base58decode, base58encode
|
|
6
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
7
6
|
from nectargraphenebase.types import varintdecode
|
|
8
7
|
|
|
9
8
|
try:
|
|
@@ -50,7 +49,7 @@ def init_aes(shared_secret, nonce):
|
|
|
50
49
|
" Shared Secret "
|
|
51
50
|
ss = hashlib.sha512(unhexlify(shared_secret)).digest()
|
|
52
51
|
" Seed "
|
|
53
|
-
seed =
|
|
52
|
+
seed = bytes(str(nonce), "ascii") + hexlify(ss)
|
|
54
53
|
seed_digest = hexlify(hashlib.sha512(seed).digest()).decode("ascii")
|
|
55
54
|
" AES "
|
|
56
55
|
key = unhexlify(seed_digest[0:64])
|
|
@@ -76,7 +75,7 @@ def init_aes_bts(shared_secret, nonce):
|
|
|
76
75
|
return AES.new(key, AES.MODE_CBC, iv)
|
|
77
76
|
|
|
78
77
|
|
|
79
|
-
def
|
|
78
|
+
def init_aes2(shared_secret, nonce):
|
|
80
79
|
"""Initialize AES instance
|
|
81
80
|
:param hex shared_secret: Shared Secret to use as encryption key
|
|
82
81
|
:param int nonce: Random nonce
|
|
@@ -121,7 +120,7 @@ def encode_memo_bts(priv, pub, nonce, message):
|
|
|
121
120
|
shared_secret = get_shared_secret(priv, pub)
|
|
122
121
|
aes = init_aes_bts(shared_secret, nonce)
|
|
123
122
|
" Checksum "
|
|
124
|
-
raw =
|
|
123
|
+
raw = bytes(message, "utf8")
|
|
125
124
|
checksum = hashlib.sha256(raw).digest()
|
|
126
125
|
raw = checksum[0:4] + raw
|
|
127
126
|
" Padding "
|
|
@@ -146,7 +145,7 @@ def decode_memo_bts(priv, pub, nonce, message):
|
|
|
146
145
|
shared_secret = get_shared_secret(priv, pub)
|
|
147
146
|
aes = init_aes_bts(shared_secret, nonce)
|
|
148
147
|
" Encryption "
|
|
149
|
-
raw =
|
|
148
|
+
raw = bytes(message, "ascii")
|
|
150
149
|
cleartext = aes.decrypt(unhexlify(raw))
|
|
151
150
|
" Checksum "
|
|
152
151
|
checksum = cleartext[0:4]
|
|
@@ -170,9 +169,9 @@ def encode_memo(priv, pub, nonce, message, **kwargs):
|
|
|
170
169
|
:rtype: hex
|
|
171
170
|
"""
|
|
172
171
|
shared_secret = get_shared_secret(priv, pub)
|
|
173
|
-
aes, check =
|
|
172
|
+
aes, check = init_aes2(shared_secret, nonce)
|
|
174
173
|
" Padding "
|
|
175
|
-
raw =
|
|
174
|
+
raw = bytes(message, "utf8")
|
|
176
175
|
raw = _pad(raw, 16)
|
|
177
176
|
" Encryption "
|
|
178
177
|
cipher = hexlify(aes.encrypt(raw)).decode("ascii")
|
|
@@ -186,7 +185,7 @@ def encode_memo(priv, pub, nonce, message, **kwargs):
|
|
|
186
185
|
"prefix": prefix,
|
|
187
186
|
}
|
|
188
187
|
tx = Memo(**s)
|
|
189
|
-
return "#" + base58encode(hexlify(
|
|
188
|
+
return "#" + base58encode(hexlify(bytes(tx)).decode("ascii"))
|
|
190
189
|
|
|
191
190
|
|
|
192
191
|
def extract_memo_data(message):
|
|
@@ -225,7 +224,7 @@ def decode_memo(priv, message):
|
|
|
225
224
|
raise ValueError("Incorrect PrivateKey")
|
|
226
225
|
|
|
227
226
|
# Init encryption
|
|
228
|
-
aes, checksum =
|
|
227
|
+
aes, checksum = init_aes2(shared_secret, nonce)
|
|
229
228
|
# Check
|
|
230
229
|
if not check == checksum:
|
|
231
230
|
raise AssertionError("Checksum failure")
|
|
@@ -234,7 +233,7 @@ def decode_memo(priv, message):
|
|
|
234
233
|
numBytes = 16 - len(cipher) % 16
|
|
235
234
|
n = 16 - numBytes
|
|
236
235
|
message = cipher[n:]
|
|
237
|
-
message = aes.decrypt(unhexlify(
|
|
236
|
+
message = aes.decrypt(unhexlify(bytes(message, "ascii")))
|
|
238
237
|
message = _unpad(message, 16)
|
|
239
238
|
n = varintdecode(message)
|
|
240
239
|
if (len(message) - n) > 0 and (len(message) - n) < 8:
|
nectarbase/objects.py
CHANGED
|
@@ -8,7 +8,6 @@ from nectargraphenebase.account import PublicKey
|
|
|
8
8
|
from nectargraphenebase.chains import known_chains
|
|
9
9
|
from nectargraphenebase.objects import GrapheneObject, isArgsThisClass
|
|
10
10
|
from nectargraphenebase.objects import Operation as GPHOperation
|
|
11
|
-
from nectargraphenebase.py23 import py23_bytes, string_types
|
|
12
11
|
from nectargraphenebase.types import (
|
|
13
12
|
Array,
|
|
14
13
|
Bytes,
|
|
@@ -38,7 +37,7 @@ def value_to_decimal(value, decimal_places):
|
|
|
38
37
|
class Amount(object):
|
|
39
38
|
def __init__(self, d, prefix=default_prefix, json_str=False):
|
|
40
39
|
self.json_str = json_str
|
|
41
|
-
if isinstance(d,
|
|
40
|
+
if isinstance(d, str):
|
|
42
41
|
self.amount, self.symbol = d.strip().split(" ")
|
|
43
42
|
self.precision = None
|
|
44
43
|
for c in known_chains:
|
|
@@ -113,7 +112,7 @@ class Amount(object):
|
|
|
113
112
|
return (
|
|
114
113
|
struct.pack("<q", int(self.amount))
|
|
115
114
|
+ struct.pack("<b", self.precision)
|
|
116
|
-
+
|
|
115
|
+
+ bytes(symbol, "ascii")
|
|
117
116
|
)
|
|
118
117
|
|
|
119
118
|
def __str__(self):
|
|
@@ -150,7 +149,7 @@ class Operation(GPHOperation):
|
|
|
150
149
|
# return json.loads(str(json.dumps([self.name, self.op.toJson()])))
|
|
151
150
|
|
|
152
151
|
def __bytes__(self):
|
|
153
|
-
return
|
|
152
|
+
return bytes(Id(self.opId)) + bytes(self.op)
|
|
154
153
|
|
|
155
154
|
def __str__(self):
|
|
156
155
|
if self.appbase:
|
|
@@ -364,7 +363,7 @@ class CommentOptionExtensions(Static_variant):
|
|
|
364
363
|
"""
|
|
365
364
|
|
|
366
365
|
def __init__(self, o):
|
|
367
|
-
if
|
|
366
|
+
if isinstance(o, dict) and "type" in o and "value" in o:
|
|
368
367
|
if o["type"] == "comment_payout_beneficiaries":
|
|
369
368
|
type_id = 0
|
|
370
369
|
else:
|
nectarbase/operations.py
CHANGED
|
@@ -5,7 +5,6 @@ from binascii import hexlify
|
|
|
5
5
|
from collections import OrderedDict
|
|
6
6
|
|
|
7
7
|
from nectargraphenebase.account import PublicKey
|
|
8
|
-
from nectargraphenebase.py23 import PY2, PY3, string_types
|
|
9
8
|
from nectargraphenebase.types import (
|
|
10
9
|
Array,
|
|
11
10
|
Bool,
|
|
@@ -58,7 +57,7 @@ class Transfer(GrapheneObject):
|
|
|
58
57
|
if isinstance(kwargs["memo"], dict):
|
|
59
58
|
kwargs["memo"]["prefix"] = prefix
|
|
60
59
|
memo = Optional(Memo(**kwargs["memo"]))
|
|
61
|
-
elif isinstance(kwargs["memo"],
|
|
60
|
+
elif isinstance(kwargs["memo"], str):
|
|
62
61
|
memo = String(kwargs["memo"])
|
|
63
62
|
else:
|
|
64
63
|
memo = Optional(Memo(kwargs["memo"]))
|
|
@@ -90,7 +89,7 @@ class Recurring_transfer(GrapheneObject):
|
|
|
90
89
|
if isinstance(kwargs["memo"], dict):
|
|
91
90
|
kwargs["memo"]["prefix"] = prefix
|
|
92
91
|
memo = Optional(Memo(**kwargs["memo"]))
|
|
93
|
-
elif isinstance(kwargs["memo"],
|
|
92
|
+
elif isinstance(kwargs["memo"], str):
|
|
94
93
|
memo = String(kwargs["memo"])
|
|
95
94
|
else:
|
|
96
95
|
memo = Optional(Memo(kwargs["memo"]))
|
|
@@ -539,10 +538,8 @@ class Witness_set_properties(GrapheneObject):
|
|
|
539
538
|
for k in kwargs["props"]:
|
|
540
539
|
if k[0] in ["key", "new_signing_key"]:
|
|
541
540
|
continue
|
|
542
|
-
if isinstance(k[1], str)
|
|
541
|
+
if isinstance(k[1], str):
|
|
543
542
|
is_hex = re.fullmatch(r"[0-9a-fA-F]+", k[1] or "") is not None
|
|
544
|
-
elif isinstance(k[1], str) and PY2:
|
|
545
|
-
is_hex = re.match(r"[0-9a-fA-F]+", k[1] or "") is not None
|
|
546
543
|
else:
|
|
547
544
|
is_hex = False
|
|
548
545
|
if isinstance(k[1], int) and k[0] in [
|
|
@@ -991,7 +988,6 @@ class Transfer_from_savings(GrapheneObject):
|
|
|
991
988
|
json_str = kwargs.get("json_str", False)
|
|
992
989
|
if "memo" not in kwargs:
|
|
993
990
|
kwargs["memo"] = ""
|
|
994
|
-
|
|
995
991
|
super(Transfer_from_savings, self).__init__(
|
|
996
992
|
OrderedDict(
|
|
997
993
|
[
|
nectarbase/version.py
CHANGED
nectargraphenebase/__init__.py
CHANGED
|
@@ -10,6 +10,7 @@ from .version import version as __version__
|
|
|
10
10
|
# from . import dictionary as BrainKeyDictionary
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
|
+
"__version__",
|
|
13
14
|
"account",
|
|
14
15
|
"aes",
|
|
15
16
|
"base58",
|
|
@@ -23,5 +24,4 @@ __all__ = [
|
|
|
23
24
|
"signedtransactions",
|
|
24
25
|
"unsignedtransactions",
|
|
25
26
|
"objecttypes",
|
|
26
|
-
"py23",
|
|
27
27
|
]
|
nectargraphenebase/account.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import binascii
|
|
3
3
|
import bisect
|
|
4
|
-
import codecs
|
|
5
4
|
import hashlib
|
|
6
5
|
import itertools
|
|
7
6
|
import os
|
|
8
7
|
import re
|
|
9
|
-
import sys
|
|
10
8
|
import unicodedata
|
|
11
9
|
from binascii import hexlify, unhexlify
|
|
12
10
|
|
|
@@ -17,7 +15,6 @@ from .bip32 import BIP32Key, parse_path
|
|
|
17
15
|
from .dictionary import words as BrainKeyDictionary
|
|
18
16
|
from .dictionary import words_bip39 as MnemonicDictionary
|
|
19
17
|
from .prefix import Prefix
|
|
20
|
-
from .py23 import PY2, py23_bytes
|
|
21
18
|
|
|
22
19
|
PBKDF2_ROUNDS = 2048
|
|
23
20
|
|
|
@@ -55,7 +52,7 @@ class PasswordKey(Prefix):
|
|
|
55
52
|
else:
|
|
56
53
|
seed = self.account + self.role + self.password
|
|
57
54
|
seed = self.normalize(seed)
|
|
58
|
-
a =
|
|
55
|
+
a = bytes(seed, "utf8")
|
|
59
56
|
s = hashlib.sha256(a).digest()
|
|
60
57
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.prefix)
|
|
61
58
|
|
|
@@ -121,13 +118,13 @@ class BrainKey(Prefix):
|
|
|
121
118
|
number
|
|
122
119
|
"""
|
|
123
120
|
encoded = "%s %d" % (self.brainkey, self.sequence)
|
|
124
|
-
a =
|
|
121
|
+
a = bytes(encoded, "ascii")
|
|
125
122
|
s = hashlib.sha256(hashlib.sha512(a).digest()).digest()
|
|
126
123
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.prefix)
|
|
127
124
|
|
|
128
125
|
def get_blind_private(self):
|
|
129
126
|
"""Derive private key from the brain key (and no sequence number)"""
|
|
130
|
-
a =
|
|
127
|
+
a = bytes(self.brainkey, "ascii")
|
|
131
128
|
return PrivateKey(hashlib.sha256(a).hexdigest(), prefix=self.prefix)
|
|
132
129
|
|
|
133
130
|
def get_public(self):
|
|
@@ -149,12 +146,7 @@ class BrainKey(Prefix):
|
|
|
149
146
|
raise AssertionError()
|
|
150
147
|
for j in range(0, word_count):
|
|
151
148
|
urand = os.urandom(2)
|
|
152
|
-
|
|
153
|
-
urand = py23_bytes(urand, "ascii")
|
|
154
|
-
if PY2:
|
|
155
|
-
num = int(codecs.encode(urand[::-1], "hex"), 16)
|
|
156
|
-
else:
|
|
157
|
-
num = int.from_bytes(urand, byteorder="little")
|
|
149
|
+
num = int.from_bytes(urand, byteorder="little")
|
|
158
150
|
rndMult = num / 2**16 # returns float between 0..1 (inclusive)
|
|
159
151
|
wIdx = int(round(len(dict_lines) * rndMult))
|
|
160
152
|
brainkey[j] = dict_lines[wIdx]
|
|
@@ -180,7 +172,7 @@ class Mnemonic(object):
|
|
|
180
172
|
"""
|
|
181
173
|
if strength not in [128, 160, 192, 224, 256]:
|
|
182
174
|
raise ValueError(
|
|
183
|
-
"Strength should be one of the following [128, 160, 192, 224, 256], but it is not (%d)."
|
|
175
|
+
"Strength should be one of the following: [128, 160, 192, 224, 256], but it is not (%d)."
|
|
184
176
|
% strength
|
|
185
177
|
)
|
|
186
178
|
return self.to_mnemonic(os.urandom(strength // 8))
|
|
@@ -223,18 +215,11 @@ class Mnemonic(object):
|
|
|
223
215
|
entropy[ii] |= 1 << (7 - jj)
|
|
224
216
|
# Take the digest of the entropy.
|
|
225
217
|
hashBytes = hashlib.sha256(entropy).digest()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
([ord(c) & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
230
|
-
)
|
|
231
|
-
)
|
|
232
|
-
else:
|
|
233
|
-
hashBits = list(
|
|
234
|
-
itertools.chain.from_iterable(
|
|
235
|
-
([c & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
236
|
-
)
|
|
218
|
+
hashBits = list(
|
|
219
|
+
itertools.chain.from_iterable(
|
|
220
|
+
([c & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
237
221
|
)
|
|
222
|
+
)
|
|
238
223
|
# Check all the checksum bits.
|
|
239
224
|
for i in range(checksumLengthBits):
|
|
240
225
|
if concatBits[entropyLengthBits + i] != hashBits[i]:
|
|
@@ -308,13 +293,7 @@ class Mnemonic(object):
|
|
|
308
293
|
@classmethod
|
|
309
294
|
def normalize_string(cls, txt):
|
|
310
295
|
"""Normalizes strings"""
|
|
311
|
-
|
|
312
|
-
utxt = txt.decode("utf8")
|
|
313
|
-
elif isinstance(txt, unicode if sys.version < "3" else str): # noqa: F821
|
|
314
|
-
utxt = txt
|
|
315
|
-
else:
|
|
316
|
-
raise TypeError("String value expected")
|
|
317
|
-
|
|
296
|
+
utxt = txt.decode("utf8")
|
|
318
297
|
return unicodedata.normalize("NFKD", utxt)
|
|
319
298
|
|
|
320
299
|
@classmethod
|
|
@@ -535,7 +514,7 @@ class Address(Prefix):
|
|
|
535
514
|
|
|
536
515
|
def __bytes__(self):
|
|
537
516
|
"""Returns the raw content of the ``Base58CheckEncoded`` address"""
|
|
538
|
-
return
|
|
517
|
+
return bytes(self._address)
|
|
539
518
|
|
|
540
519
|
|
|
541
520
|
class GrapheneAddress(Address):
|
|
@@ -683,7 +662,7 @@ class PublicKey(Prefix):
|
|
|
683
662
|
|
|
684
663
|
def __bytes__(self):
|
|
685
664
|
"""Returns the raw public key (has length 33)"""
|
|
686
|
-
return
|
|
665
|
+
return bytes(self._pk)
|
|
687
666
|
|
|
688
667
|
def __lt__(self, other):
|
|
689
668
|
"""For sorting of public keys (due to graphene),
|
|
@@ -774,13 +753,13 @@ class PrivateKey(Prefix):
|
|
|
774
753
|
sequence number
|
|
775
754
|
"""
|
|
776
755
|
encoded = "%s %d" % (str(self), sequence)
|
|
777
|
-
a =
|
|
756
|
+
a = bytes(encoded, "ascii")
|
|
778
757
|
s = hashlib.sha256(hashlib.sha512(a).digest()).digest()
|
|
779
758
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.pubkey.prefix)
|
|
780
759
|
|
|
781
760
|
def child(self, offset256):
|
|
782
761
|
"""Derive new private key from this key and a sha256 "offset" """
|
|
783
|
-
a =
|
|
762
|
+
a = bytes(self.pubkey) + offset256
|
|
784
763
|
s = hashlib.sha256(a).digest()
|
|
785
764
|
return self.derive_from_seed(s)
|
|
786
765
|
|
|
@@ -789,7 +768,7 @@ class PrivateKey(Prefix):
|
|
|
789
768
|
Here, the key itself serves as a `seed`, and `offset`
|
|
790
769
|
is expected to be a sha256 digest.
|
|
791
770
|
"""
|
|
792
|
-
seed = int(hexlify(
|
|
771
|
+
seed = int(hexlify(bytes(self)).decode("ascii"), 16)
|
|
793
772
|
z = int(hexlify(offset).decode("ascii"), 16)
|
|
794
773
|
order = ecdsa.SECP256k1.order
|
|
795
774
|
secexp = (seed + z) % order
|
|
@@ -816,7 +795,7 @@ class PrivateKey(Prefix):
|
|
|
816
795
|
|
|
817
796
|
def __bytes__(self):
|
|
818
797
|
"""Returns the raw private key"""
|
|
819
|
-
return
|
|
798
|
+
return bytes(self._wif)
|
|
820
799
|
|
|
821
800
|
|
|
822
801
|
class BitcoinAddress(Address):
|
nectargraphenebase/base58.py
CHANGED
|
@@ -5,7 +5,6 @@ import string
|
|
|
5
5
|
from binascii import hexlify, unhexlify
|
|
6
6
|
|
|
7
7
|
from .prefix import Prefix
|
|
8
|
-
from .py23 import integer_types, py23_bytes, py23_chr, string_types
|
|
9
8
|
|
|
10
9
|
log = logging.getLogger(__name__)
|
|
11
10
|
|
|
@@ -99,14 +98,12 @@ BASE58_ALPHABET = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
|
99
98
|
|
|
100
99
|
|
|
101
100
|
def base58decode(base58_str):
|
|
102
|
-
base58_text =
|
|
101
|
+
base58_text = bytes(base58_str, "ascii")
|
|
103
102
|
n = 0
|
|
104
103
|
leading_zeroes_count = 0
|
|
105
104
|
for b in base58_text:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
else:
|
|
109
|
-
n = n * 58 + BASE58_ALPHABET.find(b)
|
|
105
|
+
# b is always int in Python 3 when iterating bytes
|
|
106
|
+
n = n * 58 + BASE58_ALPHABET.find(bytes([b]))
|
|
110
107
|
if n == 0:
|
|
111
108
|
leading_zeroes_count += 1
|
|
112
109
|
res = bytearray()
|
|
@@ -120,7 +117,7 @@ def base58decode(base58_str):
|
|
|
120
117
|
|
|
121
118
|
|
|
122
119
|
def base58encode(hexstring):
|
|
123
|
-
byteseq =
|
|
120
|
+
byteseq = bytes(unhexlify(bytes(hexstring, "ascii")))
|
|
124
121
|
n = 0
|
|
125
122
|
leading_zeroes_count = 0
|
|
126
123
|
for c in byteseq:
|
|
@@ -156,7 +153,7 @@ def b58decode(v):
|
|
|
156
153
|
|
|
157
154
|
|
|
158
155
|
def base58CheckEncode(version, payload):
|
|
159
|
-
if isinstance(version,
|
|
156
|
+
if isinstance(version, str):
|
|
160
157
|
s = version + payload
|
|
161
158
|
else:
|
|
162
159
|
s = ("%.2x" % version) + payload
|
nectargraphenebase/bip32.py
CHANGED
|
@@ -17,7 +17,6 @@ from ecdsa.curves import SECP256k1
|
|
|
17
17
|
from ecdsa.numbertheory import square_root_mod_prime as sqrt_mod
|
|
18
18
|
|
|
19
19
|
from nectargraphenebase.base58 import base58CheckDecode, base58CheckEncode
|
|
20
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
21
20
|
|
|
22
21
|
VerifyKey = ecdsa.VerifyingKey.from_public_point
|
|
23
22
|
SigningKey = ecdsa.SigningKey.from_string
|
|
@@ -45,7 +44,7 @@ EX_TEST_PUBLIC = [
|
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
def int_to_hex(x):
|
|
48
|
-
return
|
|
47
|
+
return bytes(hex(x)[2:], encoding="utf-8")
|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
def parse_path(nstr, as_bytes=False):
|
|
@@ -123,11 +122,7 @@ class BIP32Key(object):
|
|
|
123
122
|
raise ValueError("unknown extended key version")
|
|
124
123
|
|
|
125
124
|
# Extract remaining fields
|
|
126
|
-
|
|
127
|
-
if type(raw[4]) == int:
|
|
128
|
-
depth = raw[4]
|
|
129
|
-
else:
|
|
130
|
-
depth = ord(raw[4])
|
|
125
|
+
depth = raw[4]
|
|
131
126
|
fpr = raw[5:9]
|
|
132
127
|
child = struct.unpack(">L", raw[9:13])[0]
|
|
133
128
|
chain = raw[13:45]
|
|
@@ -138,8 +133,7 @@ class BIP32Key(object):
|
|
|
138
133
|
secret = secret[1:]
|
|
139
134
|
else:
|
|
140
135
|
# Recover public curve point from compressed key
|
|
141
|
-
|
|
142
|
-
lsb = secret[0] & 1 if type(secret[0]) == int else ord(secret[0]) & 1
|
|
136
|
+
lsb = secret[0] & 1
|
|
143
137
|
x = int.from_bytes(secret[1:], "big")
|
|
144
138
|
ys = (x**3 + 7) % FIELD_ORDER # y^2 = x^3 + 7 mod p
|
|
145
139
|
y = sqrt_mod(ys, FIELD_ORDER)
|
|
@@ -167,10 +161,10 @@ class BIP32Key(object):
|
|
|
167
161
|
Create a public or private BIP32Key using key material and chain code.
|
|
168
162
|
|
|
169
163
|
secret This is the source material to generate the keypair, either a
|
|
170
|
-
32-byte
|
|
164
|
+
32-byte str representation of a private key, or the ECDSA
|
|
171
165
|
library object representing a public key.
|
|
172
166
|
|
|
173
|
-
chain This is a 32-byte
|
|
167
|
+
chain This is a 32-byte str representation of the chain code
|
|
174
168
|
|
|
175
169
|
depth Child depth; parent increments its own by one when assigning this
|
|
176
170
|
|
nectargraphenebase/bip38.py
CHANGED
|
@@ -6,7 +6,6 @@ from binascii import hexlify, unhexlify
|
|
|
6
6
|
|
|
7
7
|
from .account import PrivateKey
|
|
8
8
|
from .base58 import Base58, base58decode
|
|
9
|
-
from .py23 import py23_bytes, text_type
|
|
10
9
|
|
|
11
10
|
log = logging.getLogger(__name__)
|
|
12
11
|
|
|
@@ -62,16 +61,16 @@ def encrypt(privkey, passphrase):
|
|
|
62
61
|
|
|
63
62
|
privkeyhex = repr(privkey) # hex
|
|
64
63
|
addr = format(privkey.bitcoin.address, "BTC")
|
|
65
|
-
a =
|
|
64
|
+
a = bytes(addr, "ascii")
|
|
66
65
|
salt = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4]
|
|
67
66
|
if sys.version < "3":
|
|
68
|
-
if isinstance(passphrase,
|
|
67
|
+
if isinstance(passphrase, str):
|
|
69
68
|
passphrase = passphrase.encode("utf-8")
|
|
70
69
|
|
|
71
70
|
if SCRYPT_MODULE == "scrypt":
|
|
72
71
|
key = scrypt.hash(passphrase, salt, 16384, 8, 8)
|
|
73
72
|
elif SCRYPT_MODULE == "pylibscrypt":
|
|
74
|
-
key = scrypt.scrypt(
|
|
73
|
+
key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8)
|
|
75
74
|
else:
|
|
76
75
|
raise ValueError("No scrypt module loaded")
|
|
77
76
|
(derived_half1, derived_half2) = (key[:32], key[32:])
|
|
@@ -106,12 +105,12 @@ def decrypt(encrypted_privkey, passphrase):
|
|
|
106
105
|
salt = d[0:4]
|
|
107
106
|
d = d[4:-4]
|
|
108
107
|
if sys.version < "3":
|
|
109
|
-
if isinstance(passphrase,
|
|
108
|
+
if isinstance(passphrase, str):
|
|
110
109
|
passphrase = passphrase.encode("utf-8")
|
|
111
110
|
if SCRYPT_MODULE == "scrypt":
|
|
112
111
|
key = scrypt.hash(passphrase, salt, 16384, 8, 8)
|
|
113
112
|
elif SCRYPT_MODULE == "pylibscrypt":
|
|
114
|
-
key = scrypt.scrypt(
|
|
113
|
+
key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8)
|
|
115
114
|
else:
|
|
116
115
|
raise ValueError("No scrypt module loaded")
|
|
117
116
|
derivedhalf1 = key[0:32]
|
|
@@ -127,7 +126,7 @@ def decrypt(encrypted_privkey, passphrase):
|
|
|
127
126
|
""" Verify Salt """
|
|
128
127
|
privkey = PrivateKey(format(wif, "wif"))
|
|
129
128
|
addr = format(privkey.bitcoin.address, "BTC")
|
|
130
|
-
a =
|
|
129
|
+
a = bytes(addr, "ascii")
|
|
131
130
|
saltverify = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4]
|
|
132
131
|
if saltverify != salt:
|
|
133
132
|
raise SaltException("checksum verification failed! Password may be incorrect.")
|