mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Removed duplicated transaction validation in votes pipeline.
Separated block validation from transaction validation. Refactored block signature validation.
This commit is contained in:
parent
d49b06933a
commit
6b073f0898
@ -203,6 +203,12 @@ class Block(object):
|
|||||||
InvalidSignature: If a Block's signature is invalid.
|
InvalidSignature: If a Block's signature is invalid.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self._validate_block(bigchain)
|
||||||
|
self._validate_block_transactions(bigchain)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _validate_block(self, bigchain):
|
||||||
# First, make sure this node hasn't already voted on this block
|
# First, make sure this node hasn't already voted on this block
|
||||||
if bigchain.has_previous_vote(self.id, self.voters):
|
if bigchain.has_previous_vote(self.id, self.voters):
|
||||||
return self
|
return self
|
||||||
@ -212,18 +218,16 @@ class Block(object):
|
|||||||
if self.node_pubkey not in possible_voters:
|
if self.node_pubkey not in possible_voters:
|
||||||
raise OperationError('Only federation nodes can create blocks')
|
raise OperationError('Only federation nodes can create blocks')
|
||||||
|
|
||||||
|
# Check that the signature is valid
|
||||||
if not self.is_signature_valid():
|
if not self.is_signature_valid():
|
||||||
raise InvalidSignature('Block signature invalid')
|
raise InvalidSignature('Invalid block signature')
|
||||||
|
|
||||||
# Finally: Tentative assumption that every blockchain will want to
|
def _validate_block_transactions(self, bigchain):
|
||||||
# validate all transactions in each block
|
|
||||||
for tx in self.transactions:
|
for tx in self.transactions:
|
||||||
# NOTE: If a transaction is not valid, `is_valid` will throw an
|
# If a transaction is not valid, `validate_transactions` will
|
||||||
# an exception and block validation will be canceled.
|
# throw an an exception and block validation will be canceled.
|
||||||
bigchain.validate_transaction(tx)
|
bigchain.validate_transaction(tx)
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
def sign(self, private_key):
|
def sign(self, private_key):
|
||||||
"""Create a signature for the Block and overwrite `self.signature`.
|
"""Create a signature for the Block and overwrite `self.signature`.
|
||||||
|
|
||||||
@ -273,34 +277,19 @@ class Block(object):
|
|||||||
InvalidSignature: If the block's signature is not corresponding
|
InvalidSignature: If the block's signature is not corresponding
|
||||||
to it's data or `node_pubkey`.
|
to it's data or `node_pubkey`.
|
||||||
"""
|
"""
|
||||||
# TODO: Reuse `is_signature_valid` method here.
|
# Validate block id
|
||||||
block = block_body['block']
|
block = block_body['block']
|
||||||
block_serialized = serialize(block)
|
block_serialized = serialize(block)
|
||||||
block_id = hash_data(block_serialized)
|
block_id = hash_data(block_serialized)
|
||||||
public_key = PublicKey(block['node_pubkey'])
|
|
||||||
|
|
||||||
try:
|
|
||||||
signature = block_body['signature']
|
|
||||||
except KeyError:
|
|
||||||
signature = None
|
|
||||||
|
|
||||||
if block_id != block_body['id']:
|
if block_id != block_body['id']:
|
||||||
raise InvalidHash()
|
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 = public_key\
|
|
||||||
.verify(block_serialized.encode(), signature)
|
|
||||||
except ValueError:
|
|
||||||
signature_valid = False
|
|
||||||
if signature_valid is False:
|
|
||||||
raise InvalidSignature('Invalid block signature')
|
|
||||||
|
|
||||||
transactions = [Transaction.from_dict(tx) for tx
|
transactions = [Transaction.from_dict(tx) for tx
|
||||||
in block['transactions']]
|
in block['transactions']]
|
||||||
|
|
||||||
|
signature = block_body.get('signature')
|
||||||
|
|
||||||
return cls(transactions, block['node_pubkey'],
|
return cls(transactions, block['node_pubkey'],
|
||||||
block['timestamp'], block['voters'], signature)
|
block['timestamp'], block['voters'], signature)
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class Vote:
|
|||||||
block['block']['voters']):
|
block['block']['voters']):
|
||||||
try:
|
try:
|
||||||
block = Block.from_dict(block)
|
block = Block.from_dict(block)
|
||||||
except (exceptions.InvalidHash, exceptions.InvalidSignature):
|
except (exceptions.InvalidHash):
|
||||||
# XXX: if a block is invalid we should skip the `validate_tx`
|
# XXX: if a block is invalid we should skip the `validate_tx`
|
||||||
# step, but since we are in a pipeline we cannot just jump to
|
# step, but since we are in a pipeline we cannot just jump to
|
||||||
# another function. Hackish solution: generate an invalid
|
# another function. Hackish solution: generate an invalid
|
||||||
@ -61,10 +61,8 @@ class Vote:
|
|||||||
# pipeline.
|
# pipeline.
|
||||||
return block['id'], [self.invalid_dummy_tx]
|
return block['id'], [self.invalid_dummy_tx]
|
||||||
try:
|
try:
|
||||||
self.consensus.validate_block(self.bigchain, block)
|
block._validate_block(self.bigchain)
|
||||||
except (exceptions.InvalidHash,
|
except (exceptions.OperationError, exceptions.InvalidSignature):
|
||||||
exceptions.OperationError,
|
|
||||||
exceptions.InvalidSignature):
|
|
||||||
# XXX: if a block is invalid we should skip the `validate_tx`
|
# XXX: if a block is invalid we should skip the `validate_tx`
|
||||||
# step, but since we are in a pipeline we cannot just jump to
|
# step, but since we are in a pipeline we cannot just jump to
|
||||||
# another function. Hackish solution: generate an invalid
|
# another function. Hackish solution: generate an invalid
|
||||||
|
@ -107,7 +107,7 @@ class TestBlockModel(object):
|
|||||||
with raises(InvalidHash):
|
with raises(InvalidHash):
|
||||||
Block.from_dict(block)
|
Block.from_dict(block)
|
||||||
|
|
||||||
def test_block_invalid_signature_deserialization(self, b):
|
def test_block_invalid_signature(self, b):
|
||||||
from bigchaindb.common.crypto import hash_data
|
from bigchaindb.common.crypto import hash_data
|
||||||
from bigchaindb.common.exceptions import InvalidSignature
|
from bigchaindb.common.exceptions import InvalidSignature
|
||||||
from bigchaindb.common.utils import gen_timestamp, serialize
|
from bigchaindb.common.utils import gen_timestamp, serialize
|
||||||
@ -131,7 +131,7 @@ class TestBlockModel(object):
|
|||||||
}
|
}
|
||||||
|
|
||||||
with raises(InvalidSignature):
|
with raises(InvalidSignature):
|
||||||
Block.from_dict(block_body)
|
Block.from_dict(block_body).validate(b)
|
||||||
|
|
||||||
def test_compare_blocks(self, b):
|
def test_compare_blocks(self, b):
|
||||||
from bigchaindb.models import Block, Transaction
|
from bigchaindb.models import Block, Transaction
|
||||||
|
Loading…
x
Reference in New Issue
Block a user