From c993f954e088e3ccd88c156e8bab570286c1637e Mon Sep 17 00:00:00 2001 From: Scott Sadler Date: Mon, 27 Feb 2017 20:56:01 +0100 Subject: [PATCH] wip --- bigchaindb/core.py | 25 ++++++++----------------- bigchaindb/models.py | 6 ++++-- tests/pipelines/test_election.py | 16 ++++++++-------- tests/test_models.py | 3 +-- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index e4419bb4..61ea5e8c 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -69,6 +69,9 @@ class Bigchain(object): if not self.me or not self.me_private: raise exceptions.KeypairNotFoundException() + federation = property(lambda self: set(self.nodes_except_me + [self.me])) + """ Set of federation member public keys """ + def write_transaction(self, signed_transaction): """Write the transaction to bigchain. @@ -107,19 +110,8 @@ class Bigchain(object): dict: database response or None if no reassignment is possible """ - if self.nodes_except_me: - try: - federation_nodes = self.nodes_except_me + [self.me] - index_current_assignee = federation_nodes.index(transaction['assignee']) - new_assignee = random.choice(federation_nodes[:index_current_assignee] + - federation_nodes[index_current_assignee + 1:]) - except ValueError: - # current assignee not in federation - new_assignee = random.choice(self.nodes_except_me) - - else: - # There is no other node to assign to - new_assignee = self.me + other_nodes = self.federation.difference([transaction['assignee']]) + new_assignee = random.choice(other_nodes) if other_nodes else self.me return backend.query.update_transaction( self.connection, transaction['id'], @@ -467,7 +459,7 @@ class Bigchain(object): raise exceptions.OperationError('Empty block creation is not ' 'allowed') - voters = self.nodes_except_me + [self.me] + voters = list(self.federation) block = Block(validated_transactions, self.me, gen_timestamp(), voters) block = block.sign(self.me_private) @@ -607,9 +599,8 @@ class Bigchain(object): block = block.to_dict() votes = list(backend.query.get_votes_by_block_id(self.connection, block['id'])) - keyring = self.nodes_except_me + [self.me] - result = self.consensus.voting.block_election(block, votes, keyring) - return result + return self.consensus.voting.block_election(block, votes, + self.federation) def block_election_status(self, block): """Tally the votes on a block, and return the status: diff --git a/bigchaindb/models.py b/bigchaindb/models.py index ee7efe8f..2d16800f 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -236,10 +236,12 @@ class Block(object): InvalidSignature: If a Block's signature is invalid. """ # Check if the block was created by a federation node - possible_voters = (bigchain.nodes_except_me + [bigchain.me]) - if self.node_pubkey not in possible_voters: + if self.node_pubkey not in bigchain.federation: raise OperationError('Only federation nodes can create blocks') + if set(self.voters) != bigchain.federation: + raise OperationError('Block voters differs from server keyring') + # Check that the signature is valid if not self.is_signature_valid(): raise InvalidSignature('Invalid block signature') diff --git a/tests/pipelines/test_election.py b/tests/pipelines/test_election.py index bb01b6d1..e7491656 100644 --- a/tests/pipelines/test_election.py +++ b/tests/pipelines/test_election.py @@ -83,12 +83,6 @@ def test_check_for_quorum_invalid_prev_node(b, user_pk): def test_check_for_quorum_valid(b, user_pk): from bigchaindb.models import Transaction - e = election.Election() - - # create blocks with transactions - tx1 = Transaction.create([b.me], [([user_pk], 1)]) - test_block = b.create_block([tx1]) - # simulate a federation with four voters key_pairs = [crypto.generate_key_pair() for _ in range(4)] test_federation = [ @@ -96,10 +90,13 @@ def test_check_for_quorum_valid(b, user_pk): for key_pair in key_pairs ] - keyring = e.bigchain.nodes_except_me = [key_pair[1] for key_pair in key_pairs] + b.nodes_except_me = [key_pair[1] for key_pair in key_pairs] + + # create blocks with transactions + tx1 = Transaction.create([b.me], [([user_pk], 1)]) + test_block = b.create_block([tx1]) # add voters to block and write - test_block.voters = keyring test_block = test_block.sign(b.me_private) b.write_block(test_block) @@ -110,6 +107,9 @@ def test_check_for_quorum_valid(b, user_pk): for vote in votes: b.write_vote(vote) + e = election.Election() + e.bigchain = b + # since this block is valid, should go nowhere assert e.check_for_quorum(votes[-1]) is None diff --git a/tests/test_models.py b/tests/test_models.py index 8de3a6c2..0b8be0b0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -115,13 +115,12 @@ class TestBlockModel(object): transactions = [Transaction.create([b.me], [([b.me], 1)])] timestamp = gen_timestamp() - voters = ['Qaaa', 'Qbbb'] block = { 'timestamp': timestamp, 'transactions': [tx.to_dict() for tx in transactions], 'node_pubkey': b.me, - 'voters': voters, + 'voters': list(b.federation), } block_body = {