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))