diff --git a/bitdust/blockchain/bismuth_wallet.py b/bitdust/blockchain/bismuth_wallet.py index 886bb2899..e02a69f6d 100644 --- a/bitdust/blockchain/bismuth_wallet.py +++ b/bitdust/blockchain/bismuth_wallet.py @@ -19,6 +19,7 @@ from bitdust.lib import jsn from bitdust.main import settings +from bitdust.main import events from bitdust.system import local_fs @@ -195,7 +196,7 @@ def pack_transaction_id(tx): def sync_my_transactions(): global _MyTransactionsDirPath global _MyLatestTransactionBlockHeight - all_known_transactions = {} + all_known_transactions = set() for filename in os.listdir(_MyTransactionsDirPath): filepath = os.path.join(_MyTransactionsDirPath, filename) try: @@ -204,7 +205,7 @@ def sync_my_transactions(): except: lg.exc() continue - all_known_transactions[filename] = tx + all_known_transactions.add(filename) if _MyLatestTransactionBlockHeight < int(tx['block_height']): _MyLatestTransactionBlockHeight = int(tx['block_height']) blockchain_transactions = [] @@ -215,11 +216,13 @@ def sync_my_transactions(): filename = pack_transaction_id(tx) if filename in all_known_transactions: continue - all_known_transactions[filename] = tx + all_known_transactions.add(filename) if _MyLatestTransactionBlockHeight < int(tx['block_height']): _MyLatestTransactionBlockHeight = int(tx['block_height']) filepath = os.path.join(_MyTransactionsDirPath, filename) local_fs.WriteTextFile(filepath, jsn.dumps(tx)) new_transactions += 1 + tx['filename'] = filename + events.send('blockchain-transaction-received', data=tx) if _Debug: lg.args(_DebugLevel, new_transactions=new_transactions, known_transactions=len(all_known_transactions), latest_block=_MyLatestTransactionBlockHeight) diff --git a/bitdust/blockchain/blockchain_explorer.py b/bitdust/blockchain/blockchain_explorer.py index 9bba5b8c6..290a4c9eb 100644 --- a/bitdust/blockchain/blockchain_explorer.py +++ b/bitdust/blockchain/blockchain_explorer.py @@ -48,6 +48,7 @@ from bitdust.logs import lg from bitdust.lib import strng +from bitdust.lib import misc from bitdust.main import settings from bitdust.main import config @@ -188,15 +189,15 @@ def render_GET(self, request): view.append('{}'.format(time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(float(x[1]))))) view.append('{}'.format(x[2][:8])) #from view.append('{}'.format(x[3][:8])) #to - view.append('{0:g}'.format(float(x[4]))) #amount + view.append('{}'.format(misc.float2str(x[4], mask='%10.12f'))) #amount if x_old != x[0]: view.append('{}'.format(x[7][:8])) #block hash else: view.append(' ') #block hash - view.append('{0:g}'.format(float(x[8]))) #fee - view.append('{0:g}'.format(float(x[9]))) #reward + view.append('{}'.format(misc.float2str(x[8], mask='%10.12f'))) #fee + view.append('{}'.format(misc.float2str(x[9], mask='%10.12f'))) #reward view.append('{}{}'.format(x[10][:16], '…' if len(x[10]) > 16 else '')) #operation view.append('{}{}'.format(x[11][:24], '…' if len(x[11]) > 24 else '')) #openfield @@ -389,9 +390,9 @@ def render_GET(self, request): src += '
timestamp: {}

\n'.format(time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(float(raw[1])))) src += '
sender: {}

\n'.format(raw[2]) src += '
recipient: {}

\n'.format(raw[3]) - src += '
amount: {0:g}

\n'.format(raw[4]) - src += '
fee: {0:g}

\n'.format(raw[8]) - src += '
reward: {0:g}

\n'.format(raw[9]) + src += '
amount: {}

\n'.format(misc.float2str(raw[4], mask='%10.12f')) + src += '
fee: {}

\n'.format(misc.float2str(raw[8], mask='%10.12f')) + src += '
reward: {}

\n'.format(misc.float2str(raw[9], mask='%10.12f')) src += '
operation: {}

\n'.format(raw[10]) src += '
openfield: {}

\n'.format(raw[11]) src += '
signature:\n{}

\n'.format(self.tx_id) diff --git a/bitdust/services/service_blockchain_id.py b/bitdust/services/service_blockchain_id.py index 18d1f727a..700833747 100644 --- a/bitdust/services/service_blockchain_id.py +++ b/bitdust/services/service_blockchain_id.py @@ -57,12 +57,27 @@ def start(self): from twisted.internet.defer import Deferred from bitdust.logs import lg from bitdust.blockchain import blockchain_registrator + self.sync_my_transactions_loop = None self.starting_deferred = Deferred() self.starting_deferred.addErrback(lambda err: lg.warn('service %r was not started: %r' % (self.service_name, err.getErrorMessage() if err else 'unknown reason'))) blockchain_registrator.A('start', result_defer=self.starting_deferred) + self.starting_deferred.addCallback(self.on_blockchain_registrator_ready) return self.starting_deferred def stop(self): from bitdust.blockchain import blockchain_registrator + if self.sync_my_transactions_loop.running: + self.sync_my_transactions_loop.stop() + self.sync_my_transactions_loop = None blockchain_registrator.A('shutdown') return True + + def on_blockchain_registrator_ready(self, success): + from twisted.internet import task # @UnresolvedImport + self.sync_my_transactions_loop = task.LoopingCall(self.on_sync_my_transactions_task) + self.sync_my_transactions_loop.start(15*60, now=False) + return success + + def on_sync_my_transactions_task(self): + from bitdust.blockchain import bismuth_wallet + bismuth_wallet.sync_my_transactions() diff --git a/bitdust/services/service_supplier_contracts.py b/bitdust/services/service_supplier_contracts.py index 5b9f7b81a..bbaec19ec 100644 --- a/bitdust/services/service_supplier_contracts.py +++ b/bitdust/services/service_supplier_contracts.py @@ -49,26 +49,16 @@ def dependent_on(self): ] def start(self): - from twisted.internet import task # @UnresolvedImport - self.accept_payments_loop = task.LoopingCall(self.on_accept_payments_task) - self.accept_payments_loop.start(60*60, now=True) - self.sync_my_transactions_loop = task.LoopingCall(self.on_sync_my_transactions_task) - self.sync_my_transactions_loop.start(30*60, now=True) + from bitdust.main import events + events.add_subscriber(self.on_blockchain_transaction_received, 'blockchain-transaction-received') return True def stop(self): - if self.accept_payments_loop.running: - self.accept_payments_loop.stop() - self.accept_payments_loop = None - if self.sync_my_transactions_loop.running: - self.sync_my_transactions_loop.stop() - self.sync_my_transactions_loop = None + from bitdust.main import events + events.remove_subscriber(self.on_blockchain_transaction_received, 'blockchain-transaction-received') return True - def on_sync_my_transactions_task(self): - from bitdust.blockchain import bismuth_wallet - bismuth_wallet.sync_my_transactions() - - def on_accept_payments_task(self): - from bitdust.supplier import storage_contract - storage_contract.accept_storage_payments() + def on_blockchain_transaction_received(self, evt): + if evt.data.get('operation') == 'storage': + from bitdust.supplier import storage_contract + storage_contract.verify_accept_storage_payment(evt.data) diff --git a/bitdust/supplier/customer_space.py b/bitdust/supplier/customer_space.py index ee593ab1e..ffd67feda 100644 --- a/bitdust/supplier/customer_space.py +++ b/bitdust/supplier/customer_space.py @@ -994,30 +994,26 @@ def on_service_supplier_request(json_payload, newpacket, info): reactor.callLater(0, local_tester.TestUpdateCustomers) # @UndefinedVariable if new_customer: lg.info('NEW CUSTOMER: ACCEPTED %s family_position=%s ecc_map=%s allocated_bytes=%s' % (customer_idurl, family_position, ecc_map, bytes_for_customer)) - events.send( - 'new-customer-accepted', data=dict( - idurl=customer_idurl, - allocated_bytes=bytes_for_customer, - ecc_map=ecc_map, - position=family_position, - family_snapshot=family_snapshot, - key_id=customer_public_key_id, - contract=current_contract, - ) - ) + events.send('new-customer-accepted', data=dict( + idurl=customer_idurl, + allocated_bytes=bytes_for_customer, + ecc_map=ecc_map, + position=family_position, + family_snapshot=family_snapshot, + key_id=customer_public_key_id, + contract=current_contract, + )) else: lg.info('EXISTING CUSTOMER: ACCEPTED %s family_position=%s ecc_map=%s allocated_bytes=%s' % (customer_idurl, family_position, ecc_map, bytes_for_customer)) - events.send( - 'existing-customer-accepted', data=dict( - idurl=customer_idurl, - allocated_bytes=bytes_for_customer, - ecc_map=ecc_map, - position=family_position, - key_id=customer_public_key_id, - family_snapshot=family_snapshot, - contract=current_contract, - ) - ) + events.send('existing-customer-accepted', data=dict( + idurl=customer_idurl, + allocated_bytes=bytes_for_customer, + ecc_map=ecc_map, + position=family_position, + key_id=customer_public_key_id, + family_snapshot=family_snapshot, + contract=current_contract, + )) if current_contract: return p2p_service.SendAck(newpacket, 'accepted:' + jsn.dumps(current_contract)) return p2p_service.SendAck(newpacket, 'accepted') diff --git a/bitdust/supplier/storage_contract.py b/bitdust/supplier/storage_contract.py index 403d93ca5..e721d8e31 100644 --- a/bitdust/supplier/storage_contract.py +++ b/bitdust/supplier/storage_contract.py @@ -496,44 +496,40 @@ def verify_all_current_customers_contracts(): return rejected_customers -def accept_storage_payments(): - now = utime.utcnow_to_sec1970() - my_storage_transactions = {} - for filename in os.listdir(bismuth_wallet.my_transactions_dir()): - filepath = os.path.join(bismuth_wallet.my_transactions_dir(), filename) - try: - tx = jsn.loads_text(local_fs.ReadTextFile(filepath)) - int(tx['block_height']) - tx['operation'] - float(tx['amount']) - except: - lg.exc() - continue - if tx['operation'] != 'storage': - continue - if tx['recipient'] != bismuth_wallet.my_wallet_address(): - continue - try: - customer_prefix, sequence_numbers = tx['openfield'].split(' ') - except: - continue - try: - sequence_numbers = map(int, sequence_numbers.split(',')) - except: - lg.exc() - continue - if customer_prefix not in my_storage_transactions: - my_storage_transactions[customer_prefix] = { - 'total_amount': 0.0, - 'transactions': [], - } - my_storage_transactions[customer_prefix]['transactions'].append(tx) - my_storage_transactions[customer_prefix]['total_amount'] += float(tx['amount']) +def verify_accept_storage_payment(tx): + try: + customer_prefix, sequence_numbers = tx['openfield'].split(' ') + except: + lg.exc() + return + try: + sequence_numbers = map(int, sequence_numbers.split(',')) + except: + lg.exc() + continue + recently_paid_contracts = [] for customer_idurl in contactsdb.customers(): + if customer_idurl.unique_name() != customer_prefix: + continue contracts_list = list_customer_contracts(customer_idurl) for contract_started_time in contracts_list.keys(): if isinstance(contract_started_time, int): json_data = contracts_list[contract_started_time] - # if json_data['state'] == 'paid': - # ... - # latest_contract = contracts_list['latest'] + if json_data['state'] == 'completed': + if json_data['sequence_number'] in sequence_numbers: + recently_paid_contracts.append(json_data) + if _Debug: + lg.args(_DebugLevel, customer_prefix=customer_prefix, sequence_numbers=sequence_numbers, recently_paid_contracts=len(recently_paid_contracts)) + if not recently_paid_contracts: + return + customer_contracts_dir = get_customer_contracts_dir(customer_idurl) + for json_data in recently_paid_contracts: + # rename ".completed" file to ".paid" + completed_contract_path = os.path.join(customer_contracts_dir, json_data['filename']) + paid_contract_path = os.path.join(customer_contracts_dir, '{}.paid'.format(utime.unpack_time(json_data['started']))) + if _Debug: + lg.args(_DebugLevel, old_path=completed_contract_path, new_path=paid_contract_path) + os.rename(completed_contract_path, paid_contract_path) + paid_contract = jsn.loads_text(local_fs.ReadTextFile(paid_contract_path)) + paid_contract['customer'] = customer_idurl + events.send('storage-contract-paid', data=dict(contract=paid_contract))