Newer
Older
import CellFrame
from CellFrame.Network import Net
from CellFrame.Common import DatumEmission
from DAP import Crypto
from DAP.Crypto import Cert, Sign
from CellFrame.Chain import Mempool
from CellFrame.Consensus import DAG,Block
from CellFrame.Common import Datum, DatumTx, TxOut, TxIn, TxToken, TxSig, TxOutCondSubtypeSrvStakeLock, TxInCond,TxOutExt
from DAP.Crypto import HashFast
from DAP.Core import logIt
from datetime import datetime
import hashlib
from pycfhelpers.helpers import json_dump, find_tx_out
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
class TSD:
TYPE_UNKNOWN = 0x0000
TYPE_TIMESTAMP = 0x0001
TYPE_ADDRESS = 0x0002
TYPE_VALUE = 0x0003
TYPE_CONTRACT = 0x0004
TYPE_NET_ID = 0x0005
TYPE_BLOCK_NUM = 0x0006
TYPE_TOKEN_SYM = 0x0007
TYPE_OUTER_TX_HASH = 0x0008
TYPE_SOURCE = 0x0009
TYPE_SOURCE_SUBTYPE = 0x000A
TYPE_DATA = 0x000B
TYPE_SENDER = 0x000C
TYPE_TOKEN_ADDRESS = 0x000D
TYPE_SIGNATURS = 0x000E
TYPE_UNIQUE_ID = 0x000F
TYPE_BASE_TX_HASH = 0x0010
TYPE_EMISSION_CENTER_UID = 0x0011
TYPE_EMISSION_CENTER_VER = 0x0012
class CellframeEmission:
def __init__(self, datum):
self.datum = datum
self.hash = str(self.datum.hash)
m = hashlib.sha256()
addr = datum.getTSD(TSD.TYPE_ADDRESS)
btx = datum.getTSD(TSD.TYPE_BASE_TX_HASH)
otx = datum.getTSD(TSD.TYPE_OUTER_TX_HASH)
src = datum.getTSD(TSD.TYPE_SOURCE)
stp = datum.getTSD(TSD.TYPE_SOURCE_SUBTYPE)
ts = datum.getTSD(TSD.TYPE_TIMESTAMP)
data = datum.getTSD(TSD.TYPE_DATA)
uid = datum.getTSD(TSD.TYPE_UNIQUE_ID)
m.update(str(addr).encode("utf-8"))
m.update(str(btx).encode("utf-8"))
m.update(str(otx).encode("utf-8"))
m.update(str(src).encode("utf-8"))
m.update(str(stp).encode("utf-8"))
m.update(str(data).encode("utf-8"))
m.update(str(ts).encode("utf-8"))
m.update(str(uid).encode("utf-8"))
m.update(str(data).encode("utf-8"))
self.uid = m.hexdigest()
def getTSD(self, type):
tsd = self.datum.getTSD(type)
if tsd:
try:
return tsd.decode("utf-8")
except:
pass
return None
def setTSD(self, type, data):
self.datum.addTSD(type, data)
#if datum not base-tx - exception
class CellframeBaseTransactionDatum:
def __init__(self, datum, net, block=None):
self.block = block
self.datum = datum
self.hash = str(datum.hash)
self.created = datum.dateCreated
self.net = net
#base tx : has txToken item
if not self.tx_token():
raise RuntimeError("Datum {} not base tx".format(self.datum))
self.to_address = str(self.tx_out().addr)
self.amount = self.tx_out().value
self.emission_hash = str(self.tx_token().tokenEmissionHash)
self.emission_ = None
def tx_out(self):
try:
return next(filter(lambda x: isinstance(x, TxOut), self.datum.getItems()))
except:
return None
def tx_in(self):
try:
return next(filter(lambda x: isinstance(x, TxIn), self.datum.getItems()))
except:
return None
def tx_token(self):
try:
return next(filter(lambda x: isinstance(x, TxToken), self.datum.getItems()))
except:
return None
def tx_sig(self):
try:
return next(filter(lambda x: isinstance(x, TxSig), self.datum.getItems()))
except:
return None
def emission(self):
if not self.emission_:
tiker = str(self.tx_token().ticker)
hf = HashFast.fromString(str(self.tx_token().tokenEmissionHash))
ledger = self.net.getLedger()
ems = ledger.tokenEmissionFind(tiker, hf)
if not ems:
return None
self.emission_ = CellframeEmission(ems)
return self.emission_
class CellframeNetwork:
def __init__(self, name, chains, group_alias = None):
self.name = name
self.net = Net.byName(name)
self.group_alias = group_alias or name
if not self.net:
raise RuntimeError("No such net: {}".format(name))
for chain in chains:
setattr(self, chain, self.net.getChainByName(chain))
def set_mempool_notification_callback(self, chain, callback):
callback_name = "{}".format(self.name)
logIt.notice("New mempool notifier for {}".format(callback_name))
def callback_wraper(op_code, group, key, value, net_name):
callback(op_code, group, key, value, net_name, self, chain)
chain.addMempoolNotify(callback_wraper, callback_name)
def set_gdbsync_notification_callback(self, callback):
callback_name = "{}".format(self.name)
logIt.notice("New gdb notifier for {}".format(callback_name))
def callback_wraper(op_code, group, key, value, net_name):
callback(self, op_code, group, key, value, net_name)
self.net.addNotify(callback_wraper, self.name)
def set_atom_notification_callback(self, chain, callback):
callback_name = "{}".format(self.name)
logIt.notice("New atom notifier for {}".format(callback_name))
def callback_wraper(atom, size, callback_name):
callback(atom, size, callback_name, self, chain)
chain.addAtomNotify(callback_wraper, callback_name)
def set_ledger_tx_notification_callback(self, callback):
ledger = self.net.getLedger()
def callback_wrapper(ledger, tx, argv):
callback(ledger, tx, argv, self)
ledger.txAddNotify(callback_wrapper, self.net)
def load_cert(certname):
return Crypto.Cert.load(certname)
def extract_emission_from_mempool_nofitication(self, chain, value):
ems = Mempool.emissionExtract(chain, value)
if ems:
return CellframeEmission(ems)
else:
return None
return Mempool.baseTxCreate(self.main, emission.datum.hash, self.zerochain, emission.datum.value, emission.datum.ticker,
def get_emission_by_tsd(self, tsd_dict):
atom_count = self.zerochain.countAtom()
atoms = self.zerochain.getAtoms(atom_count, 1, True)
emissions = {}
for atom in atoms:
#event = DAG.fromAtom(atom[0], atom[1])
event = DAG.fromAtom(atom)
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
if not event.datum.isDatumTokenEmission():
continue
token_emission = event.datum.getDatumTokenEmission()
if not token_emission:
continue
results = []
for key,value in tsd_dict.items():
tsd = token_emission.getTSD(key)
if not tsd and value == None:
results.append(True)
continue
try:
if tsd and tsd.decode("utf-8") == value:
results.append(True)
continue
except:
pass
results.append(False)
if all(results):
emissions[str(event.datum.hash)] = CellframeEmission(token_emission)
return emissions
def get_emission_from_mempool_by_tsd(self, tsd_dict):
datums = Mempool.list(self.net, self.zerochain).values()
emissions = {}
for datum in datums:
if not datum.isDatumTokenEmission():
continue
token_emission = datum.getDatumTokenEmission()
if not token_emission:
continue
results = []
for key,value in tsd_dict.items():
tsd = token_emission.getTSD(key)
if not tsd and value == None:
results.append(True)
continue
try:
if tsd and tsd.decode("utf-8") == value:
results.append(True)
continue
except:
pass
results.append(False)
if all(results):
emissions[str(datum.hash)] = CellframeEmission(token_emission)
return emissions
def base_transactions_from_blocks(self, emission_hash=None):
iterator = self.main.createAtomItem(False)
ptr = self.main.atomIterGetFirst(iterator)
if not ptr:
logIt.error("Can't iterate over blocks in {}!".format(self.name))
return []
aptr, size = ptr
#iterate over blocks: atom-pointer should not be none, and size shoud be >0
while aptr:
if size <= 0: #skip such blocks
aptr, size = self.main.atomIterGetNext(iter)
continue
block = Block.fromAtom(aptr, size)
if not block.datums:
aptr, size = self.main.atomIterGetNext(iterator)
continue
for datum in block.datums:
if datum.isDatumTX():
try:
#if emshash provided - filter items
basedatum = CellframeBaseTransactionDatum( datum.getDatumTX(), block)
if emission_hash:
if basedatum.emission_hash == emission_hash:
yield basedatum
else:
continue
else:
yield basedatum
except:
continue
aptr, size = self.main.atomIterGetNext(iterator)
def get_transactions_to_wallet_from_blocks(self, address):
def nextBlockDatums():
iterator = self.createAtomItem(False)
aptr, size = self.main.atomIterGetFirst(iterator)
#iterate over blocks: atom-pointer should not be none, and size shoud be >0
while aptr:
if size <= 0: #skip such blocks
aptr, size = self.main.atomIterGetNext(iter)
continue
block = Block.fromAtom(aptr, size)
if block.datums:
yield block, block.datums
aptr, size = self.main.atomIterGetNext(iterator)
def isDatumToAddress(datum_with_block):
try:
txn_out = next(filter(lambda x: isinstance(x, TxOut), datum_with_block.datum.getItems()))
return str(txn_out.addr) == address
except Exception as e:
return False
transactions_to_wallet = []
class DatumWithBlock:
def __init__(self, datum, block):
self.datum = datum
self.block = block
for block, datums in nextBlockDatums():
tx_datums = [DatumWithBlock(datum.getDatumTX(), block) for datum in filter(lambda datum: datum.isDatumTX(), datums)]
transactions_to_wallet.extend(list(filter(isDatumToAddress, tx_datums)))
return transactions_to_wallet
def create_emission(self, wallet, token_symbol, value, tsd):
addr = CellFrame.Chain.ChainAddr.fromStr(wallet)
ems = DatumEmission(str(value), token_symbol, addr)
for key,value in tsd.items():
if isinstance(value, dict):
ems.addTSD(key, json_dump(value).encode("utf-8"))
elif isinstance(value, list):
ems.addTSD(key, json_dump(value).encode("utf-8"))
else:
ems.addTSD(key, str(value).encode("utf-8"))
return CellframeEmission(ems)
def place_emission(self, ems, chain):
return Mempool.emissionPlace(chain, ems.datum)
def place_datum(self, datum, chain):
return Mempool.addDatum(chain, datum)
def remove_key_from_mempool(self, key, chain):
Mempool.remove(chain, key)
def mempool_list(self, chain):
return Mempool.list(self.net, chain)
def mempool_get_emission(self, key):
return Mempool.emissionGet(self.zerochain, key)
def mempool_proc(self, hash, chain):
Mempool.proc(hash, chain)
def all_tx_from_ledger(self):
res = []
legder = self.net.getLedger()
count = legder.count()
txs = legder.getTransactions(count,1,False)
if not txs:
return [], legder
return txs, legder
def all_tx_from_blocks(self):
#logIt.error("DIR MAIN {}!".format(dir(self.main)))
iterator = self.main.createAtomIter(False)
ptr = self.main.atomIterGetFirst(iterator)
if not ptr:
logIt.error("Can't iterate over blocks in {}!".format(self.name))
return []
logIt.notice("ptr = {}" .format(ptr))
aptr, size = ptr
#iterate over blocks: atom-pointer should not be none, and size shoud be >0
if size <= 0:
aptr, size = self.main.atomIterGetNext(iterator)
if not block.datums:
aptr, size = self.main.atomIterGetNext(iterator)
continue
for datum in block.datums:
if datum.isDatumTX():
yield datum.getDatumTX()
else:
continue
aptr, size = self.main.atomIterGetNext(iterator)