From 01d706ac56f44887c34ae294a8d67950af1020d0 Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Tue, 8 Mar 2016 18:24:21 -0800 Subject: [PATCH] Moved consensus package files into single consensus.py module --- bigchaindb/consensus.py | 152 +++++++++++++++++++++++++++++++ bigchaindb/consensus/__init__.py | 43 --------- bigchaindb/consensus/base.py | 109 ---------------------- bigchaindb/consensus/silly.py | 21 ----- setup.py | 3 +- 5 files changed, 153 insertions(+), 175 deletions(-) create mode 100644 bigchaindb/consensus.py delete mode 100644 bigchaindb/consensus/__init__.py delete mode 100644 bigchaindb/consensus/base.py delete mode 100644 bigchaindb/consensus/silly.py diff --git a/bigchaindb/consensus.py b/bigchaindb/consensus.py new file mode 100644 index 00000000..4bf5fe66 --- /dev/null +++ b/bigchaindb/consensus.py @@ -0,0 +1,152 @@ +import bigchaindb.exceptions as exceptions +from bigchaindb import util +from bigchaindb.crypto import hash_data + +# TODO: no real reason to use abc yet, but later we can enforce inheritance from +# this class when loading plugins if that's desirable. +# from abc import ABCMeta + +class AbstractConsensusRules: + + # TODO: rather than having plugin-authors inherit and override, + # it'd be cleaner to make a `transactionrule` decorator and etc + @classmethod + def validate_transaction(cls, bigchain, transaction): + """Validate a transaction. + + Args: + bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. + transaction (dict): transaction to validate. + + Returns: + The transaction if the transaction is valid else it raises an + exception describing the reason why the transaction is invalid. + + Raises: + Descriptive exceptions indicating the reason the transaction failed. + See the `exceptions` module for bigchain-native error classes. + """ + return transaction + + @classmethod + def validate_block(cls, bigchain, block): + """Validate a block. + + Args: + bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. + block (dict): block to validate. + + Returns: + The block if the block is valid else it raises and exception + describing the reason why the block is invalid. + + Raises: + Descriptive exceptions indicating the reason the block failed. + See the `exceptions` module for bigchain-native error classes. + """ + return block + + class ConsensusRules(AbstractConsensusRules): + """Base consensus rules for Bigchain. + + This class can be copied to write your own consensus rules! + + Note: Consensus plugins will be executed in the order that they're listed in + the bigchain config file. + """ + + @classmethod + def validate_transaction(cls, bigchain, transaction): + """Validate a transaction. + + Args: + bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. + transaction (dict): transaction to validate. + + Returns: + The transaction if the transaction is valid else it raises an + exception describing the reason why the transaction is invalid. + + Raises: + OperationError: if the transaction operation is not supported + TransactionDoesNotExist: if the input of the transaction is not found + TransactionOwnerError: if the new transaction is using an input it doesn't own + DoubleSpend: if the transaction is a double spend + InvalidHash: if the hash of the transaction is wrong + InvalidSignature: if the signature of the transaction is wrong + """ + + # If the operation is CREATE the transaction should have no inputs and + # should be signed by a federation node + if transaction['transaction']['operation'] == 'CREATE': + if transaction['transaction']['input']: + raise ValueError('A CREATE operation has no inputs') + if transaction['transaction']['current_owner'] not in ( + bigchain.federation_nodes + [bigchain.me]): + raise exceptions.OperationError( + 'Only federation nodes can use the operation `CREATE`') + + else: + # check if the input exists, is owned by the current_owner + if not transaction['transaction']['input']: + raise ValueError( + 'Only `CREATE` transactions can have null inputs') + + tx_input = bigchain.get_transaction( + transaction['transaction']['input']) + + if not tx_input: + raise exceptions.TransactionDoesNotExist( + 'input `{}` does not exist in the bigchain'.format( + transaction['transaction']['input'])) + + if (tx_input['transaction']['new_owner'] != + transaction['transaction']['current_owner']): + raise exceptions.TransactionOwnerError( + 'current_owner `{}` does not own the input `{}`'.format( + transaction['transaction']['current_owner'], + transaction['transaction']['input'])) + + # check if the input was already spent by a transaction other than + # this one. + spent = bigchain.get_spent(tx_input['id']) + if spent and spent['id'] != transaction['id']: + raise exceptions.DoubleSpend( + 'input `{}` was already spent'.format( + transaction['transaction']['input'])) + + # Check hash of the transaction + calculated_hash = hash_data(util.serialize( + transaction['transaction'])) + if calculated_hash != transaction['id']: + raise exceptions.InvalidHash() + + # Check signature + if not bigchain.verify_signature(transaction): + raise exceptions.InvalidSignature() + + return transaction + + # TODO: check that the votings structure is correctly constructed + @classmethod + def validate_block(cls, bigchain, block): + """Validate a block. + + Args: + bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. + block (dict): block to validate. + + Returns: + The block if the block is valid else it raises and exception + describing the reason why the block is invalid. + + Raises: + InvalidHash: if the hash of the block is wrong. + """ + + # Check if current hash is correct + calculated_hash = hash_data(util.serialize(block['block'])) + if calculated_hash != block['id']: + raise exceptions.InvalidHash() + + return block diff --git a/bigchaindb/consensus/__init__.py b/bigchaindb/consensus/__init__.py deleted file mode 100644 index 24806bd0..00000000 --- a/bigchaindb/consensus/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -# TODO: no real reason to use abc yet, but later we can enforce inheritance from -# this class when loading plugins if that's desirable. -# from abc import ABCMeta - -class AbstractConsensusRules: - - # TODO: rather than having plugin-authors inherit and override, - # it'd be cleaner to make a `transactionrule` decorator and etc - @classmethod - def validate_transaction(cls, bigchain, transaction): - """Validate a transaction. - - Args: - bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. - transaction (dict): transaction to validate. - - Returns: - The transaction if the transaction is valid else it raises an - exception describing the reason why the transaction is invalid. - - Raises: - Descriptive exceptions indicating the reason the transaction failed. - See the `exceptions` module for bigchain-native error classes. - """ - return transaction - - @classmethod - def validate_block(cls, bigchain, block): - """Validate a block. - - Args: - bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. - block (dict): block to validate. - - Returns: - The block if the block is valid else it raises and exception - describing the reason why the block is invalid. - - Raises: - Descriptive exceptions indicating the reason the block failed. - See the `exceptions` module for bigchain-native error classes. - """ - return block diff --git a/bigchaindb/consensus/base.py b/bigchaindb/consensus/base.py deleted file mode 100644 index ed3f05c9..00000000 --- a/bigchaindb/consensus/base.py +++ /dev/null @@ -1,109 +0,0 @@ -import bigchaindb.exceptions as exceptions -from bigchaindb import util -from bigchaindb.crypto import hash_data -from bigchaindb.consensus import AbstractConsensusRules - -class ConsensusRules(AbstractConsensusRules): - """Base consensus rules for Bigchain. - - This class can be copied to write your own consensus rules! - - Note: Consensus plugins will be executed in the order that they're listed in - the bigchain config file. - """ - - @classmethod - def validate_transaction(cls, bigchain, transaction): - """Validate a transaction. - - Args: - bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. - transaction (dict): transaction to validate. - - Returns: - The transaction if the transaction is valid else it raises an - exception describing the reason why the transaction is invalid. - - Raises: - OperationError: if the transaction operation is not supported - TransactionDoesNotExist: if the input of the transaction is not found - TransactionOwnerError: if the new transaction is using an input it doesn't own - DoubleSpend: if the transaction is a double spend - InvalidHash: if the hash of the transaction is wrong - InvalidSignature: if the signature of the transaction is wrong - """ - - # If the operation is CREATE the transaction should have no inputs and - # should be signed by a federation node - if transaction['transaction']['operation'] == 'CREATE': - if transaction['transaction']['input']: - raise ValueError('A CREATE operation has no inputs') - if transaction['transaction']['current_owner'] not in ( - bigchain.federation_nodes + [bigchain.me]): - raise exceptions.OperationError( - 'Only federation nodes can use the operation `CREATE`') - - else: - # check if the input exists, is owned by the current_owner - if not transaction['transaction']['input']: - raise ValueError( - 'Only `CREATE` transactions can have null inputs') - - tx_input = bigchain.get_transaction( - transaction['transaction']['input']) - - if not tx_input: - raise exceptions.TransactionDoesNotExist( - 'input `{}` does not exist in the bigchain'.format( - transaction['transaction']['input'])) - - if (tx_input['transaction']['new_owner'] != - transaction['transaction']['current_owner']): - raise exceptions.TransactionOwnerError( - 'current_owner `{}` does not own the input `{}`'.format( - transaction['transaction']['current_owner'], - transaction['transaction']['input'])) - - # check if the input was already spent by a transaction other than - # this one. - spent = bigchain.get_spent(tx_input['id']) - if spent and spent['id'] != transaction['id']: - raise exceptions.DoubleSpend( - 'input `{}` was already spent'.format( - transaction['transaction']['input'])) - - # Check hash of the transaction - calculated_hash = hash_data(util.serialize( - transaction['transaction'])) - if calculated_hash != transaction['id']: - raise exceptions.InvalidHash() - - # Check signature - if not bigchain.verify_signature(transaction): - raise exceptions.InvalidSignature() - - return transaction - - # TODO: check that the votings structure is correctly constructed - @classmethod - def validate_block(cls, bigchain, block): - """Validate a block. - - Args: - bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. - block (dict): block to validate. - - Returns: - The block if the block is valid else it raises and exception - describing the reason why the block is invalid. - - Raises: - InvalidHash: if the hash of the block is wrong. - """ - - # Check if current hash is correct - calculated_hash = hash_data(util.serialize(block['block'])) - if calculated_hash != block['id']: - raise exceptions.InvalidHash() - - return block diff --git a/bigchaindb/consensus/silly.py b/bigchaindb/consensus/silly.py deleted file mode 100644 index 879b1328..00000000 --- a/bigchaindb/consensus/silly.py +++ /dev/null @@ -1,21 +0,0 @@ -import bigchaindb.exceptions as exceptions -from bigchaindb.crypto import hash_data -from bigchaindb.consensus import AbstractConsensusRules - - -class SillyConsensusRules(AbstractConsensusRules): - - @classmethod - def validate_transaction(cls, bigchain, transaction): - # I only like transactions whose timestamps are even. - if transaction['transaction']['timestamp'] % 2 != 0: - raise StandardError("Odd... very odd indeed.") - return transaction - - @classmethod - def validate_block(cls, bigchain, transaction): - # I don't trust Alice, I think she's shady. - if block['block']['node_pubkey'] == '': - raise StandardError("Alice is shady, everybody ignore her blocks!") - - return block diff --git a/setup.py b/setup.py index 083dc7a8..475cb3cc 100644 --- a/setup.py +++ b/setup.py @@ -59,8 +59,7 @@ setup( packages=[ 'bigchaindb', 'bigchaindb.commands', - 'bigchaindb.db', - 'bigchaindb.consensus' + 'bigchaindb.db' ], entry_points={