Exemple #1
0
    def _send_request(self, block,
                      sync_tolerance=None, target_count=None):
        block_info_txn = BlockInfoTxn(
            block=block, sync_tolerance=sync_tolerance,
            target_count=target_count)

        self.validator.send(self.factory.create_tp_process_request(
            payload=block_info_txn.SerializeToString(),
            inputs=None, outputs=None, deps=None))
    def create_batch(self, block_info):
        payload = BlockInfoTxn(block=block_info).SerializeToString()
        public_key = self._signer.get_public_key().as_hex()
        header = TransactionHeader(
            signer_public_key=public_key,
            family_name=FAMILY_NAME,
            family_version=FAMILY_VERSION,
            inputs=[CONFIG_ADDRESS, BLOCK_INFO_NAMESPACE],
            outputs=[CONFIG_ADDRESS, BLOCK_INFO_NAMESPACE],
            dependencies=[],
            payload_sha512=hashlib.sha512(payload).hexdigest(),
            batcher_public_key=public_key,
        ).SerializeToString()

        transaction_signature = self._signer.sign(header)

        transaction = Transaction(
            header=header,
            payload=payload,
            header_signature=transaction_signature,
        )

        header = BatchHeader(
            signer_public_key=public_key,
            transaction_ids=[transaction_signature],
        ).SerializeToString()

        batch_signature = self._signer.sign(header)

        return Batch(
            header=header,
            transactions=[transaction],
            header_signature=batch_signature,
        )
Exemple #3
0
    def apply(self, transaction, context):
        # Unpack payload
        txn = BlockInfoTxn()
        txn.ParseFromString(transaction.payload)
        next_block = txn.block

        # Validate block info fields
        if next_block.block_num < 0:
            raise InvalidTransaction(
                "Invalid block num '{}'".format(next_block.block_num))

        if not (validate_hex(next_block.previous_block_id, 128)
                or next_block.previous_block_id == "0000000000000000"):
            raise InvalidTransaction("Invalid previous block id '{}'".format(
                next_block.previous_block_id))

        if not validate_hex(next_block.signer_public_key, 66):
            raise InvalidTransaction("Invalid signer public_key '{}'".format(
                next_block.signer_public_key))

        if not validate_hex(next_block.header_signature, 128):
            raise InvalidTransaction("Invalid header signature '{}'".format(
                next_block.header_signature))

        if next_block.timestamp <= 0:
            raise InvalidTransaction(
                "Invalid timestamp '{}'".format(next_block.timestamp))

        # Get config and previous block (according to the block info in the
        # transaction) from state
        entries = context.get_state([CONFIG_ADDRESS])

        deletes = []
        sets = []
        config = BlockInfoConfig()

        # If there is no config in state, we don't know anything about what's
        # in state, so we have to treat this as the first entry
        if not entries:
            # If sync tolerance or target count were not specified in the txn,
            # use default values.
            config.sync_tolerance = \
                DEFAULT_SYNC_TOLERANCE if txn.sync_tolerance == 0 \
                else txn.sync_tolerance

            config.target_count = \
                DEFAULT_TARGET_COUNT if txn.target_count == 0 \
                else txn.target_count

            config.latest_block = next_block.block_num
            config.oldest_block = next_block.block_num

            validate_timestamp(next_block.timestamp, config.sync_tolerance)

            sets.append((CONFIG_ADDRESS, config.SerializeToString()))
            sets.append((
                create_block_address(next_block.block_num),
                next_block.SerializeToString()))

        else:
            config.ParseFromString(entries[0].data)

            # If the config was changed in this transaction
            if txn.sync_tolerance != 0:
                config.sync_tolerance = txn.sync_tolerance
            if txn.target_count != 0:
                config.target_count = txn.target_count

            if next_block.block_num - 1 != config.latest_block:
                raise InvalidTransaction(
                    "Block number must be one more than previous block's."
                    " Got {} expected {}".format(
                        next_block.block_num, config.latest_block + 1))

            validate_timestamp(next_block.timestamp, config.sync_tolerance)

            entries = context.get_state(
                [create_block_address(config.latest_block)])
            if not entries:
                raise InternalError(
                    "Config and state out of sync. Latest block not found in"
                    " state.")

            prev_block = BlockInfo()
            prev_block.ParseFromString(entries[0].data)
            if prev_block.block_num != config.latest_block:
                raise InternalError(
                    "Block info stored at latest block has incorrect block"
                    " num.")

            if next_block.previous_block_id != prev_block.header_signature:
                raise InvalidTransaction(
                    "Previous block id must match header signature of previous"
                    " block. Go {} expected {}".format(
                        next_block.previous_block_id,
                        prev_block.header_signature))

            if next_block.timestamp < prev_block.timestamp:
                raise InvalidTransaction(
                    "Timestamp must be greater than previous block's."
                    " Got {}, expected >{}".format(
                        next_block.timestamp, prev_block.timestamp))

            config.latest_block = next_block.block_num
            while (config.latest_block - config.oldest_block) \
                    > config.target_count:
                deletes.append(create_block_address(config.oldest_block))
                config.oldest_block = config.oldest_block + 1

            sets.append((CONFIG_ADDRESS, config.SerializeToString()))
            sets.append((
                create_block_address(next_block.block_num),
                next_block.SerializeToString()))

        # If this is not true, something else has modified global state
        if deletes:
            if set(deletes) != set(context.delete_state(deletes)):
                raise InternalError(
                    "Blocks should have been in state but weren't: {}".format(
                        deletes))

        if sets:
            addresses = set([k for k, _ in sets])
            addresses_set = set(context.set_state(
                {k: v for k, v in sets}))
            if addresses != addresses_set:
                raise InternalError("Failed to set addresses.")

        return None