Skip to content
Snippets Groups Projects
Commit 916475b2 authored by inso's avatar inso
Browse files

Implementation of cert stock (#383)

parent b7729670
No related branches found
No related tags found
No related merge requests found
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
<item> <item>
<widget class="QComboBox" name="combo_community"/> <widget class="QComboBox" name="combo_community"/>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Certifications stock</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QLabel" name="label_cert_stock"> <widget class="QLabel" name="label_cert_stock">
<property name="text"> <property name="text">
...@@ -39,6 +45,9 @@ ...@@ -39,6 +45,9 @@
</layout> </layout>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
......
...@@ -284,7 +284,7 @@ class Identity(QObject): ...@@ -284,7 +284,7 @@ class Identity(QObject):
Get the list of this person certifiers Get the list of this person certifiers
:param sakia.core.registry.identities.IdentitiesRegistry identities_registry: The identities registry :param sakia.core.registry.identities.IdentitiesRegistry identities_registry: The identities registry
:param sakia.core.community.Community community: The community target to request the join date :param sakia.core.community.Community community: The community target
:return: The list of the certifiers of this community :return: The list of the certifiers of this community
:rtype: list :rtype: list
""" """
...@@ -301,10 +301,10 @@ class Identity(QObject): ...@@ -301,10 +301,10 @@ class Identity(QObject):
BlockchainState.VALIDATED, BlockchainState.VALIDATED,
community) community)
certifier['cert_time'] = certifier_data['cert_time']['medianTime'] certifier['cert_time'] = certifier_data['cert_time']['medianTime']
if 'written' in certifier_data and type(certifier_data['written']) is dict: if certifier_data['written']:
certifier['block_number'] = certifier_data['written']['number'] certifier['block_number'] = certifier_data['written']['number']
else: else:
certifier['block_number'] = certifier_data['cert_time']['block'] certifier['block_number'] = None
certifiers.append(certifier) certifiers.append(certifier)
except ValueError as e: except ValueError as e:
...@@ -348,7 +348,7 @@ class Identity(QObject): ...@@ -348,7 +348,7 @@ class Identity(QObject):
Get the certifications in the blockchain and in the pools Get the certifications in the blockchain and in the pools
Get only unique and last certification for each pubkey Get only unique and last certification for each pubkey
:param sakia.core.registry.identities.IdentitiesRegistry identities_registry: The identities registry :param sakia.core.registry.identities.IdentitiesRegistry identities_registry: The identities registry
:param sakia.core.community.Community community: The community target to request the join date :param sakia.core.community.Community community: The community target
:return: The list of the certifiers of this community :return: The list of the certifiers of this community
:rtype: list :rtype: list
""" """
...@@ -378,9 +378,7 @@ class Identity(QObject): ...@@ -378,9 +378,7 @@ class Identity(QObject):
""" """
Get the list of persons certified by this person Get the list of persons certified by this person
:param sakia.core.registry.IdentitiesRegistry identities_registry: The registry :param sakia.core.registry.IdentitiesRegistry identities_registry: The registry
:param sakia.core.Community community: The community :param sakia.core.community.Community community: The community target
:param sakia.core.community.Community community: The community target to request the join date
:return: The list of the certified persons of this community in BMA json format :return: The list of the certified persons of this community in BMA json format
:rtype: list :rtype: list
""" """
...@@ -395,10 +393,10 @@ class Identity(QObject): ...@@ -395,10 +393,10 @@ class Identity(QObject):
BlockchainState.VALIDATED, BlockchainState.VALIDATED,
community) community)
certified['cert_time'] = certified_data['cert_time']['medianTime'] certified['cert_time'] = certified_data['cert_time']['medianTime']
if 'written' in certified_data and type(certified_data['written']) is dict: if certified_data['written']:
certified['block_number'] = certified_data['written']['number'] certified['block_number'] = certified_data['written']['number']
else: else:
certified['block_number'] = certified_data['cert_time']['block'] certified['block_number'] = None
certified_list.append(certified) certified_list.append(certified)
except ValueError as e: except ValueError as e:
if '404' in str(e): if '404' in str(e):
...@@ -429,6 +427,14 @@ class Identity(QObject): ...@@ -429,6 +427,14 @@ class Identity(QObject):
return certified_list return certified_list
async def unique_valid_certified_by(self, identities_registry, community): async def unique_valid_certified_by(self, identities_registry, community):
"""
Get the list of persons certified by this person, filtered to get only unique
and valid certifications.
:param sakia.core.registry.IdentitiesRegistry identities_registry: The registry
:param sakia.core.community.Community community: The community target
:return: The list of the certified persons of this community in BMA json format
:rtype: list
"""
certified_list = await self.certified_by(identities_registry, community) certified_list = await self.certified_by(identities_registry, community)
unique_valid = [] unique_valid = []
# add certifiers of uid # add certifiers of uid
...@@ -452,6 +458,12 @@ class Identity(QObject): ...@@ -452,6 +458,12 @@ class Identity(QObject):
return unique_valid return unique_valid
async def membership_expiration_time(self, community): async def membership_expiration_time(self, community):
"""
Get the remaining time before membership expiration
:param sakia.core.Community community: the community
:return: the remaining time
:rtype: int
"""
membership = await self.membership(community) membership = await self.membership(community)
join_block = membership['blockNumber'] join_block = membership['blockNumber']
block = await community.get_block(join_block) block = await community.get_block(join_block)
...@@ -461,6 +473,23 @@ class Identity(QObject): ...@@ -461,6 +473,23 @@ class Identity(QObject):
current_time = time.time() current_time = time.time()
return expiration_date - current_time return expiration_date - current_time
async def cert_issuance_delay(self, identities_registry, community):
"""
Get the remaining time before being able to issue new certification.
:param sakia.core.Community community: the community
:return: the remaining time
:rtype: int
"""
certified = await self.certified_by(identities_registry, community)
if len(certified) > 0:
latest_time = max([c['cert_time'] for c in certified])
parameters = await community.parameters()
if parameters:
current_time = time.time()
if current_time - latest_time < parameters['sigPeriod']:
return parameters['sigPeriod'] - (current_time - latest_time)
return 0
def _refresh_uid(self, uids): def _refresh_uid(self, uids):
""" """
Refresh UID from uids list, got from a successful lookup request Refresh UID from uids list, got from a successful lookup request
......
...@@ -8,7 +8,7 @@ import logging ...@@ -8,7 +8,7 @@ import logging
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QApplication, QMessageBox from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QApplication, QMessageBox
from PyQt5.QtCore import Qt, QObject from PyQt5.QtCore import Qt, QObject, QLocale, QDateTime
from ..gen_resources.certification_uic import Ui_CertificationDialog from ..gen_resources.certification_uic import Ui_CertificationDialog
from .widgets import toast from .widgets import toast
...@@ -188,7 +188,23 @@ class CertificationDialog(QObject): ...@@ -188,7 +188,23 @@ class CertificationDialog(QObject):
logging.debug(str(e)) logging.debug(str(e))
block_0 = None block_0 = None
if is_member or not block_0: params = await self.community.parameters()
nb_certifications = len(await account_identity.certified_by(self.app.identities_registry, self.community))
remaining_time = await account_identity.cert_issuance_delay(self.app.identities_registry, self.community)
cert_text = self.tr("Certifications sent : {nb_certifications}/{stock}").format(
nb_certifications=nb_certifications,
stock=params['sigStock'])
if remaining_time > 0:
cert_text += self.tr("Remaining time before next available certification : {0}").format(
QLocale.toString(
QLocale(),
QDateTime.fromTime_t(remaining_time),
QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat)
),
)
self.ui.label_cert_stock.setText(cert_text)
if (is_member and remaining_time == 0 and nb_certifications < params['sigStock']) or not block_0:
self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(True) self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
self.ui.button_box.button(QDialogButtonBox.Ok).setText(self.tr("&Ok")) self.ui.button_box.button(QDialogButtonBox.Ok).setText(self.tr("&Ok"))
else: else:
......
...@@ -66,10 +66,31 @@ bma_lookup_test_patrick = { ...@@ -66,10 +66,31 @@ bma_lookup_test_patrick = {
] ]
} }
bma_parameters = {
"currency": "test_currency",
"c": 0.1,
"dt": 86400,
"ud0": 100,
"sigPeriod": 600,
"sigValidity": 2629800,
"sigQty": 3,
"sigWoT": 3,
"sigStock": 10,
"sigWindow": 1000,
"msValidity": 2629800,
"stepMax": 3,
"medianTimeBlocks": 11,
"avgGenTime": 600,
"dtDiffEval": 20,
"blocksRot": 144,
"percentRot": 0.67
}
def get_mock(loop): def get_mock(loop):
mock = MockServer(loop) mock = MockServer(loop)
mock.add_route('GET', '/blockchain/parameters', bma_parameters, 200)
mock.add_route('GET', '/blockchain/block/0', {"message": "Block not found"}, 404) mock.add_route('GET', '/blockchain/block/0', {"message": "Block not found"}, 404)
mock.add_route('GET', '/blockchain/current', {'message': "Block not found"}, 404) mock.add_route('GET', '/blockchain/current', {'message': "Block not found"}, 404)
......
...@@ -18,9 +18,31 @@ bma_wot_add = { ...@@ -18,9 +18,31 @@ bma_wot_add = {
] ]
} }
bma_parameters = {
"currency": "test_currency",
"c": 0.1,
"dt": 86400,
"ud0": 100,
"sigPeriod": 600,
"sigValidity": 2629800,
"sigQty": 3,
"sigWoT": 3,
"sigStock": 10,
"sigWindow": 1000,
"msValidity": 2629800,
"stepMax": 3,
"medianTimeBlocks": 11,
"avgGenTime": 600,
"dtDiffEval": 20,
"blocksRot": 144,
"percentRot": 0.67
}
def get_mock(loop): def get_mock(loop):
mock = MockServer(loop) mock = MockServer(loop)
mock.add_route('GET', '/blockchain/parameters', bma_parameters, 200)
mock.add_route('GET', '/blockchain/block/0', {'message': "Block not found"}, 404) mock.add_route('GET', '/blockchain/block/0', {'message': "Block not found"}, 404)
mock.add_route('GET', '/blockchain/current', {'message': "Block not found"}, 404) mock.add_route('GET', '/blockchain/current', {'message': "Block not found"}, 404)
......
...@@ -69,7 +69,20 @@ bma_lookup_doe = { ...@@ -69,7 +69,20 @@ bma_lookup_doe = {
"others": [] "others": []
} }
], ],
"signed": [] "signed": [
{
"pubkey": "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
"meta": {
"block_number": 38580
},
"uids": [
"john"
],
"isMember": True,
"wasMember": True,
"signature": "4ulycI2MtBu/8bZipy+OsXDCNm9EyUIdZ1HA7hbJ66phKRNvv70Oo2YOF/+VDRJb97z9TqWKgfIQ0NbXU15xDg=="
},
]
} }
] ]
} }
...@@ -86,7 +99,7 @@ bma_certifiers_of_john = { ...@@ -86,7 +99,7 @@ bma_certifiers_of_john = {
"wasMember": True, "wasMember": True,
"cert_time": { "cert_time": {
"block": 15, "block": 15,
"medianTime": 1447693329 "medianTime": 1500000000
}, },
"sigDate": "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "sigDate": "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"written": { "written": {
...@@ -107,12 +120,36 @@ bma_certified_by_john = { ...@@ -107,12 +120,36 @@ bma_certified_by_john = {
] ]
} }
bma_certified_by_doe = {
"pubkey": "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn",
"uid": "doe",
"isMember": True,
"certifications": [
{
"pubkey": "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
"uid": "john",
"isMember": True,
"wasMember": True,
"cert_time": {
"block": 15,
"medianTime": 1500000000
},
"sigDate": "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"written": {
"number": 15,
"hash": "0000EC88BBBAA29D530D2B815DEE264DDC9F07F4"
},
"signature": "oliiPDhniZAGHrIFL66oHR+cqD4aTgXX+20VFLMfNHwdYPeik76hy334zxhoDC4cPODMb9df2nF/EDfCefrNBg=="
},
]
}
bma_parameters = { bma_parameters = {
"currency": "test_currency", "currency": "test_currency",
"c": 0.1, "c": 0.1,
"dt": 86400, "dt": 86400,
"ud0": 100, "ud0": 100,
"sigDelay": 604800, "sigPeriod": 600,
"sigValidity": 2629800, "sigValidity": 2629800,
"sigQty": 3, "sigQty": 3,
"sigWoT": 3, "sigWoT": 3,
......
import unittest import unittest
from asynctest import Mock, CoroutineMock from asynctest import Mock, CoroutineMock, patch
from PyQt5.QtCore import QLocale from PyQt5.QtCore import QLocale
from sakia.core.registry.identities import Identity, LocalState, BlockchainState from sakia.core.registry.identities import Identity, LocalState, BlockchainState
...@@ -49,6 +49,32 @@ class TestIdentity(unittest.TestCase, QuamashTest): ...@@ -49,6 +49,32 @@ class TestIdentity(unittest.TestCase, QuamashTest):
self.lp.run_until_complete(exec_test()) self.lp.run_until_complete(exec_test())
@patch('time.time', Mock(return_value=1500000400))
def test_identity_cert_delay(self):
def bma_access(request, *args):
if request is bma.wot.CertifiedBy:
return nice_blockchain.bma_certified_by_doe
if request is bma.wot.Lookup:
return nice_blockchain.bma_lookup_doe
if request is bma.blockchain.Block:
return nice_blockchain.bma_blockchain_current
identity = Identity("john", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
BlockUID(20, "7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67"),
LocalState.COMPLETED, BlockchainState.VALIDATED)
id_doe = Identity("doe", "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn",
BlockUID(101, "BAD49448A1AD73C978CEDCB8F137D20A5715EBAA739DAEF76B1E28EE67B2C00C"),
LocalState.COMPLETED, BlockchainState.VALIDATED)
self.community.bma_access.future_request = CoroutineMock(side_effect=bma_access)
self.community.parameters = CoroutineMock(side_effect=lambda: nice_blockchain.bma_parameters)
self.identities_registry.from_handled_data = Mock(return_value=id_doe)
async def exec_test():
cert_delay = await identity.cert_issuance_delay(self.identities_registry, self.community)
self.assertEqual(cert_delay, 200)
self.lp.run_until_complete(exec_test())
def test_identity_membership(self): def test_identity_membership(self):
def bma_access(request, *args): def bma_access(request, *args):
if request is bma.blockchain.Membership: if request is bma.blockchain.Membership:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment