hive-nectar 0.0.11__py3-none-any.whl → 0.1.0__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.11.dist-info → hive_nectar-0.1.0.dist-info}/METADATA +10 -11
- hive_nectar-0.1.0.dist-info/RECORD +88 -0
- nectar/__init__.py +1 -4
- nectar/account.py +791 -685
- nectar/amount.py +82 -21
- nectar/asset.py +1 -2
- nectar/block.py +34 -22
- nectar/blockchain.py +111 -143
- nectar/blockchaininstance.py +396 -247
- nectar/blockchainobject.py +33 -5
- nectar/cli.py +1058 -1349
- nectar/comment.py +313 -181
- nectar/community.py +39 -43
- nectar/constants.py +1 -14
- nectar/discussions.py +793 -139
- nectar/hive.py +137 -77
- nectar/hivesigner.py +106 -68
- nectar/imageuploader.py +33 -23
- nectar/instance.py +31 -79
- nectar/market.py +128 -264
- nectar/memo.py +40 -13
- nectar/message.py +23 -10
- nectar/nodelist.py +115 -81
- nectar/price.py +80 -61
- nectar/profile.py +6 -3
- nectar/rc.py +45 -25
- nectar/snapshot.py +285 -163
- nectar/storage.py +16 -5
- nectar/transactionbuilder.py +132 -41
- nectar/utils.py +37 -17
- nectar/version.py +1 -1
- nectar/vote.py +171 -30
- nectar/wallet.py +26 -19
- nectar/witness.py +153 -54
- nectarapi/graphenerpc.py +147 -133
- nectarapi/noderpc.py +12 -6
- nectarapi/rpcutils.py +12 -6
- nectarapi/version.py +1 -1
- nectarbase/ledgertransactions.py +24 -1
- nectarbase/objects.py +17 -6
- nectarbase/operations.py +160 -90
- nectarbase/signedtransactions.py +38 -2
- nectarbase/version.py +1 -1
- nectargraphenebase/account.py +295 -17
- nectargraphenebase/chains.py +0 -135
- nectargraphenebase/ecdsasig.py +152 -176
- nectargraphenebase/types.py +18 -4
- nectargraphenebase/unsignedtransactions.py +1 -1
- nectargraphenebase/version.py +1 -1
- hive_nectar-0.0.11.dist-info/RECORD +0 -91
- nectar/blurt.py +0 -562
- nectar/conveyor.py +0 -308
- nectar/steem.py +0 -581
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/licenses/LICENSE.txt +0 -0
nectargraphenebase/ecdsasig.py
CHANGED
|
@@ -2,55 +2,37 @@
|
|
|
2
2
|
import hashlib
|
|
3
3
|
import logging
|
|
4
4
|
import struct
|
|
5
|
-
import time
|
|
6
5
|
from binascii import hexlify
|
|
7
6
|
|
|
8
7
|
import ecdsa
|
|
8
|
+
from cryptography.hazmat.backends import default_backend
|
|
9
|
+
from cryptography.hazmat.primitives import hashes
|
|
10
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
11
|
+
from cryptography.hazmat.primitives.asymmetric.utils import (
|
|
12
|
+
Prehashed,
|
|
13
|
+
decode_dss_signature,
|
|
14
|
+
encode_dss_signature,
|
|
15
|
+
)
|
|
9
16
|
|
|
10
17
|
from .account import PrivateKey, PublicKey
|
|
11
18
|
|
|
12
19
|
log = logging.getLogger(__name__)
|
|
13
20
|
|
|
14
|
-
SECP256K1_MODULE = None
|
|
15
|
-
SECP256K1_AVAILABLE = False
|
|
16
|
-
CRYPTOGRAPHY_AVAILABLE = False
|
|
17
|
-
GMPY2_MODULE = False
|
|
18
|
-
if not SECP256K1_MODULE:
|
|
19
|
-
try:
|
|
20
|
-
import secp256k1prp as secp256k1
|
|
21
|
-
|
|
22
|
-
SECP256K1_MODULE = "secp256k1"
|
|
23
|
-
SECP256K1_AVAILABLE = True
|
|
24
|
-
except Exception:
|
|
25
|
-
try:
|
|
26
|
-
import secp256k1
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
try:
|
|
32
|
-
import cryptography
|
|
33
|
-
except ImportError:
|
|
34
|
-
SECP256K1_MODULE = "ecdsa"
|
|
35
|
-
else:
|
|
36
|
-
SECP256K1_MODULE = "cryptography"
|
|
37
|
-
CRYPTOGRAPHY_AVAILABLE = True
|
|
38
|
-
|
|
39
|
-
try:
|
|
40
|
-
from cryptography.hazmat.backends import default_backend
|
|
41
|
-
from cryptography.hazmat.primitives import hashes
|
|
42
|
-
from cryptography.hazmat.primitives.asymmetric import ec
|
|
43
|
-
from cryptography.hazmat.primitives.asymmetric.utils import (
|
|
44
|
-
decode_dss_signature,
|
|
45
|
-
encode_dss_signature,
|
|
46
|
-
)
|
|
47
|
-
except ImportError:
|
|
48
|
-
pass
|
|
22
|
+
def _is_canonical(sig):
|
|
23
|
+
"""
|
|
24
|
+
Return True if a 64-byte ECDSA signature (R || S) is in canonical form.
|
|
49
25
|
|
|
50
|
-
|
|
26
|
+
A canonical signature here means:
|
|
27
|
+
- Neither R nor S has its highest bit set (no negative integers when interpreted as signed big-endian).
|
|
28
|
+
- Neither R nor S has unnecessary leading zero bytes (no extra 0x00 padding before a non-negative highest byte).
|
|
51
29
|
|
|
30
|
+
Parameters:
|
|
31
|
+
sig (bytes or bytearray): 64-byte concatenation of R (32 bytes) followed by S (32 bytes).
|
|
52
32
|
|
|
53
|
-
|
|
33
|
+
Returns:
|
|
34
|
+
bool: True if signature is canonical, False otherwise.
|
|
35
|
+
"""
|
|
54
36
|
sig = bytearray(sig)
|
|
55
37
|
return (
|
|
56
38
|
not (int(sig[0]) & 0x80)
|
|
@@ -61,21 +43,62 @@ def _is_canonical(sig):
|
|
|
61
43
|
|
|
62
44
|
|
|
63
45
|
def compressedPubkey(pk):
|
|
64
|
-
|
|
46
|
+
"""
|
|
47
|
+
Return the 33-byte compressed secp256k1 public key for the given public-key object.
|
|
48
|
+
|
|
49
|
+
Accepts either an ecdsa.keys.VerifyingKey or an object exposing public_numbers().x and .y
|
|
50
|
+
(such as a cryptography EllipticCurvePublicKey). The output is 1 byte (0x02 if y is even,
|
|
51
|
+
0x03 if y is odd) followed by the 32-byte big-endian X coordinate.
|
|
52
|
+
|
|
53
|
+
Parameters:
|
|
54
|
+
pk: Public-key object (ecdsa.VerifyingKey or object with public_numbers().x and .y).
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
bytes: 33-byte compressed public key (prefix + 32-byte X).
|
|
58
|
+
"""
|
|
59
|
+
if isinstance(pk, ecdsa.keys.VerifyingKey):
|
|
65
60
|
order = ecdsa.SECP256k1.order
|
|
66
|
-
x = pk.public_numbers().x
|
|
67
|
-
y = pk.public_numbers().y
|
|
68
|
-
else:
|
|
69
|
-
order = pk.curve.generator.order()
|
|
70
61
|
p = pk.pubkey.point
|
|
71
62
|
x = p.x()
|
|
72
63
|
y = p.y()
|
|
64
|
+
else:
|
|
65
|
+
order = ecdsa.SECP256k1.order
|
|
66
|
+
x = pk.public_numbers().x
|
|
67
|
+
y = pk.public_numbers().y
|
|
73
68
|
x_str = ecdsa.util.number_to_string(x, order)
|
|
74
69
|
return bytes(chr(2 + (y & 1)), "ascii") + x_str
|
|
75
70
|
|
|
76
71
|
|
|
77
72
|
def recover_public_key(digest, signature, i, message=None):
|
|
78
|
-
"""
|
|
73
|
+
"""
|
|
74
|
+
Recover the secp256k1 public key from an ECDSA signature and message hash.
|
|
75
|
+
|
|
76
|
+
If `message` is provided the function will construct a cryptography EllipticCurvePublicKey
|
|
77
|
+
from the recovered point and verify the signature against the message; on success it
|
|
78
|
+
returns that cryptography public key. If `message` is None the function returns an
|
|
79
|
+
ecdsa.VerifyingKey built from the recovered point after verifying the signature
|
|
80
|
+
against the provided digest. If verification fails, returns None (when `message` is None)
|
|
81
|
+
or raises a verification exception (when `message` is provided).
|
|
82
|
+
|
|
83
|
+
Parameters:
|
|
84
|
+
digest (bytes): The message hash (big-endian) used when signing.
|
|
85
|
+
signature (bytes): 64-byte signature consisting of r||s (raw concatenation).
|
|
86
|
+
i (int): Recovery identifier (0..3) selecting which of the possible curve points to use.
|
|
87
|
+
message (bytes or str, optional): Original message to verify against; if a str it is
|
|
88
|
+
encoded as UTF-8. When provided the function returns a cryptography public key
|
|
89
|
+
and performs verification using ECDSA-SHA256.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey
|
|
93
|
+
when `message` is provided and verification succeeds;
|
|
94
|
+
ecdsa.keys.VerifyingKey
|
|
95
|
+
when `message` is None and digest-based verification succeeds;
|
|
96
|
+
None
|
|
97
|
+
when `message` is None and verification fails.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
cryptography.exceptions.InvalidSignature: If `message` is provided and signature verification fails.
|
|
101
|
+
"""
|
|
79
102
|
|
|
80
103
|
# See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily
|
|
81
104
|
curve = ecdsa.SECP256k1.curve
|
|
@@ -97,7 +120,7 @@ def recover_public_key(digest, signature, i, message=None):
|
|
|
97
120
|
# 1.6 Compute Q = r^-1(sR - eG)
|
|
98
121
|
Q = ecdsa.numbertheory.inverse_mod(r, order) * (s * R + (-e % order) * G)
|
|
99
122
|
|
|
100
|
-
if
|
|
123
|
+
if message is not None:
|
|
101
124
|
if not isinstance(message, bytes):
|
|
102
125
|
message = bytes(message, "utf-8")
|
|
103
126
|
sigder = encode_dss_signature(r, s)
|
|
@@ -128,18 +151,24 @@ def recover_public_key(digest, signature, i, message=None):
|
|
|
128
151
|
|
|
129
152
|
|
|
130
153
|
def recoverPubkeyParameter(message, digest, signature, pubkey):
|
|
131
|
-
"""
|
|
132
|
-
|
|
154
|
+
"""
|
|
155
|
+
Determine the ECDSA recovery parameter (0–3) that, when used with the given digest and 64-byte signature (R||S), reproduces the provided public key.
|
|
156
|
+
|
|
157
|
+
Attempts each recovery index i in 0..3, recovers a candidate public key, and compares its compressed form to the compressed form of the supplied pubkey. If a match is found returns the matching index; otherwise returns None.
|
|
158
|
+
|
|
159
|
+
Parameters that need clarification:
|
|
160
|
+
- message: the original message (will be encoded as UTF-8 if not bytes) and is used when recovering a cryptography public key variant.
|
|
161
|
+
- digest: the message hash used for recovery.
|
|
162
|
+
- signature: 64-byte R||S signature (bytes-like).
|
|
163
|
+
- pubkey: the expected public key to match; may be a cryptography/ec or ecdsa-like public key object.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
int: matching recovery parameter in 0..3, or None if no match is found.
|
|
133
167
|
"""
|
|
134
168
|
if not isinstance(message, bytes):
|
|
135
169
|
message = bytes(message, "utf-8")
|
|
136
170
|
for i in range(0, 4):
|
|
137
|
-
if
|
|
138
|
-
sig = pubkey.ecdsa_recoverable_deserialize(signature, i)
|
|
139
|
-
p = secp256k1.PublicKey(pubkey.ecdsa_recover(message, sig))
|
|
140
|
-
if p.serialize() == pubkey.serialize():
|
|
141
|
-
return i
|
|
142
|
-
elif SECP256K1_MODULE == "cryptography" and not isinstance(pubkey, PublicKey):
|
|
171
|
+
if not isinstance(pubkey, PublicKey):
|
|
143
172
|
p = recover_public_key(digest, signature, i, message)
|
|
144
173
|
p_comp = hexlify(compressedPubkey(p))
|
|
145
174
|
pubkey_comp = hexlify(compressedPubkey(pubkey))
|
|
@@ -159,102 +188,63 @@ def recoverPubkeyParameter(message, digest, signature, pubkey):
|
|
|
159
188
|
|
|
160
189
|
|
|
161
190
|
def sign_message(message, wif, hashfn=hashlib.sha256):
|
|
162
|
-
"""
|
|
191
|
+
"""
|
|
192
|
+
Sign a message using a private key in Wallet Import Format (WIF) and return a compact, canonical ECDSA signature.
|
|
193
|
+
|
|
194
|
+
Signs the provided message with secp256k1 ECDSA-SHA256 using the private key derived from the given WIF. The function repeats signing as needed until it produces a canonical 64-byte R||S signature (both R and S encoded as 32 bytes). It also computes the recovery parameter for the signature and encodes it into the first byte of the returned blob.
|
|
195
|
+
|
|
196
|
+
Parameters:
|
|
197
|
+
message (bytes or str): Message to sign. If a str is provided it is encoded as UTF-8 before hashing.
|
|
198
|
+
wif (str): Private key in Wallet Import Format (WIF).
|
|
199
|
+
hashfn (callable, optional): Hash function to apply to the message prior to recovery-parameter computation; defaults to hashlib.sha256.
|
|
163
200
|
|
|
164
|
-
:
|
|
201
|
+
Returns:
|
|
202
|
+
bytes: 65-byte compact signature: 1-byte recovery/version prefix (recovery parameter adjusted for compact/compressed form) followed by the 64-byte R||S sequence.
|
|
165
203
|
"""
|
|
166
204
|
|
|
167
205
|
if not isinstance(message, bytes):
|
|
168
206
|
message = bytes(message, "utf-8")
|
|
169
207
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if SECP256K1_MODULE == "secp256k1":
|
|
173
|
-
p = bytes(priv_key)
|
|
174
|
-
ndata = secp256k1.ffi.new("const int *ndata")
|
|
175
|
-
ndata[0] = 0
|
|
176
|
-
while True:
|
|
177
|
-
ndata[0] += 1
|
|
178
|
-
privkey = secp256k1.PrivateKey(p, raw=True)
|
|
179
|
-
sig = secp256k1.ffi.new("secp256k1_ecdsa_recoverable_signature *")
|
|
180
|
-
signed = secp256k1.lib.secp256k1_ecdsa_sign_recoverable(
|
|
181
|
-
privkey.ctx, sig, digest, privkey.private_key, secp256k1.ffi.NULL, ndata
|
|
182
|
-
)
|
|
183
|
-
if not signed == 1:
|
|
184
|
-
raise AssertionError()
|
|
185
|
-
signature, i = privkey.ecdsa_recoverable_serialize(sig)
|
|
186
|
-
if _is_canonical(signature):
|
|
187
|
-
i += 4 # compressed
|
|
188
|
-
i += 27 # compact
|
|
189
|
-
break
|
|
190
|
-
elif SECP256K1_MODULE == "cryptography":
|
|
191
|
-
cnt = 0
|
|
192
|
-
private_key = ec.derive_private_key(
|
|
193
|
-
int(repr(priv_key), 16), ec.SECP256K1(), default_backend()
|
|
194
|
-
)
|
|
195
|
-
public_key = private_key.public_key()
|
|
196
|
-
while True:
|
|
197
|
-
cnt += 1
|
|
198
|
-
if not cnt % 20:
|
|
199
|
-
log.info("Still searching for a canonical signature. Tried %d times already!" % cnt)
|
|
200
|
-
order = ecdsa.SECP256k1.order
|
|
201
|
-
sigder = private_key.sign(message, ec.ECDSA(hashes.SHA256()))
|
|
202
|
-
r, s = decode_dss_signature(sigder)
|
|
203
|
-
signature = ecdsa.util.sigencode_string(r, s, order)
|
|
204
|
-
# Make sure signature is canonical!
|
|
205
|
-
#
|
|
206
|
-
sigder = bytearray(sigder)
|
|
207
|
-
lenR = sigder[3]
|
|
208
|
-
lenS = sigder[5 + lenR]
|
|
209
|
-
if lenR == 32 and lenS == 32:
|
|
210
|
-
# Derive the recovery parameter
|
|
211
|
-
#
|
|
212
|
-
i = recoverPubkeyParameter(message, digest, signature, public_key)
|
|
213
|
-
i += 4 # compressed
|
|
214
|
-
i += 27 # compact
|
|
215
|
-
break
|
|
216
|
-
else: # pragma: no branch # pragma: no cover
|
|
217
|
-
cnt = 0
|
|
218
|
-
p = bytes(priv_key)
|
|
219
|
-
sk = ecdsa.SigningKey.from_string(p, curve=ecdsa.SECP256k1)
|
|
220
|
-
while 1:
|
|
221
|
-
cnt += 1
|
|
222
|
-
if not cnt % 20:
|
|
223
|
-
log.info("Still searching for a canonical signature. Tried %d times already!" % cnt)
|
|
224
|
-
|
|
225
|
-
# Deterministic k
|
|
226
|
-
#
|
|
227
|
-
k = ecdsa.rfc6979.generate_k(
|
|
228
|
-
sk.curve.generator.order(),
|
|
229
|
-
sk.privkey.secret_multiplier,
|
|
230
|
-
hashlib.sha256,
|
|
231
|
-
hashlib.sha256(
|
|
232
|
-
digest
|
|
233
|
-
+ struct.pack("d", time.time()) # use the local time to randomize the signature
|
|
234
|
-
).digest(),
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
# Sign message
|
|
238
|
-
#
|
|
239
|
-
sigder = sk.sign_digest(digest, sigencode=ecdsa.util.sigencode_der, k=k)
|
|
208
|
+
# Detect if message is already a digest
|
|
209
|
+
prehashed = len(message) == hashfn().digest_size
|
|
240
210
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
211
|
+
if prehashed:
|
|
212
|
+
digest = message
|
|
213
|
+
message_for_signing = message # the digest
|
|
214
|
+
algorithm_for_signing = ec.ECDSA(Prehashed(hashes.SHA256()))
|
|
215
|
+
message_for_recovery = None
|
|
216
|
+
else:
|
|
217
|
+
digest = hashfn(message).digest()
|
|
218
|
+
message_for_signing = message
|
|
219
|
+
algorithm_for_signing = ec.ECDSA(hashes.SHA256())
|
|
220
|
+
message_for_recovery = message
|
|
245
221
|
|
|
246
|
-
|
|
222
|
+
priv_key = PrivateKey(wif)
|
|
223
|
+
cnt = 0
|
|
224
|
+
private_key = ec.derive_private_key(int(repr(priv_key), 16), ec.SECP256K1(), default_backend())
|
|
225
|
+
public_key = private_key.public_key()
|
|
226
|
+
while True:
|
|
227
|
+
cnt += 1
|
|
228
|
+
if not cnt % 20:
|
|
229
|
+
log.info("Still searching for a canonical signature. Tried %d times already!" % cnt)
|
|
230
|
+
order = ecdsa.SECP256k1.order
|
|
231
|
+
sigder = private_key.sign(message_for_signing, algorithm_for_signing)
|
|
232
|
+
r, s = decode_dss_signature(sigder)
|
|
233
|
+
signature = ecdsa.util.sigencode_string(r, s, order)
|
|
234
|
+
# Make sure signature is canonical!
|
|
235
|
+
#
|
|
236
|
+
sigder = bytearray(sigder)
|
|
237
|
+
lenR = sigder[3]
|
|
238
|
+
lenS = sigder[5 + lenR]
|
|
239
|
+
if lenR == 32 and lenS == 32 and _is_canonical(signature):
|
|
240
|
+
# Derive the recovery parameter
|
|
247
241
|
#
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
i = recoverPubkeyParameter(message, digest, signature, sk.get_verifying_key())
|
|
255
|
-
i += 4 # compressed
|
|
256
|
-
i += 27 # compact
|
|
257
|
-
break
|
|
242
|
+
i = recoverPubkeyParameter(message_for_recovery, digest, signature, public_key)
|
|
243
|
+
if i is None:
|
|
244
|
+
continue
|
|
245
|
+
i += 4 # compressed
|
|
246
|
+
i += 27 # compact
|
|
247
|
+
break
|
|
258
248
|
|
|
259
249
|
# pack signature
|
|
260
250
|
#
|
|
@@ -265,6 +255,23 @@ def sign_message(message, wif, hashfn=hashlib.sha256):
|
|
|
265
255
|
|
|
266
256
|
|
|
267
257
|
def verify_message(message, signature, hashfn=hashlib.sha256, recover_parameter=None):
|
|
258
|
+
"""
|
|
259
|
+
Verify an ECDSA secp256k1 signature against a message and return the signer's compressed public key.
|
|
260
|
+
|
|
261
|
+
Parameters:
|
|
262
|
+
message (bytes or str): The message to verify. If a str, it will be UTF-8 encoded.
|
|
263
|
+
signature (bytes or str): 65-byte compact signature where the first byte encodes the recovery parameter/version and the remaining 64 bytes are R||S. If a str, it will be UTF-8 encoded.
|
|
264
|
+
hashfn (callable): Hash function constructor used to compute the digest of the message (default: hashlib.sha256).
|
|
265
|
+
recover_parameter (int, optional): Explicit recovery parameter (0–3). If omitted, it is extracted from the signature's first byte.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
bytes: The 33-byte compressed public key of the recovered signer on successful verification.
|
|
269
|
+
|
|
270
|
+
Notes:
|
|
271
|
+
- The function computes the digest of `message` with `hashfn`, recovers the public key using the recovery parameter, converts the 64-byte R||S into DER form, and verifies the signature with ECDSA-SHA256.
|
|
272
|
+
- If the recovery parameter cannot be determined from the signature, None is returned.
|
|
273
|
+
- Cryptographic verification errors (e.g., invalid signature) will propagate as raised exceptions.
|
|
274
|
+
"""
|
|
268
275
|
if not isinstance(message, bytes):
|
|
269
276
|
message = bytes(message, "utf-8")
|
|
270
277
|
if not isinstance(signature, bytes):
|
|
@@ -281,41 +288,10 @@ def verify_message(message, signature, hashfn=hashlib.sha256, recover_parameter=
|
|
|
281
288
|
log.info("Could not recover parameter")
|
|
282
289
|
return None
|
|
283
290
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
# Recover PublicKey
|
|
291
|
-
verifyPub = secp256k1.PublicKey(pub.ecdsa_recover(message, sig))
|
|
292
|
-
# Convert recoverable sig to normal sig
|
|
293
|
-
normalSig = verifyPub.ecdsa_recoverable_convert(sig)
|
|
294
|
-
# Verify
|
|
295
|
-
verifyPub.ecdsa_verify(message, normalSig)
|
|
296
|
-
phex = verifyPub.serialize(compressed=True)
|
|
297
|
-
elif SECP256K1_MODULE == "cryptography":
|
|
298
|
-
p = recover_public_key(digest, sig, recover_parameter, message)
|
|
299
|
-
order = ecdsa.SECP256k1.order
|
|
300
|
-
r, s = ecdsa.util.sigdecode_string(sig, order)
|
|
301
|
-
sigder = encode_dss_signature(r, s)
|
|
302
|
-
p.verify(sigder, message, ec.ECDSA(hashes.SHA256()))
|
|
303
|
-
phex = compressedPubkey(p)
|
|
304
|
-
else: # pragma: no branch # pragma: no cover
|
|
305
|
-
p = recover_public_key(digest, sig, recover_parameter)
|
|
306
|
-
# Will throw an exception of not valid
|
|
307
|
-
p.verify_digest(sig, digest, sigdecode=ecdsa.util.sigdecode_string)
|
|
308
|
-
phex = compressedPubkey(p)
|
|
309
|
-
|
|
291
|
+
p = recover_public_key(digest, sig, recover_parameter, message)
|
|
292
|
+
order = ecdsa.SECP256k1.order
|
|
293
|
+
r, s = ecdsa.util.sigdecode_string(sig, order)
|
|
294
|
+
sigder = encode_dss_signature(r, s)
|
|
295
|
+
p.verify(sigder, digest, ec.ECDSA(Prehashed(hashes.SHA256())))
|
|
296
|
+
phex = compressedPubkey(p)
|
|
310
297
|
return phex
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
def tweakaddPubkey(pk, digest256, SECP256K1_MODULE=SECP256K1_MODULE):
|
|
314
|
-
if SECP256K1_MODULE == "secp256k1":
|
|
315
|
-
tmp_key = secp256k1.PublicKey(pubkey=bytes(pk), raw=True)
|
|
316
|
-
new_key = tmp_key.tweak_add(digest256) # <-- add
|
|
317
|
-
raw_key = hexlify(new_key.serialize()).decode("ascii")
|
|
318
|
-
else:
|
|
319
|
-
raise Exception("Must have secp256k1 for `tweak_add`")
|
|
320
|
-
# raw_key = ecmult(pk, 1, digest256, SECP256K1_MODULE)
|
|
321
|
-
return PublicKey(raw_key, prefix=pk.prefix)
|
nectargraphenebase/types.py
CHANGED
|
@@ -3,9 +3,11 @@ import json
|
|
|
3
3
|
import struct
|
|
4
4
|
import time
|
|
5
5
|
from binascii import hexlify, unhexlify
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
# Move calendar import to avoid circular import issue in Python 3.13
|
|
7
8
|
from datetime import datetime
|
|
8
9
|
|
|
10
|
+
# Import calendar only when needed to avoid circular imports
|
|
9
11
|
timeformat = "%Y-%m-%dT%H:%M:%S%Z"
|
|
10
12
|
|
|
11
13
|
|
|
@@ -265,11 +267,23 @@ class PointInTime(object):
|
|
|
265
267
|
self.data = d
|
|
266
268
|
|
|
267
269
|
def __bytes__(self):
|
|
268
|
-
"""
|
|
270
|
+
"""
|
|
271
|
+
Return a 4-byte little-endian Unix timestamp for the stored point-in-time.
|
|
272
|
+
|
|
273
|
+
If the instance holds a datetime, it is converted to a POSIX timestamp using UTC. If it holds a string, the string is parsed (with the module-level `timeformat` and "UTC" appended) and converted to a POSIX timestamp. The timestamp is encoded as a signed 32-bit little-endian integer when negative, otherwise as an unsigned 32-bit little-endian integer.
|
|
274
|
+
"""
|
|
275
|
+
# Import lazily to avoid import-time cycles
|
|
276
|
+
from calendar import timegm
|
|
277
|
+
|
|
269
278
|
if isinstance(self.data, datetime):
|
|
270
|
-
|
|
279
|
+
# Use UTC, not local time
|
|
280
|
+
unixtime = timegm(self.data.utctimetuple())
|
|
271
281
|
else:
|
|
272
|
-
|
|
282
|
+
s = self.data
|
|
283
|
+
# Accept ISO8601 'Z' suffix
|
|
284
|
+
if isinstance(s, str) and s.endswith("Z"):
|
|
285
|
+
s = s[:-1]
|
|
286
|
+
unixtime = timegm(time.strptime((s + "UTC"), timeformat))
|
|
273
287
|
if unixtime < 0:
|
|
274
288
|
return struct.pack("<i", unixtime)
|
|
275
289
|
return struct.pack("<I", unixtime)
|
|
@@ -104,7 +104,7 @@ class Unsigned_Transaction(GrapheneObjectASN1):
|
|
|
104
104
|
else:
|
|
105
105
|
if len(args) == 1 and len(kwargs) == 0:
|
|
106
106
|
kwargs = args[0]
|
|
107
|
-
|
|
107
|
+
kwargs.pop("prefix", "STM")
|
|
108
108
|
if "extensions" not in kwargs:
|
|
109
109
|
kwargs["extensions"] = Set([])
|
|
110
110
|
elif not kwargs.get("extensions"):
|
nectargraphenebase/version.py
CHANGED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
nectar/__init__.py,sha256=ykNGWDHaB3B2l22VK3HF8jpXXUf78tb6uyUw_Gnq6Kc,522
|
|
2
|
-
nectar/account.py,sha256=R__rmM8RwgKlO0-wwCo3jWecjz7WP6BxJEtLLVDhOXg,172221
|
|
3
|
-
nectar/amount.py,sha256=m5u0ixthz-XY69yEhla8yu6iKQACOcNtpKlK1NY__v0,18057
|
|
4
|
-
nectar/asciichart.py,sha256=DwPyZAqne6o9L_PPRtlw6Xj0QdOZ-aId1lpOnmbyc6Q,8828
|
|
5
|
-
nectar/asset.py,sha256=spGsJmlVQeZ6-oYhcwmQKsI3gpGmrpCzimYO1Qv4MtA,2725
|
|
6
|
-
nectar/block.py,sha256=6UIKzeKaPBOE2kRopTbnT0wAyz0g_FOJ4EuTZWMKA0Y,16050
|
|
7
|
-
nectar/blockchain.py,sha256=jLJ6Lsw35nwamzhcSXnU1UOtrEacBlDIINXUnYQS_P0,49101
|
|
8
|
-
nectar/blockchaininstance.py,sha256=dYGvI5JpNNHP6XOttIX3QR12fkuBCqek1O5DgDFdZwQ,93159
|
|
9
|
-
nectar/blockchainobject.py,sha256=bgfEjTGjFaUputmfNCD1jRTqk1d94tbnujYGkNshsWs,6984
|
|
10
|
-
nectar/blurt.py,sha256=2qRZf9-k5vonJEd-e8Dnpb09GP5bRvP5fE_MItSpCZw,23013
|
|
11
|
-
nectar/cli.py,sha256=zQHYUbqEW-TPvEsYuILrYxuynhGJHLSWJiez3mxcKsg,227615
|
|
12
|
-
nectar/comment.py,sha256=yL1JdFTEl6a47homQZHHSmOfeRzdtw1BVAFTTp5-yRo,46664
|
|
13
|
-
nectar/community.py,sha256=EUCPSgHDWQIeFvO4zHOIl15dcfmEHN6VU2m1jHKVWxo,31821
|
|
14
|
-
nectar/constants.py,sha256=lrspBwCz9BE0YZY10DMS98oPwwxgmI0LzFdlQ7v53Ig,4974
|
|
15
|
-
nectar/conveyor.py,sha256=atw49yhCEPEGIVdcSL0T0Y0_DY-vp6MCWOm2umBbgXo,11203
|
|
16
|
-
nectar/discussions.py,sha256=n-4GnYvnDc5AwFdUHSA9wTfdCmLWHb9h06U4vWq05q4,66439
|
|
17
|
-
nectar/exceptions.py,sha256=AKA75cDNnpioZPe2XcNWvyAVPRLcHBfPyBwjYVFOJC0,2884
|
|
18
|
-
nectar/hive.py,sha256=SjTTbLt_wWshEbaJFxjAPYT38wTa1i5RgBNepdeoAcw,22197
|
|
19
|
-
nectar/hivesigner.py,sha256=DpHMdGhsy7Kh8gfcEAeHtFHEXOVTr0AqeZBXxgQNzIQ,14010
|
|
20
|
-
nectar/imageuploader.py,sha256=dR6bd-CtHcKReLHuWsF_XmE_uJfqWxyWbU6lLhI2iM8,2647
|
|
21
|
-
nectar/instance.py,sha256=oUAycW1q5ynM3M4O9a0drgY7e8UBExTj69aMxrOjxwg,3905
|
|
22
|
-
nectar/market.py,sha256=mlKKsq6DQ4WCLaqNnuuwbJM4qUiejy5pGdXIPKK2Sug,41972
|
|
23
|
-
nectar/memo.py,sha256=lTIuPrX-kPynOa-9q6kJHRzb9BfJjSf0kdpipwEXnY8,17777
|
|
24
|
-
nectar/message.py,sha256=lVGaydsxh8oMTS90khho3DtqxhzgIrt4NmjxwyP0X3k,13019
|
|
25
|
-
nectar/nodelist.py,sha256=wNSFJyqaRL4dh_OKXui4jVXoGIIIgVBtB8K3bPCfNfY,18659
|
|
26
|
-
nectar/price.py,sha256=Rv-ffhkyN1c-tl6QTGWvhrdqTQNHbE1rcUzTi21t4Tc,21052
|
|
27
|
-
nectar/profile.py,sha256=t-pqC2DZxzvTV2XLU6iZWT1NdHuk77A_iiisbA0QIOM,1921
|
|
28
|
-
nectar/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
nectar/rc.py,sha256=XRscyDqXiw03cBDznUPafEdhB64jxkrn6pH1kvoLcW4,12773
|
|
30
|
-
nectar/snapshot.py,sha256=_5hsrmJDpPoWTYtQGZ2grMMuuGBInOGS0ip9gv5-RJo,31696
|
|
31
|
-
nectar/steem.py,sha256=z7yrhWbnkVF4PzlpvG-JO4tqEFYZZ5dnqC5YMchnWFY,23859
|
|
32
|
-
nectar/storage.py,sha256=efmvfBD102ye8TTCRhMUkegVNmASFAYCfV9qqSFSSJM,1844
|
|
33
|
-
nectar/transactionbuilder.py,sha256=S14zLfbyvrMCnTOAAOUf6gqvU3aEyPDRZqEbYPYl4DM,25886
|
|
34
|
-
nectar/utils.py,sha256=8mlRkx133yeZPkYgDUKLK79PVLRYIvJV1qts_V3pLjY,18884
|
|
35
|
-
nectar/version.py,sha256=9aPmBLTmfKZ2C3bmweqIUOMrBvbWXo3Nvh-mGPpVVyI,77
|
|
36
|
-
nectar/vote.py,sha256=-FHyrF79K4zmvH_IYl-2ImrX6pUhSs0dS7wCMeJAYh8,20085
|
|
37
|
-
nectar/wallet.py,sha256=mbFNDbzo8PbcN7iYlVwwFIp9e4zCFuS4cYoWeepF1jY,16232
|
|
38
|
-
nectar/witness.py,sha256=88XYjhTRNhyu9hfIG0sm3Pg1hC9eooo3HhW5EhcaYps,23600
|
|
39
|
-
nectarapi/__init__.py,sha256=eyiQRdZ8agc_qi9fr8sAvYPfpStEpTN06yBWFxkCTJk,176
|
|
40
|
-
nectarapi/exceptions.py,sha256=gDaDFy1QcFkXrpOadduZ9bFWanHZpaiZRK_AOJZ-AWo,2044
|
|
41
|
-
nectarapi/graphenerpc.py,sha256=7woRA4CmuwqYrJU9E4LV3UdxaANHzIrKuWZPaxTcJnw,22642
|
|
42
|
-
nectarapi/node.py,sha256=mjK-fMFJ2icDaOUBoiUuDU-beo3aQK0HGwt0l0pC0YQ,5456
|
|
43
|
-
nectarapi/noderpc.py,sha256=FxJz1KbjU6FbNdyp7ovOSZ8TbmD_xqQclKjeBP42Jls,10093
|
|
44
|
-
nectarapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
-
nectarapi/rpcutils.py,sha256=0nKCrEeNHFSEU3AjaOGNh-2pjc8qw4mRA9lCrBkP1FQ,2910
|
|
46
|
-
nectarapi/version.py,sha256=9aPmBLTmfKZ2C3bmweqIUOMrBvbWXo3Nvh-mGPpVVyI,77
|
|
47
|
-
nectarbase/__init__.py,sha256=O11coqB-Woq_yp946kA1b8hzqSdDcK9j9gwenx7d6JE,253
|
|
48
|
-
nectarbase/ledgertransactions.py,sha256=0N1EHIZJdp-pVXmd0PgIVwhCFUtPRky4Pt9RQdP4f2A,2488
|
|
49
|
-
nectarbase/memo.py,sha256=Ix5Uhan7x2rz54_QMSQ-Z5rZz-FqvR3i13H3cGEnPIY,7496
|
|
50
|
-
nectarbase/objects.py,sha256=zDDLTz0eaenBDiZf_T1E9nXehU3xTs0aZyrrttkGKSk,14813
|
|
51
|
-
nectarbase/objecttypes.py,sha256=zrKBFwoUJXvWDSn8RugWioKqf7TS7dY0EEXVAZv_-K0,690
|
|
52
|
-
nectarbase/operationids.py,sha256=wpKltPFlInpueyvLl3XCI2fjP9ziIs4MStoIj2mbPfQ,3645
|
|
53
|
-
nectarbase/operations.py,sha256=Ik87L6_rzptfCy4eeOX--9669mcrZ6SVxQe7jrmHd5U,47419
|
|
54
|
-
nectarbase/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
-
nectarbase/signedtransactions.py,sha256=r-MRnEQDnx6U6XFPcM3hPXiDZvU6sQVx4Vv_0nZF7fs,1792
|
|
56
|
-
nectarbase/transactions.py,sha256=D7TK4Pkxr1N7p0Yh2bxvdXpOuEYpLl2tWK84Pj_93c0,319
|
|
57
|
-
nectarbase/version.py,sha256=9aPmBLTmfKZ2C3bmweqIUOMrBvbWXo3Nvh-mGPpVVyI,77
|
|
58
|
-
nectargrapheneapi/__init__.py,sha256=_Gxdt_qaQQwwYABHEFBuf4tMh93ItIa3HPBH9nk1PTw,151
|
|
59
|
-
nectargrapheneapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
|
-
nectargraphenebase/__init__.py,sha256=66IxULO3eMKcx-nRDFDLz0YfEvXCkty08xjt9M1WgyY,577
|
|
61
|
-
nectargraphenebase/account.py,sha256=tjEbiqkFmTs0AZAaCRke3OzopHKV4i3deryCAR54xek,28984
|
|
62
|
-
nectargraphenebase/aes.py,sha256=BywHJR8F7n2IBXhBmXqyc61DlVXcJ_QIE9qkubFdX2M,1578
|
|
63
|
-
nectargraphenebase/base58.py,sha256=7ilcjbwV3YGDL3a5MCilR03P-p5kNVafrmsRsftr0d8,5410
|
|
64
|
-
nectargraphenebase/bip32.py,sha256=UjqgbBvvdya3gQRD73ccdfEQL4brxs4DWhM9vTvRMpc,16023
|
|
65
|
-
nectargraphenebase/bip38.py,sha256=EIlaNMvDHOhb4GKTcjX_8X8FWIG45pP3VTyoZD70Mh4,4458
|
|
66
|
-
nectargraphenebase/chains.py,sha256=JhaqY8qZaK-6OYf72RLVNxJtrc6yZtYxJm8p9U-i338,6185
|
|
67
|
-
nectargraphenebase/dictionary.py,sha256=Fooynl3XWE9ALy31jsVNb9CEHZh5N8TeJUAZJvqslnY,360748
|
|
68
|
-
nectargraphenebase/ecdsasig.py,sha256=Etv1C83GpkhGFgWrHoB7WR4T_Ygh4SZ-6Qlnc9XCYHY,12129
|
|
69
|
-
nectargraphenebase/objects.py,sha256=twOADiBOSXlZNu6y1TrdDw135zWQeIsfn12xRl5m6Fw,3896
|
|
70
|
-
nectargraphenebase/objecttypes.py,sha256=8YkRyxtd1hNZ06XvyHBRA5PatVeTd8XCFQmW_2p8MGk,160
|
|
71
|
-
nectargraphenebase/operationids.py,sha256=TLXB8FovmDwC39PNAR8OaW-NWyo1gFH0zE4ibShcMiI,65
|
|
72
|
-
nectargraphenebase/operations.py,sha256=Lp25CSjHUttzWLbcgYLeccFtPHqip8uo9iTqLKKm40U,690
|
|
73
|
-
nectargraphenebase/prefix.py,sha256=tpX2_uz5lPveUoGbmXC4zsrG-5QsaVbIGIFPWJvYRbg,280
|
|
74
|
-
nectargraphenebase/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
nectargraphenebase/signedtransactions.py,sha256=rhFEQDNcOau08qnNAf_3UxJDXtIpi5Y8tOFDXZK1bPw,7119
|
|
76
|
-
nectargraphenebase/types.py,sha256=nxkpR4N1DOZwIwDSVQrMxp8VZVKVjYdiLvPv0sX65jU,9439
|
|
77
|
-
nectargraphenebase/unsignedtransactions.py,sha256=6WLZCSVC0vCa7VVBt39TQl1vW-GAF2khkF0DLIgZG-s,9247
|
|
78
|
-
nectargraphenebase/version.py,sha256=9aPmBLTmfKZ2C3bmweqIUOMrBvbWXo3Nvh-mGPpVVyI,77
|
|
79
|
-
nectarstorage/__init__.py,sha256=nEM9OMoHqHPS6IoV_JzVyxPRORz0DCeS7Yv-MwjmWoQ,1772
|
|
80
|
-
nectarstorage/base.py,sha256=h7Oca1_RaJw39P1I_xXRKup016pS8zCLOs3e4IHKKdE,9734
|
|
81
|
-
nectarstorage/exceptions.py,sha256=0erk_d0Ejia9td_Ke7XFBl17H1BxbM42gFpkej8EbV0,421
|
|
82
|
-
nectarstorage/interfaces.py,sha256=WK2YR2mKUk1Qts50ZYLd407gECywA02A8iWr_p0KfCw,6786
|
|
83
|
-
nectarstorage/masterpassword.py,sha256=xOAOZvVfIctfGiwIed_XpKnWcGDla95qp8osTLyYYCk,8654
|
|
84
|
-
nectarstorage/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
|
-
nectarstorage/ram.py,sha256=Cy6JbMrlgcEG673_KqfyaofhAdJR-luRKTedj3qTZEE,1034
|
|
86
|
-
nectarstorage/sqlite.py,sha256=ZKJxPL0AZjJIlwjxCEh6GGcjQzlBPuWs6tj40oPZz3M,10635
|
|
87
|
-
hive_nectar-0.0.11.dist-info/METADATA,sha256=GcTDdw97TsV6-QWUjcs18n66gVdpPgqgf3-0RpK4BXg,6163
|
|
88
|
-
hive_nectar-0.0.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
89
|
-
hive_nectar-0.0.11.dist-info/entry_points.txt,sha256=DbqiJb5fFpQvGZ0ojvc2w3dXZitTg6FPz09CobKq4m8,47
|
|
90
|
-
hive_nectar-0.0.11.dist-info/licenses/LICENSE.txt,sha256=WjJRNR4r7FuLEO2BTBLGa05T7bBecGGgH47NgKsSY0E,1158
|
|
91
|
-
hive_nectar-0.0.11.dist-info/RECORD,,
|