mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Solution: BigchainDB depends on tendermint's RPC API to get the validator set which is not avaiable during replay so the validators set should be tracked inside BigchainDB
177 lines
5.8 KiB
Python
177 lines
5.8 KiB
Python
import codecs
|
|
|
|
import abci.types_pb2 as types
|
|
import json
|
|
import pytest
|
|
|
|
|
|
from abci.server import ProtocolHandler
|
|
from abci.encoding import read_messages
|
|
from copy import deepcopy
|
|
from io import BytesIO
|
|
|
|
|
|
@pytest.mark.tendermint
|
|
@pytest.mark.bdb
|
|
def test_app(tb, init_chain_request):
|
|
from bigchaindb import App
|
|
from bigchaindb.tendermint_utils import calculate_hash
|
|
from bigchaindb.common.crypto import generate_key_pair
|
|
from bigchaindb.models import Transaction
|
|
|
|
b = tb
|
|
app = App(b)
|
|
p = ProtocolHandler(app)
|
|
|
|
data = p.process('info', types.Request(info=types.RequestInfo(version='2')))
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
assert res
|
|
assert res.info.last_block_app_hash == b''
|
|
assert res.info.last_block_height == 0
|
|
assert not b.get_latest_block()
|
|
|
|
p.process('init_chain', types.Request(init_chain=init_chain_request))
|
|
block0 = b.get_latest_block()
|
|
assert block0
|
|
assert block0['height'] == 0
|
|
assert block0['app_hash'] == ''
|
|
|
|
pk = codecs.encode(init_chain_request.validators[0].pub_key.data, 'base64').decode().strip('\n')
|
|
[validator] = b.get_validators(height=1)
|
|
assert validator['pub_key']['data'] == pk
|
|
assert validator['voting_power'] == 10
|
|
|
|
alice = generate_key_pair()
|
|
bob = generate_key_pair()
|
|
tx = Transaction.create([alice.public_key],
|
|
[([bob.public_key], 1)])\
|
|
.sign([alice.private_key])
|
|
etxn = json.dumps(tx.to_dict()).encode('utf8')
|
|
|
|
r = types.Request(check_tx=types.RequestCheckTx(tx=etxn))
|
|
data = p.process('check_tx', r)
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
assert res
|
|
assert res.check_tx.code == 0
|
|
|
|
r = types.Request()
|
|
r.begin_block.hash = b''
|
|
p.process('begin_block', r)
|
|
|
|
r = types.Request(deliver_tx=types.RequestDeliverTx(tx=etxn))
|
|
data = p.process('deliver_tx', r)
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
assert res
|
|
assert res.deliver_tx.code == 0
|
|
|
|
new_block_txn_hash = calculate_hash([tx.id])
|
|
|
|
r = types.Request(end_block=types.RequestEndBlock(height=1))
|
|
data = p.process('end_block', r)
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
assert res
|
|
assert 'end_block' == res.WhichOneof('value')
|
|
|
|
new_block_hash = calculate_hash([block0['app_hash'], new_block_txn_hash])
|
|
|
|
data = p.process('commit', None)
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
assert res.commit.data == new_block_hash.encode('utf-8')
|
|
assert b.get_transaction(tx.id).id == tx.id
|
|
|
|
block0 = b.get_latest_block()
|
|
assert block0
|
|
assert block0['height'] == 1
|
|
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)
|
|
res = next(read_messages(BytesIO(data), types.Response))
|
|
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
|
|
|
|
|
|
@pytest.mark.skip
|
|
@pytest.mark.abci
|
|
def test_upsert_validator(b, alice):
|
|
from bigchaindb.backend.query import VALIDATOR_UPDATE_ID
|
|
from bigchaindb.backend import query, connect
|
|
from bigchaindb.models import Transaction
|
|
from bigchaindb.tendermint_utils import public_key_to_base64
|
|
import time
|
|
|
|
conn = connect()
|
|
power = 1
|
|
public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403'
|
|
|
|
validator = {'pub_key': {'type': 'AC26791624DE60',
|
|
'data': public_key},
|
|
'power': power}
|
|
validator_update = {'validator': validator,
|
|
'update_id': VALIDATOR_UPDATE_ID}
|
|
|
|
query.store_validator_update(conn, deepcopy(validator_update))
|
|
|
|
tx = Transaction.create([alice.public_key],
|
|
[([alice.public_key], 1)],
|
|
asset=None)\
|
|
.sign([alice.private_key])
|
|
|
|
code, message = b.write_transaction(tx, 'broadcast_tx_commit')
|
|
assert code == 202
|
|
time.sleep(5)
|
|
|
|
validators = b.get_validators()
|
|
validators = [(v['pub_key']['value'], v['voting_power']) for v in validators]
|
|
|
|
public_key64 = public_key_to_base64(public_key)
|
|
assert ((public_key64, str(power)) in validators)
|
|
|
|
|
|
@pytest.mark.abci
|
|
def test_post_transaction_responses(tendermint_ws_url, b):
|
|
from bigchaindb.common.crypto import generate_key_pair
|
|
from bigchaindb.models import Transaction
|
|
|
|
alice = generate_key_pair()
|
|
bob = generate_key_pair()
|
|
tx = Transaction.create([alice.public_key],
|
|
[([alice.public_key], 1)],
|
|
asset=None)\
|
|
.sign([alice.private_key])
|
|
|
|
code, message = b.write_transaction(tx, 'broadcast_tx_commit')
|
|
assert code == 202
|
|
|
|
tx_transfer = Transaction.transfer(tx.to_inputs(),
|
|
[([bob.public_key], 1)],
|
|
asset_id=tx.id)\
|
|
.sign([alice.private_key])
|
|
|
|
code, message = b.write_transaction(tx_transfer, 'broadcast_tx_commit')
|
|
assert code == 202
|
|
|
|
# NOTE: DOESN'T WORK (double spend)
|
|
# Tendermint crashes with error: Unexpected result type
|
|
# carly = generate_key_pair()
|
|
# double_spend = Transaction.transfer(tx.to_inputs(),
|
|
# [([carly.public_key], 1)],
|
|
# asset_id=tx.id)\
|
|
# .sign([alice.private_key])
|
|
# code, message = b.write_transaction(double_spend, 'broadcast_tx_commit')
|
|
# assert code == 500
|