Skip to content

Commit

Permalink
Merkle proof update for web batch (blockchain-certificates#121)
Browse files Browse the repository at this point in the history
* add wsgi.py file to spawn flask process

* Add default config settings for use with wsgi

* multibatch proof fix for web api
  • Loading branch information
yancyribbens authored and fuerve committed Jun 17, 2020
1 parent 2f132fc commit bb3e324
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 27 deletions.
12 changes: 8 additions & 4 deletions cert_issuer/certificate_handlers.py
Expand Up @@ -9,7 +9,6 @@

from cert_issuer.signer import FinalizableSigner


class CertificateV2Handler(CertificateHandler):
def get_byte_array_to_issue(self, certificate_metadata):
certificate_json = self._get_certificate_to_issue(certificate_metadata)
Expand Down Expand Up @@ -44,11 +43,16 @@ def add_proof(self, certificate_json, merkle_proof):
:param merkle_proof:
:return:
"""
return merkle_proof
certificate_json['signature'] = merkle_proof
return certificate_json

class CertificateBatchWebHandler(BatchHandler):
def finish_batch(self, tx_id, chain):
self.proof = next(self.merkle_tree.get_proof_generator(tx_id, chain))
self.proof = []
proof_generator = self.merkle_tree.get_proof_generator(tx_id, chain)
for metadata in self.certificates_to_issue:
proof = next(proof_generator)
self.proof.append(self.certificate_handler.add_proof(metadata, proof))

def get_certificate_generator(self):
"""
Expand Down Expand Up @@ -117,7 +121,7 @@ def get_certificate_generator(self):

def finish_batch(self, tx_id, chain):
proof_generator = self.merkle_tree.get_proof_generator(tx_id, chain)
for uid, metadata in self.certificates_to_issue.items():
for metadata in self.certificates_to_issue.items():
proof = next(proof_generator)
self.certificate_handler.add_proof(metadata, proof)

Expand Down
146 changes: 124 additions & 22 deletions tests/test_certificate_handler.py
Expand Up @@ -2,14 +2,68 @@

import mock
import json
import io
from pycoin.serialize import b2h
from unittest.mock import patch
from mock import patch, mock_open

from cert_issuer.certificate_handlers import CertificateBatchHandler, CertificateHandler, CertificateBatchWebHandler
from cert_issuer.certificate_handlers import CertificateWebV2Handler, CertificateV2Handler, CertificateBatchHandler, CertificateHandler, CertificateBatchWebHandler
from cert_issuer.merkle_tree_generator import MerkleTreeGenerator
from cert_issuer import helpers
from mock import ANY

class TestCertificateHandler(unittest.TestCase):
def _proof_helper(self, chain):
proof = {
'merkleRoot': '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044',
'type': ['MerkleProof2017', 'Extension'],
'targetHash': ANY,
'anchors': [
{
'sourceId': ANY,
'type': chain.blockchain_type.external_display_value,
'chain': chain.external_display_value
}
],
'proof': [
{'right': 'd4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35'},
{'right': '4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce'}
],
}

proof_1 = {
'merkleRoot': '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044',
'type': ['MerkleProof2017', 'Extension'],
'targetHash': ANY,
'anchors': [
{
'sourceId': ANY,
'type': chain.blockchain_type.external_display_value,
'chain': chain.external_display_value
}
],
'proof': [
{'left': '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b'},
{'right': '4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce'}
]
}

proof_2 = {
'merkleRoot': '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044',
'type': ['MerkleProof2017', 'Extension'],
'targetHash': ANY,
'anchors': [
{
'sourceId': ANY,
'type': chain.blockchain_type.external_display_value,
'chain': chain.external_display_value
}
],
'proof': [
{'left': '4295f72eeb1e3507b8461e240e3b8d18c1e7bd2f1122b11fc9ec40a65894031a'}
]
}
return proof, proof_1, proof_2

def _helper_mock_call(self, *args):
helper_mock = mock.MagicMock()
helper_mock.__len__.return_value = self.directory_count
Expand All @@ -36,7 +90,6 @@ def _get_certificate_batch_web_handler(self):

return handler, certificates_to_issue


def _get_certificate_batch_handler(self):
secret_manager = mock.Mock()
certificates_to_issue = dict()
Expand All @@ -51,37 +104,57 @@ def _get_certificate_batch_handler(self):

return handler, certificates_to_issue

def test_batch_handler_web_prepare(self):
web_request = json.dumps([{'allyourbasearebelongtous': True}])
def test_batch_handler_web_prepare_batch(self):
web_handler, certificates_to_issue = self._get_certificate_batch_web_handler()
web_handler.set_certificates_in_batch(web_request)
single_item_batch = web_handler.prepare_batch()

web_handler.set_certificates_in_batch(certificates_to_issue)
result = web_handler.prepare_batch()
self.assertEqual(
b2h(single_item_batch),
'38451f557bc2b5ad74012d3389798281b993fc7375c024615ed73fb147670ba7')
b2h(result), '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044')

web_handler, certificates_to_issue = self._get_certificate_batch_web_handler()
web_handler.set_certificates_in_batch(
[{'allyourbasearebelongtous': True}, {'allyourbasearebelongtous': False}])
multi_batch = web_handler.prepare_batch()
self.assertNotEqual(b2h(single_item_batch), b2h(multi_batch))
def test_batch_handler_prepare_batch(self):
certificate_batch_handler, certificates_to_issue = self._get_certificate_batch_handler()

certificate_batch_handler.set_certificates_in_batch(certificates_to_issue)
result = certificate_batch_handler.prepare_batch()
self.assertEqual(
b2h(result), '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044')

def test_batch_handler_prepare_batch(self):
secret_manager = mock.Mock()
certificates_to_issue = dict()
certificates_to_issue['1'] = mock.Mock()
certificates_to_issue['2'] = mock.Mock()
certificates_to_issue['3'] = mock.Mock()
def test_batch_web_handler_finish_batch(self):
certificate_batch_handler, certificates_to_issue = self._get_certificate_batch_web_handler()

certificate_batch_handler.set_certificates_in_batch(certificates_to_issue)
result = certificate_batch_handler.prepare_batch()

chain = mock.Mock()
proof, proof_1, proof_2 = self._proof_helper(chain)

with patch.object(DummyCertificateHandler, 'add_proof', return_value= {"cert": "cert"} ) as mock_method:
result = certificate_batch_handler.finish_batch(
'5604f0c442922b5db54b69f8f363b3eac67835d36a006b98e8727f83b6a830c0', chain
)
self.assertEqual(certificate_batch_handler.proof, [{'cert': 'cert'}, {'cert': 'cert'}, {'cert': 'cert'}])
mock_method.assert_any_call(ANY, proof)
mock_method.assert_any_call(ANY, proof_1)
mock_method.assert_any_call(ANY, proof_2)

def test_batch_handler_finish_batch(self):
certificate_batch_handler, certificates_to_issue = self._get_certificate_batch_handler()

certificate_batch_handler.set_certificates_in_batch(certificates_to_issue)
result = certificate_batch_handler.prepare_batch()

self.assertEqual(
b2h(result), '0932f1d2e98219f7d7452801e2b64ebd9e5c005539db12d9b1ddabe7834d9044')
chain = mock.Mock()
proof, proof_1, proof_2 = self._proof_helper(chain)

with patch.object(DummyCertificateHandler, 'add_proof') as mock_method:
result = certificate_batch_handler.finish_batch(
'5604f0c442922b5db54b69f8f363b3eac67835d36a006b98e8727f83b6a830c0', chain
)

mock_method.assert_any_call(ANY, proof)
mock_method.assert_any_call(ANY, proof_1)
mock_method.assert_any_call(ANY, proof_2)

def test_pre_batch_actions(self):
self.directory_count = 1
Expand Down Expand Up @@ -121,6 +194,35 @@ def test_pre_batch_actions_empty_directories(self):

assert not mock_method.called

@mock.patch("__builtin__.open", create=True)
def test_add_proof(self,mock_open):
handler = CertificateV2Handler()

cert_to_issue = {'kek':'kek'}
proof = {'a': 'merkel'}
file_call = 'call().__enter__().write(\'{"kek": "kek", "signature": {"a": "merkel"}}\')'

chain = mock.Mock()
metadata = mock.Mock()
metadata.blockchain_cert_file_name = 'file_path.nfo'

with patch.object(
CertificateV2Handler, '_get_certificate_to_issue', return_value=cert_to_issue) as mock_method:
handler.add_proof(metadata, proof)

mock_open.assert_any_call('file_path.nfo','w')
calls = mock_open.mock_calls
call_strings = map(str, calls)
assert file_call in call_strings

def test_web_add_proof(self):
handler = CertificateWebV2Handler()
proof = {'a': 'merkel'}
chain = mock.Mock()
certificate_json = {'kek': 'kek'}

return_cert = handler.add_proof(certificate_json, proof)
self.assertEqual(return_cert, {'kek':'kek', 'signature': {'a': 'merkel'}})

class DummyCertificateHandler(CertificateHandler):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_signer.py
@@ -1,5 +1,5 @@
import unittest
from unittest import mock
import mock

from cert_issuer.signer import FinalizableSigner

Expand Down

0 comments on commit bb3e324

Please sign in to comment.