diff --git a/bigchaindb/tendermint/core.py b/bigchaindb/tendermint/core.py index f33182ef..cbde790f 100644 --- a/bigchaindb/tendermint/core.py +++ b/bigchaindb/tendermint/core.py @@ -28,8 +28,8 @@ class App(BaseApplication): def init_chain(self, validators): """Initialize chain with block of height 0""" - block = Block(hash='', height=0) - self.bigchaindb.store_block(block.to_dict()) + block = Block(app_hash='', height=0) + self.bigchaindb.store_block(block._asdict()) def info(self): """Return height of the latest committed block.""" @@ -38,7 +38,7 @@ class App(BaseApplication): block = self.bigchaindb.get_latest_block() if block: r.last_block_height = block['height'] - r.last_block_app_hash = block['hash'].encode('utf-8') + r.last_block_app_hash = block['app_hash'].encode('utf-8') else: r.last_block_height = 0 r.last_block_app_hash = b'' @@ -89,10 +89,9 @@ class App(BaseApplication): block = self.bigchaindb.get_latest_block() if self.block_txn_ids: - self.block_txn_hash = calculate_hash([block['hash'], - block_txn_hash]) + self.block_txn_hash = calculate_hash([block['app_hash'], block_txn_hash]) else: - self.block_txn_hash = block['hash'] + self.block_txn_hash = block['app_hash'] return ResponseEndBlock() @@ -101,8 +100,8 @@ class App(BaseApplication): # register a new block only when new transactions are received if self.block_txn_ids: - block = Block(hash=self.block_txn_hash, height=self.new_height) - self.bigchaindb.store_block(block.to_dict()) + block = Block(app_hash=self.block_txn_hash, height=self.new_height) + self.bigchaindb.store_block(block._asdict()) data = self.block_txn_hash.encode('utf-8') return Result.ok(data=data) diff --git a/bigchaindb/tendermint/lib.py b/bigchaindb/tendermint/lib.py index 68729d0b..4f2e2aae 100644 --- a/bigchaindb/tendermint/lib.py +++ b/bigchaindb/tendermint/lib.py @@ -1,6 +1,7 @@ from copy import deepcopy from uuid import uuid4 import logging +from collections import namedtuple import requests @@ -114,13 +115,4 @@ class BigchainDB(Bigchain): return transaction -class Block(object): - - def __init__(self, hash='', height=0): - self.hash = hash - self.height = height - - def to_dict(self): - block = {'hash': self.hash, - 'height': self.height} - return block +Block = namedtuple('Block', ('app_hash', 'height')) diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index ad97a358..a7f664e5 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -1,19 +1,17 @@ import json -import pytest + +from abci.server import ProtocolHandler +from io import BytesIO +import abci.types_pb2 as types +from abci.wire import read_message +from abci.messages import to_request_deliver_tx, to_request_check_tx -@pytest.mark.bdb -@pytest.mark.tapp def test_app(b): from bigchaindb.tendermint import App from bigchaindb.tendermint.utils import calculate_hash - from abci.server import ProtocolHandler - from io import BytesIO - import abci.types_pb2 as types - from abci.wire import read_message from bigchaindb.common.crypto import generate_key_pair from bigchaindb.models import Transaction - from abci.messages import to_request_deliver_tx, to_request_check_tx app = App(b) p = ProtocolHandler(app) @@ -29,7 +27,7 @@ def test_app(b): block0 = b.get_latest_block() assert block0 assert block0['height'] == 0 - assert block0['hash'] == '' + assert block0['app_hash'] == '' alice = generate_key_pair() bob = generate_key_pair() @@ -64,7 +62,7 @@ def test_app(b): assert res assert 'end_block' == res.WhichOneof("value") - new_block_hash = calculate_hash([block0['hash'], new_block_txn_hash]) + new_block_hash = calculate_hash([block0['app_hash'], new_block_txn_hash]) data = p.process('commit', None) res, err = read_message(BytesIO(data), types.Response) @@ -75,4 +73,23 @@ def test_app(b): block0 = b.get_latest_block() assert block0 assert block0['height'] == 1 - assert block0['hash'] == new_block_hash + assert block0['app_hash'] == new_block_hash + + # empty block should not update height + r = types.Request() + r.begin_block.hash = new_block_hash.encode('utf-8') + p.process('begin_block', r) + + r = types.Request() + r.end_block.height = 2 + p.process('end_block', r) + + data = p.process('commit', None) + assert res.commit.data == new_block_hash.encode('utf-8') + + block0 = b.get_latest_block() + assert block0 + assert block0['height'] == 1 + + # when empty block is generated hash of previous block should be returned + assert block0['app_hash'] == new_block_hash diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 8e41aa19..1f1f78ef 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -1,3 +1,5 @@ +import os + from bigchaindb import backend @@ -27,3 +29,15 @@ def test_asset_is_separated_from_transaciton(b): assert 'asset' not in backend.query.get_transaction(b.connection, tx.id) assert backend.query.get_asset(b.connection, tx.id)['data'] == asset assert b.get_transaction(tx.id) == tx + + +def test_get_latest_block(b): + from bigchaindb.tendermint.lib import Block + + for i in range(10): + app_hash = os.urandom(16).hex() + block = Block(app_hash=app_hash, height=i)._asdict() + b.store_block(block) + + block = b.get_latest_block() + assert block['height'] == 9