Coverage for src/lib/cash.py: 73%
77 statements
« prev ^ index » next coverage.py v7.2.7, created at 2025-03-09 17:37 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2025-03-09 17:37 +0000
2from random import randint
3from cryptography.hazmat.primitives import hashes
6class Cash():
7 data: str
8 bits: int
9 proof: str
10 nonce: int
12 def __init__(self, data: str, bits: int):
13 self.data = data.encode()
14 self.bits = bits
15 self.proof = None
16 self.nonce = None
18 def __str__(self): # pragma: no cover
19 return 'Cash(b={})'.format(self.bits)
21 def __repr__(self): # pragma: no cover
22 return self.__str__()
24 def mine(self) -> int:
25 self.nonce = randint(0, 100000000)
27 cycle = 0
28 while True:
29 cycle += 1
31 input_data = b'FC:' + str(self.bits).encode() + b':' + self.data + b':' + str(self.nonce).encode()
33 # print(input_data)
34 # print(input_data.hex())
36 hasher = hashes.Hash(hashes.SHA256())
37 hasher.update(input_data)
38 digest = hasher.finalize()
39 # print('digest: {} {}'.format(self.nonce, digest.hex()))
41 found_bits = 0
42 for c in digest:
43 if c & 0b10000000:
44 break
45 if c & 0b01000000:
46 found_bits += 1
47 break
48 if c & 0b00100000:
49 found_bits += 2
50 break
51 if c & 0b00010000:
52 found_bits += 3
53 break
54 if c & 0b00001000:
55 found_bits += 4
56 break
57 if c & 0b00000100:
58 found_bits += 5
59 break
60 if c & 0b00000010:
61 found_bits += 6
62 break
63 if c & 0b00000001:
64 found_bits += 7
65 break
66 if c == 0:
67 found_bits += 8
69 if found_bits >= self.bits:
70 break
72 if found_bits >= self.bits:
73 self.proof = digest.hex()
74 break
76 self.nonce += 1
78 return cycle
80 def verify(self, proof: str, nonce: int) -> bool:
81 if len(proof) != 64:
82 # print('verify, invalid length')
83 return False
85 full_bytes = self.bits % 4 == 0
86 if full_bytes:
87 if not proof.startswith('0' * (self.bits // 4)):
88 # print('verify, startswith wrong')
89 return False
90 else:
91 found_bits = 0
92 for c in bytes.fromhex(proof):
93 pos = bin(c)[2:].zfill(8).find('1')
94 if pos == -1:
95 found_bits += 8
96 continue
98 found_bits += pos
99 break
101 # print('verify, found_bits: {} {}'.format(found_bits, self.bits))
102 if found_bits < self.bits:
103 # print('verify, found_bits wrong')
104 return False
106 input_data = b'FC:' + str(self.bits).encode() + b':' + self.data + b':' + str(nonce).encode()
108 hasher = hashes.Hash(hashes.SHA256())
109 hasher.update(input_data)
110 digest = hasher.finalize()
112 return digest.hex() == proof