def vote(self, block_id, previous_block_id, decision, invalid_reason=None): """Cast your vote on the block given the previous_block_hash and the decision (valid/invalid) return the block to the updated in the database. Args: block_id (str): The id of the block to vote. previous_block_id (str): The id of the previous block. decision (bool): Whether the block is valid or invalid. invalid_reason (Optional[str]): Reason the block is invalid """ if block_id == previous_block_id: raise exceptions.CyclicBlockchainError() vote = { 'voting_for_block': block_id, 'previous_block': previous_block_id, 'is_block_valid': decision, 'invalid_reason': invalid_reason, 'timestamp': gen_timestamp() } vote_data = serialize(vote) signature = crypto.SigningKey(self.me_private).sign(vote_data) vote_signed = { 'node_pubkey': self.me, 'signature': signature, 'vote': vote } return vote_signed
def from_dict(cls, block_body): block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) verifying_key = VerifyingKey(block['node_pubkey']) try: signature = block_body['signature'] except KeyError: signature = None if block_id != block_body['id']: raise InvalidHash() if signature is not None: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 try: signature_valid = verifying_key.verify(block_serialized, signature) except ValueError: signature_valid = False if signature_valid is False: raise InvalidSignature('Invalid block signature') transactions = [Transaction.from_dict(tx) for tx in block['transactions']] return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
def is_signature_valid(self): block = self.to_dict()['block'] block_serialized = serialize(block) verifying_key = VerifyingKey(block['node_pubkey']) try: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 return verifying_key.verify(block_serialized, self.signature) except (ValueError, AttributeError): return False
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_cond, user_priv, data_id): from copy import deepcopy from bigchaindb_common.crypto import SigningKey from bigchaindb_common.transaction import Transaction, Asset from bigchaindb_common.util import serialize expected = { 'transaction': { 'conditions': [user2_cond.to_dict(0)], 'metadata': None, 'asset': { 'id': data_id, }, 'fulfillments': [ { 'owners_before': [ user_pub ], 'fid': 0, 'fulfillment': None, 'input': { 'txid': tx.id, 'cid': 0 } } ], 'operation': 'TRANSFER', }, 'version': 1 } inputs = tx.to_inputs([0]) asset = Asset(None, data_id) transfer_tx = Transaction.transfer(inputs, [user2_pub], asset=asset) transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.to_dict() transfer_tx_body = transfer_tx['transaction'] expected_input = deepcopy(inputs[0]) expected['id'] = transfer_tx['id'] expected['transaction']['timestamp'] = transfer_tx_body['timestamp'] expected_input.fulfillment.sign(serialize(expected).encode(), SigningKey(user_priv)) expected_ffill = expected_input.fulfillment.serialize_uri() transfer_ffill = transfer_tx_body['fulfillments'][0]['fulfillment'] assert transfer_ffill == expected_ffill transfer_tx = Transaction.from_dict(transfer_tx) assert transfer_tx.fulfillments_valid([tx.conditions[0]]) is True
def to_dict(self): if len(self.transactions) == 0: raise OperationError('Empty block creation is not allowed') block = { 'timestamp': self.timestamp, 'transactions': [tx.to_dict() for tx in self.transactions], 'node_pubkey': self.node_pubkey, 'voters': self.voters, } block_serialized = serialize(block) block_id = hash_data(block_serialized) return { 'id': block_id, 'block': block, 'signature': self.signature, }
def verify_vote_signature(voters, signed_vote): """Verify the signature of a vote A valid vote should have been signed `owner_before` corresponding private key. Args: voters (list): voters of the block that is under election signed_vote (dict): a vote with the `signature` included. Returns: bool: True if the signature is correct, False otherwise. """ signature = signed_vote['signature'] vk_base58 = signed_vote['node_pubkey'] # immediately return False if the voter is not in the block voter list if vk_base58 not in voters: return False public_key = crypto.VerifyingKey(vk_base58) return public_key.verify(serialize(signed_vote['vote']), signature)
def to_str(self): return serialize(self.to_dict())
def sign(self, signing_key): block_body = self.to_dict() block_serialized = serialize(block_body['block']) signing_key = SigningKey(signing_key) self.signature = signing_key.sign(block_serialized) return self