From 1813c2687967330744205463ae0b60080273064c Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Thu, 28 Apr 2016 13:54:50 +0200 Subject: [PATCH] validate_block now checks if a federation node created the block. It checks to see if node_pubkey is a federation node and if the signature is correct. Created tests --- bigchaindb/consensus.py | 10 +++++++++- tests/db/test_bigchain_api.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/bigchaindb/consensus.py b/bigchaindb/consensus.py index 277dad3e..26d89623 100644 --- a/bigchaindb/consensus.py +++ b/bigchaindb/consensus.py @@ -167,7 +167,6 @@ class BaseConsensusRules(AbstractConsensusRules): return transaction - # TODO: Unsure if a bigchain parameter is really necessary here? @staticmethod def validate_block(bigchain, block): """Validate a block. @@ -189,6 +188,15 @@ class BaseConsensusRules(AbstractConsensusRules): if calculated_hash != block['id']: raise exceptions.InvalidHash() + # Check if the block was created by a federation node + if block['block']['node_pubkey'] not in (bigchain.federation_nodes + [bigchain.me]): + raise exceptions.OperationError('Only federation nodes can create blocks') + + # Check if block signature is valid + verifying_key = crypto.VerifyingKey(block['block']['node_pubkey']) + if not verifying_key.verify(util.serialize(block['block']), block['signature']): + raise exceptions.InvalidSignature('Invalid block signature') + return block @staticmethod diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 23e73580..340f5c2d 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -407,6 +407,37 @@ class TestBlockValidation(object): assert block == b.validate_block(block) assert b.is_valid_block(block) + def test_invalid_signature(self, b): + # create a valid block + block = b.create_block([]) + + # replace the block signature with an invalid one + block['signature'] = crypto.SigningKey(b.me_private).sign(b'wrongdata') + + # check that validate_block raises an InvalidSignature exception + with pytest.raises(exceptions.InvalidSignature): + b.validate_block(block) + + def test_invalid_node_pubkey(self, b): + # blocks can only be created by a federation node + # create a valid block + block = b.create_block([]) + + # create some temp keys + tmp_sk, tmp_vk = crypto.generate_key_pair() + + # change the block node_pubkey + block['block']['node_pubkey'] = tmp_vk + + # just to make sure lets re-hash the block and create a valid signature + # from a non federation node + block['id'] = crypto.hash_data(util.serialize(block['block'])) + block['signature'] = crypto.SigningKey(tmp_sk).sign(util.serialize(block['block'])) + + # check that validate_block raises an OperationError + with pytest.raises(exceptions.OperationError): + b.validate_block(block) + class TestBigchainVoter(object):