Exemple #1
0
 def sign_block(self, signable_block: "model.BlockModel") -> str:
     """Sign a block with this class' keys
     Args:
         block: BlockModel to sign
     Returns:
         Base64 encoded string of the block signature
     Raises:
         exceptions.InvalidNodeLevel when invalid level on self
         RuntimeError when no private key is set on self
     """
     if self.priv is None:
         raise RuntimeError("No private key has been set for signing")
     if self.level == 1:
         return crypto.sign_l1_block(self.hash, self.encryption, self.priv,
                                     signable_block)
     elif self.level == 2:
         return crypto.sign_l2_block(self.hash, self.encryption, self.priv,
                                     signable_block)
     elif self.level == 3:
         return crypto.sign_l3_block(self.hash, self.encryption, self.priv,
                                     signable_block)
     elif self.level == 4:
         return crypto.sign_l4_block(self.hash, self.encryption, self.priv,
                                     signable_block)
     elif self.level == 5:
         return crypto.sign_l5_block(self.hash, self.encryption, self.priv,
                                     signable_block)
     else:
         raise exceptions.InvalidNodeLevel(
             f"Node level {self.level} not implemented yet")
Exemple #2
0
def get_broadcast_dto(higher_level: int, block_id: str) -> Dict[str, Any]:
    """Get the broadcast dto for a block to a certain level
    Args:
        higher_level: (2-5)
        block_id: block_id used to locate block in storage
    Returns:
        Broadcast DTO of requested
    """
    l1_block = storage.get_json_from_object(f"{FOLDER}/{block_id}")
    if higher_level == 2:
        return l1_block_model.export_broadcast_dto(l1_block)
    else:
        required_verification_count = dragonnet_config.DRAGONNET_CONFIG[
            f"l{higher_level - 1}"]["nodesRequired"]
        verification_blocks = get_verifications_for_l1_block(
            block_id, (higher_level - 1))
        if len(verification_blocks) < required_verification_count:
            raise exceptions.NotEnoughVerifications(
                f"This chain requires {required_verification_count} level {higher_level - 1} verifications, but only {len(verification_blocks)} were found. (Probably just need to wait)"  # noqa: B950
            )
        if higher_level == 3:
            return l2_block_model.export_broadcast_dto(verification_blocks,
                                                       l1_block)
        elif higher_level == 4:
            return l3_block_model.export_broadcast_dto(verification_blocks,
                                                       l1_block)
        elif higher_level == 5:
            return l4_block_model.export_broadcast_dto(verification_blocks)
        else:
            raise exceptions.InvalidNodeLevel(
                f"Level {higher_level} is not valid for getting a broadcast DTO (Only allowed 2-5)"
            )
def process_receipt_v1(block_dto: Dict[str, Any]) -> None:
    if not block_dto:
        raise exceptions.ValidationException("block_dto missing")
    _log.info(
        f"[RECEIPT] Got receipt from L{block_dto['header']['level']}: {block_dto}"
    )
    block_model = cast("model.BlockModel",
                       None)  # This will always get defined, or it will raise
    level_received_from: int = block_dto["header"]["level"]
    if level_received_from == 2:
        block_model = l2_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 3:
        block_model = l3_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 4:
        block_model = l4_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 5:
        block_model = l5_block_model.new_from_at_rest(block_dto)
    else:
        raise exceptions.InvalidNodeLevel("Unsupported level receipt")

    _log.info(f"Block model {block_model.__dict__}")
    l1_block_id_set = block_model.get_associated_l1_block_id()

    _log.info(
        f"Processing receipt for blocks {l1_block_id_set} from L{level_received_from}"
    )
    for l1_block_id in l1_block_id_set:
        # Check that the chain which sent this receipt is in our claims, and that this L1 block is accepting receipts for this level
        validations = matchmaking.get_claim_check(
            l1_block_id)["validations"][f"l{level_received_from}"]
        if (
                block_model.dc_id in validations
        ) and broadcast_functions.is_block_accepting_verifications_from_level(
                l1_block_id, level_received_from):
            _log.info(
                f"Verified that block {l1_block_id} was sent. Inserting receipt"
            )
            storage_location = broadcast_functions.verification_storage_location(
                l1_block_id, level_received_from, block_model.dc_id)
            storage.put_object_as_json(storage_location,
                                       block_model.export_as_at_rest())
            # Set new receipt for matchmaking claim check
            try:
                block_id = block_model.block_id
                proof = block_model.proof
                dc_id = block_model.dc_id
                matchmaking.add_receipt(l1_block_id, level_received_from,
                                        dc_id, block_id, proof)
            except Exception:
                _log.exception("matchmaking add_receipt failed!")
            # Update the broadcast system about this receipt
            broadcast_functions.set_receieved_verification_for_block_from_chain_sync(
                l1_block_id, level_received_from, block_model.dc_id)
        else:
            _log.warning(
                f"Chain {block_model.dc_id} (level {level_received_from}) returned a receipt that wasn't expected (possibly expired?) for block {l1_block_id}. Rejecting receipt"  # noqa: B950
            )
            raise exceptions.NotAcceptingVerifications(
                f"Not accepting verifications for block {l1_block_id} from {block_model.dc_id}"
            )
def _get_verification_records(
        block_id: str,
        level: int = 0) -> Union[List[Any], Dict[str, List[Any]]]:
    if level:
        if level in [2, 3, 4, 5]:
            return _level_records(block_id, level)
        raise exceptions.InvalidNodeLevel(f"Level {level} not valid.")
    else:
        return _all_records(block_id)
Exemple #5
0
    def verify_full_transaction(
            self, full_tx: "transaction_model.TransactionModel") -> bool:
        """Verify a full transaction
        Args:
            full_tx: TransactionModel to verify
        Returns:
            Boolean if valid signed and hashed transaction
        Raises:
            exceptions.InvalidNodeLevel when self is not level 1
            RuntimeError when no public key is set on self
        """
        if self.level != 1:
            raise exceptions.InvalidNodeLevel(
                "Transactions only exist on level 1 nodes")
        if self.pub is None:
            raise RuntimeError("No public key has been set for verifying")

        return crypto.verify_full_transaction(self.hash, self.encryption,
                                              self.pub, full_tx)
Exemple #6
0
    def sign_transaction(
            self, signable_tx: "transaction_model.TransactionModel"
    ) -> Tuple[str, str]:
        """Sign a transaction
        Args:
            signable_tx: TransactionModel to sign
        Returns:
            Tuple of strings where index 0 is the base64 encoded full hash and index 1 is the base64 encoded stripped signature
        Raises:
            exceptions.InvalidNodeLevel when self is not level 1
            RuntimeError when no private key is set on self
        """
        if self.level != 1:
            raise exceptions.InvalidNodeLevel(
                "Transactions only exist on level 1 nodes")
        if self.priv is None:
            raise RuntimeError("No private key has been set for signing")

        return crypto.sign_transaction(self.hash, self.encryption, self.priv,
                                       signable_tx)
Exemple #7
0
def setup() -> Tuple[Dict[str, str], Any]:
    cron_trigger = {"second": "*/1"}
    if LEVEL == "1":
        cron_trigger = {"second": "*/5"}
        from dragonchain.transaction_processor import level_1_actions as processor
    elif LEVEL == "2":
        from dragonchain.transaction_processor import level_2_actions as processor
    elif LEVEL == "3":
        from dragonchain.transaction_processor import level_3_actions as processor
    elif LEVEL == "4":
        from dragonchain.transaction_processor import level_4_actions as processor
    elif LEVEL == "5":
        cron_trigger = {"minute": "*/1"}
        from dragonchain.transaction_processor import level_5_actions as processor

        processor.setup()  # L5 processor requires setup to be called to configure module state before running
    else:
        raise exceptions.InvalidNodeLevel("Invalid node level")

    return cron_trigger, processor
Exemple #8
0
 def pow_block(self, signable_block: "model.BlockModel") -> Tuple[str, int]:
     """Do proof of work on a block
     Args:
         block: BlockModel to do proof of work on
     Returns:
         Tuple where index 0 is a Base64 encoded string of the generated hash and index 1 is the nonce
     Raises:
         exceptions.InvalidNodeLevel when invalid level on self
     """
     if self.level == 1:
         return crypto.pow_l1_block(
             self.hash, cast("l1_block_model.L1BlockModel", signable_block))
     elif self.level == 2:
         return crypto.pow_l2_block(
             self.hash, cast("l2_block_model.L2BlockModel", signable_block))
     elif self.level == 3:
         return crypto.pow_l3_block(
             self.hash, cast("l3_block_model.L3BlockModel", signable_block))
     elif self.level == 4:
         return crypto.pow_l4_block(
             self.hash, cast("l4_block_model.L4BlockModel", signable_block))
     else:
         raise exceptions.InvalidNodeLevel(
             f"Node level {self.level} not implemented yet")
Exemple #9
0
 def verify_block(self, block: "model.BlockModel") -> bool:  # noqa: C901
     """Verify a block with this class' keys
     Args:
         block: BlockModel to verify
     Returns:
         Boolean if valid block (according to these keys)
     Raises:
         NotImplementedError when invalid scheme on self
     """
     if self.scheme == SupportedSchemes.trust and self.pub is None:
         RuntimeError(
             "No public key has been set for verifying block signature")
     if self.level == 1:
         if self.scheme == SupportedSchemes.trust:
             return crypto.verify_l1_block_trust(
                 self.hash, self.encryption, self.pub,
                 cast("l1_block_model.L1BlockModel", block))
         elif self.scheme == SupportedSchemes.work:
             return crypto.verify_l1_block_pow(
                 self.hash, cast("l1_block_model.L1BlockModel", block))
         else:
             raise NotImplementedError(
                 f"Proof scheme {self.scheme} not implemented")
     elif self.level == 2:
         if self.scheme == SupportedSchemes.trust:
             return crypto.verify_l2_block_trust(
                 self.hash, self.encryption, self.pub,
                 cast("l2_block_model.L2BlockModel", block))
         elif self.scheme == SupportedSchemes.work:
             return crypto.verify_l2_block_pow(
                 self.hash, cast("l2_block_model.L2BlockModel", block))
         else:
             raise NotImplementedError(
                 f"Proof scheme {self.scheme} not implemented")
     elif self.level == 3:
         if self.scheme == SupportedSchemes.trust:
             return crypto.verify_l3_block_trust(
                 self.hash, self.encryption, self.pub,
                 cast("l3_block_model.L3BlockModel", block))
         elif self.scheme == SupportedSchemes.work:
             return crypto.verify_l3_block_pow(
                 self.hash, cast("l3_block_model.L3BlockModel", block))
         else:
             raise NotImplementedError(
                 f"Proof scheme {self.scheme} not implemented")
     elif self.level == 4:
         if self.scheme == SupportedSchemes.trust:
             return crypto.verify_l4_block_trust(
                 self.hash, self.encryption, self.pub,
                 cast("l4_block_model.L4BlockModel", block))
         elif self.scheme == SupportedSchemes.work:
             return crypto.verify_l4_block_pow(
                 self.hash, cast("l4_block_model.L4BlockModel", block))
         else:
             raise NotImplementedError(
                 f"Proof scheme {self.scheme} not implemented")
     elif self.level == 5:
         if self.scheme == SupportedSchemes.trust:
             return crypto.verify_l5_block_trust(
                 self.hash, self.encryption, self.pub,
                 cast("l5_block_model.L5BlockModel", block))
         else:
             raise NotImplementedError(
                 f"Proof scheme {self.scheme} not implemented")
     else:
         raise exceptions.InvalidNodeLevel(
             f"Node level {self.level} nonexistent")
Exemple #10
0
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#      6. Trademarks. This License does not grant permission to use the trade
#         names, trademarks, service marks, or product names of the Licensor
#         and its affiliates, except as required to comply with Section 4(c) of
#         the License and to reproduce the content of the NOTICE file.
# You may obtain a copy of the Apache License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.

import os

import flask

from dragonchain import exceptions
from dragonchain.webserver.routes import route

LEVEL = os.environ["LEVEL"]

if LEVEL not in ["1", "2", "3", "4", "5"]:
    raise exceptions.InvalidNodeLevel(f"Invalid level {LEVEL}")

app = flask.Flask(__name__)

route(app)
Exemple #11
0
 def test_webserver_error_handler_invalid_node_level(self, mock_http_response, mock_report_exception):
     exception = exceptions.InvalidNodeLevel()
     helpers.webserver_error_handler(exception)
     mock_report_exception.assert_not_called()
     mock_http_response.assert_called_once_with(400, ANY)