mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
check if fulfillments are in a valid block (#629)
* check if fulfillments are in a valid block * documentation * fix almost all tests where tx validity is checked before writing to block * move import
This commit is contained in:
parent
73ed9c4f75
commit
81e70951d4
@ -188,7 +188,8 @@ class Bigchain(object):
|
|||||||
return self.validate_transaction(transaction)
|
return self.validate_transaction(transaction)
|
||||||
except (ValueError, exceptions.OperationError, exceptions.TransactionDoesNotExist,
|
except (ValueError, exceptions.OperationError, exceptions.TransactionDoesNotExist,
|
||||||
exceptions.TransactionOwnerError, exceptions.DoubleSpend,
|
exceptions.TransactionOwnerError, exceptions.DoubleSpend,
|
||||||
exceptions.InvalidHash, exceptions.InvalidSignature):
|
exceptions.InvalidHash, exceptions.InvalidSignature,
|
||||||
|
exceptions.FulfillmentNotInValidBlock):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_transaction(self, txid, include_status=False):
|
def get_transaction(self, txid, include_status=False):
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from bigchaindb_common.crypto import hash_data, VerifyingKey, SigningKey
|
from bigchaindb_common.crypto import hash_data, VerifyingKey, SigningKey
|
||||||
from bigchaindb_common.exceptions import (InvalidHash, InvalidSignature,
|
from bigchaindb_common.exceptions import (InvalidHash, InvalidSignature,
|
||||||
OperationError, DoubleSpend,
|
OperationError, DoubleSpend,
|
||||||
TransactionDoesNotExist)
|
TransactionDoesNotExist,
|
||||||
|
FulfillmentNotInValidBlock)
|
||||||
from bigchaindb_common.transaction import Transaction
|
from bigchaindb_common.transaction import Transaction
|
||||||
from bigchaindb_common.util import gen_timestamp, serialize
|
from bigchaindb_common.util import gen_timestamp, serialize
|
||||||
|
|
||||||
@ -45,11 +46,18 @@ class Transaction(Transaction):
|
|||||||
for ffill in self.fulfillments:
|
for ffill in self.fulfillments:
|
||||||
input_txid = ffill.tx_input.txid
|
input_txid = ffill.tx_input.txid
|
||||||
input_cid = ffill.tx_input.cid
|
input_cid = ffill.tx_input.cid
|
||||||
input_tx = bigchain.get_transaction(input_txid)
|
input_tx, status = bigchain.\
|
||||||
|
get_transaction(input_txid, include_status=True)
|
||||||
|
|
||||||
if input_tx is None:
|
if input_tx is None:
|
||||||
raise TransactionDoesNotExist("input `{}` doesn't exist"
|
raise TransactionDoesNotExist("input `{}` doesn't exist"
|
||||||
.format(input_txid))
|
.format(input_txid))
|
||||||
|
|
||||||
|
if status != bigchain.TX_VALID:
|
||||||
|
raise FulfillmentNotInValidBlock(
|
||||||
|
'input `{}` does not exist in a valid block'.format(
|
||||||
|
input_txid))
|
||||||
|
|
||||||
spent = bigchain.get_spent(input_txid, ffill.tx_input.cid)
|
spent = bigchain.get_spent(input_txid, ffill.tx_input.cid)
|
||||||
if spent and spent.id != self.id:
|
if spent and spent.id != self.id:
|
||||||
raise DoubleSpend('input `{}` was already spent'
|
raise DoubleSpend('input `{}` was already spent'
|
||||||
|
@ -11,7 +11,9 @@ import rethinkdb as r
|
|||||||
|
|
||||||
from bigchaindb import Bigchain
|
from bigchaindb import Bigchain
|
||||||
from bigchaindb.db import get_conn
|
from bigchaindb.db import get_conn
|
||||||
|
from bigchaindb_common import crypto
|
||||||
|
|
||||||
|
USER2_SK, USER2_VK = crypto.generate_key_pair()
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def restore_config(request, node_config):
|
def restore_config(request, node_config):
|
||||||
@ -104,11 +106,12 @@ def inputs(user_vk):
|
|||||||
# 1. create the genesis block
|
# 1. create the genesis block
|
||||||
b = Bigchain()
|
b = Bigchain()
|
||||||
try:
|
try:
|
||||||
b.create_genesis_block()
|
g = b.create_genesis_block()
|
||||||
except GenesisBlockAlreadyExistsError:
|
except GenesisBlockAlreadyExistsError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 2. create block with transactions for `USER` to spend
|
# 2. create blocks with transactions for `USER` to spend
|
||||||
|
prev_block_id = g.id
|
||||||
for block in range(4):
|
for block in range(4):
|
||||||
transactions = [
|
transactions = [
|
||||||
Transaction.create(
|
Transaction.create(
|
||||||
@ -117,3 +120,46 @@ def inputs(user_vk):
|
|||||||
]
|
]
|
||||||
block = b.create_block(transactions)
|
block = b.create_block(transactions)
|
||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# 3. vote the blocks valid, so that the inputs are valid
|
||||||
|
vote = b.vote(block.id, prev_block_id, True)
|
||||||
|
prev_block_id = block.id
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def user2_sk():
|
||||||
|
return USER2_SK
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def user2_vk():
|
||||||
|
return USER2_VK
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def inputs_shared(user_vk, user2_vk):
|
||||||
|
from bigchaindb.models import Transaction
|
||||||
|
from bigchaindb_common.exceptions import GenesisBlockAlreadyExistsError
|
||||||
|
# 1. create the genesis block
|
||||||
|
b = Bigchain()
|
||||||
|
try:
|
||||||
|
g = b.create_genesis_block()
|
||||||
|
except GenesisBlockAlreadyExistsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 2. create blocks with transactions for `USER` to spend
|
||||||
|
prev_block_id = g.id
|
||||||
|
for block in range(4):
|
||||||
|
transactions = [
|
||||||
|
Transaction.create(
|
||||||
|
[b.me], [user_vk, user2_vk], payload={'i': i}).sign([b.me_private])
|
||||||
|
for i in range(10)
|
||||||
|
]
|
||||||
|
block = b.create_block(transactions)
|
||||||
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# 3. vote the blocks valid, so that the inputs are valid
|
||||||
|
vote = b.vote(block.id, prev_block_id, True)
|
||||||
|
prev_block_id = block.id
|
||||||
|
b.write_vote(vote)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from time import sleep
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@ -556,6 +558,7 @@ class TestTransactionValidation(object):
|
|||||||
with pytest.raises(InvalidSignature):
|
with pytest.raises(InvalidSignature):
|
||||||
b.validate_transaction(tx)
|
b.validate_transaction(tx)
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_non_create_double_spend(self, b, signed_create_tx,
|
def test_non_create_double_spend(self, b, signed_create_tx,
|
||||||
signed_transfer_tx):
|
signed_transfer_tx):
|
||||||
from bigchaindb_common.exceptions import DoubleSpend
|
from bigchaindb_common.exceptions import DoubleSpend
|
||||||
@ -563,10 +566,20 @@ class TestTransactionValidation(object):
|
|||||||
block1 = b.create_block([signed_create_tx])
|
block1 = b.create_block([signed_create_tx])
|
||||||
b.write_block(block1)
|
b.write_block(block1)
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block1.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
b.write_transaction(signed_transfer_tx)
|
b.write_transaction(signed_transfer_tx)
|
||||||
block = b.create_block([signed_transfer_tx])
|
block = b.create_block([signed_transfer_tx])
|
||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
signed_transfer_tx.timestamp = 123
|
signed_transfer_tx.timestamp = 123
|
||||||
# FIXME: https://github.com/bigchaindb/bigchaindb/issues/592
|
# FIXME: https://github.com/bigchaindb/bigchaindb/issues/592
|
||||||
with pytest.raises(DoubleSpend):
|
with pytest.raises(DoubleSpend):
|
||||||
@ -595,6 +608,32 @@ class TestTransactionValidation(object):
|
|||||||
# bigchain
|
# bigchain
|
||||||
assert transfer_tx == b.validate_transaction(transfer_tx)
|
assert transfer_tx == b.validate_transaction(transfer_tx)
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
|
def test_fulfillment_not_in_valid_block(self, b, user_vk, user_sk):
|
||||||
|
from bigchaindb.models import Transaction
|
||||||
|
from bigchaindb_common.exceptions import FulfillmentNotInValidBlock
|
||||||
|
|
||||||
|
input_tx = b.get_owned_ids(user_vk).pop()
|
||||||
|
input_tx = b.get_transaction(input_tx.txid)
|
||||||
|
inputs = input_tx.to_inputs()
|
||||||
|
|
||||||
|
# create a transaction that's valid but not in a voted valid block
|
||||||
|
transfer_tx = Transaction.transfer(inputs, [user_vk])
|
||||||
|
transfer_tx = transfer_tx.sign([user_sk])
|
||||||
|
|
||||||
|
assert transfer_tx == b.validate_transaction(transfer_tx)
|
||||||
|
|
||||||
|
# create block
|
||||||
|
block = b.create_block([transfer_tx])
|
||||||
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# create transaction with the undecided input
|
||||||
|
tx_invalid = Transaction.transfer(transfer_tx.to_inputs(), [user_vk])
|
||||||
|
tx_invalid = tx_invalid.sign([user_sk])
|
||||||
|
|
||||||
|
with pytest.raises(FulfillmentNotInValidBlock):
|
||||||
|
b.validate_transaction(tx_invalid)
|
||||||
|
|
||||||
|
|
||||||
class TestBlockValidation(object):
|
class TestBlockValidation(object):
|
||||||
@pytest.mark.skipif(reason='Separated tx validation from block creation.')
|
@pytest.mark.skipif(reason='Separated tx validation from block creation.')
|
||||||
@ -695,67 +734,52 @@ class TestMultipleInputs(object):
|
|||||||
assert len(tx.fulfillments) == 1
|
assert len(tx.fulfillments) == 1
|
||||||
assert len(tx.conditions) == 1
|
assert len(tx.conditions) == 1
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_transfer_single_owners_multiple_inputs(self, b, user_sk, user_vk):
|
def test_transfer_single_owners_multiple_inputs(self, b, user_sk, user_vk):
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
user2_sk, user2_vk = crypto.generate_key_pair()
|
||||||
|
|
||||||
# TODO: Make this a fixture
|
|
||||||
transactions = []
|
|
||||||
for i in range(3):
|
|
||||||
tx = Transaction.create([user_vk], [user_vk])
|
|
||||||
tx = tx.sign([user_sk])
|
|
||||||
transactions.append(tx)
|
|
||||||
b.write_transaction(tx)
|
|
||||||
block = b.create_block(transactions)
|
|
||||||
b.write_block(block, durability='hard')
|
|
||||||
|
|
||||||
# get inputs
|
# get inputs
|
||||||
owned_inputs = b.get_owned_ids(user_vk)
|
owned_inputs = b.get_owned_ids(user_vk)
|
||||||
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
||||||
in owned_inputs]
|
in owned_inputs]
|
||||||
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
||||||
tx = Transaction.transfer(inputs, 3 * [[user_vk]])
|
tx = Transaction.transfer(inputs, len(inputs) * [[user_vk]])
|
||||||
tx = tx.sign([user_sk])
|
tx = tx.sign([user_sk])
|
||||||
assert b.validate_transaction(tx) == tx
|
assert b.validate_transaction(tx) == tx
|
||||||
assert len(tx.fulfillments) == 3
|
assert len(tx.fulfillments) == len(inputs)
|
||||||
assert len(tx.conditions) == 3
|
assert len(tx.conditions) == len(inputs)
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_transfer_single_owners_single_input_from_multiple_outputs(self, b,
|
def test_transfer_single_owners_single_input_from_multiple_outputs(self, b,
|
||||||
user_sk,
|
user_sk,
|
||||||
user_vk):
|
user_vk):
|
||||||
import random
|
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
user2_sk, user2_vk = crypto.generate_key_pair()
|
||||||
|
|
||||||
transactions = []
|
|
||||||
for i in range(3):
|
|
||||||
payload = {'somedata': random.randint(0, 255)}
|
|
||||||
tx = Transaction.create([user_vk], [user_vk], None, 'CREATE', payload)
|
|
||||||
tx = tx.sign([user_sk])
|
|
||||||
transactions.append(tx)
|
|
||||||
b.write_transaction(tx)
|
|
||||||
block = b.create_block(transactions)
|
|
||||||
b.write_block(block, durability='hard')
|
|
||||||
|
|
||||||
# get inputs
|
# get inputs
|
||||||
owned_inputs = b.get_owned_ids(user_vk)
|
owned_inputs = b.get_owned_ids(user_vk)
|
||||||
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
||||||
in owned_inputs]
|
in owned_inputs]
|
||||||
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
||||||
tx = Transaction.transfer(inputs, 3 * [[user2_vk]])
|
tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk]])
|
||||||
tx = tx.sign([user_sk])
|
tx = tx.sign([user_sk])
|
||||||
|
|
||||||
# create block with the transaction
|
# create block with the transaction
|
||||||
block = b.create_block([tx])
|
block = b.create_block([tx])
|
||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
# get inputs from user2
|
# get inputs from user2
|
||||||
owned_inputs = b.get_owned_ids(user2_vk)
|
owned_inputs = b.get_owned_ids(user2_vk)
|
||||||
assert len(owned_inputs) == 3
|
assert len(owned_inputs) == len(inputs)
|
||||||
|
|
||||||
# create a transaction with a single input from a multiple output transaction
|
# create a transaction with a single input from a multiple output transaction
|
||||||
tx_link = owned_inputs.pop()
|
tx_link = owned_inputs.pop()
|
||||||
@ -787,40 +811,38 @@ class TestMultipleInputs(object):
|
|||||||
assert len(tx.fulfillments) == 1
|
assert len(tx.fulfillments) == 1
|
||||||
assert len(tx.conditions) == 1
|
assert len(tx.conditions) == 1
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_single_owner_before_multiple_owners_after_multiple_inputs(self, b,
|
def test_single_owner_before_multiple_owners_after_multiple_inputs(self, b,
|
||||||
user_sk,
|
user_sk,
|
||||||
user_vk):
|
user_vk):
|
||||||
import random
|
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
user2_sk, user2_vk = crypto.generate_key_pair()
|
||||||
user3_sk, user3_vk = crypto.generate_key_pair()
|
user3_sk, user3_vk = crypto.generate_key_pair()
|
||||||
|
|
||||||
transactions = []
|
|
||||||
for i in range(3):
|
|
||||||
payload = {'somedata': random.randint(0, 255)}
|
|
||||||
tx = Transaction.create([user_vk], [user_vk], None, 'CREATE',
|
|
||||||
payload)
|
|
||||||
tx = tx.sign([user_sk])
|
|
||||||
transactions.append(tx)
|
|
||||||
b.write_transaction(tx)
|
|
||||||
block = b.create_block(transactions)
|
|
||||||
b.write_block(block, durability='hard')
|
|
||||||
|
|
||||||
owned_inputs = b.get_owned_ids(user_vk)
|
owned_inputs = b.get_owned_ids(user_vk)
|
||||||
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
input_txs = [b.get_transaction(tx_link.txid) for tx_link
|
||||||
in owned_inputs]
|
in owned_inputs]
|
||||||
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
inputs = sum([input_tx.to_inputs() for input_tx in input_txs], [])
|
||||||
|
|
||||||
tx = Transaction.transfer(inputs, 3 * [[user2_vk, user3_vk]])
|
tx = Transaction.transfer(inputs, len(inputs) * [[user2_vk, user3_vk]])
|
||||||
tx = tx.sign([user_sk])
|
tx = tx.sign([user_sk])
|
||||||
|
|
||||||
|
# create block with the transaction
|
||||||
|
block = b.create_block([tx])
|
||||||
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
# validate transaction
|
# validate transaction
|
||||||
assert b.is_valid_transaction(tx) == tx
|
assert b.is_valid_transaction(tx) == tx
|
||||||
assert len(tx.fulfillments) == 3
|
assert len(tx.fulfillments) == len(inputs)
|
||||||
assert len(tx.conditions) == 3
|
assert len(tx.conditions) == len(inputs)
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_multiple_owners_before_single_owner_after_single_input(self, b,
|
def test_multiple_owners_before_single_owner_after_single_input(self, b,
|
||||||
user_sk,
|
user_sk,
|
||||||
user_vk):
|
user_vk):
|
||||||
@ -835,6 +857,10 @@ class TestMultipleInputs(object):
|
|||||||
block = b.create_block([tx])
|
block = b.create_block([tx])
|
||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
owned_input = b.get_owned_ids(user_vk).pop()
|
owned_input = b.get_owned_ids(user_vk).pop()
|
||||||
input_tx = b.get_transaction(owned_input.txid)
|
input_tx = b.get_transaction(owned_input.txid)
|
||||||
inputs = input_tx.to_inputs()
|
inputs = input_tx.to_inputs()
|
||||||
@ -847,23 +873,15 @@ class TestMultipleInputs(object):
|
|||||||
assert len(transfer_tx.fulfillments) == 1
|
assert len(transfer_tx.fulfillments) == 1
|
||||||
assert len(transfer_tx.conditions) == 1
|
assert len(transfer_tx.conditions) == 1
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs_shared')
|
||||||
def test_multiple_owners_before_single_owner_after_multiple_inputs(self, b,
|
def test_multiple_owners_before_single_owner_after_multiple_inputs(self, b,
|
||||||
user_sk,
|
user_sk, user_vk, user2_vk, user2_sk):
|
||||||
user_vk):
|
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
# create a new users
|
||||||
user3_sk, user3_vk = crypto.generate_key_pair()
|
user3_sk, user3_vk = crypto.generate_key_pair()
|
||||||
|
|
||||||
transactions = []
|
|
||||||
for i in range(3):
|
|
||||||
tx = Transaction.create([b.me], [user_vk, user2_vk])
|
|
||||||
tx = tx.sign([b.me_private])
|
|
||||||
transactions.append(tx)
|
|
||||||
block = b.create_block(transactions)
|
|
||||||
b.write_block(block, durability='hard')
|
|
||||||
|
|
||||||
tx_links = b.get_owned_ids(user_vk)
|
tx_links = b.get_owned_ids(user_vk)
|
||||||
inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link
|
inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link
|
||||||
in tx_links], [])
|
in tx_links], [])
|
||||||
@ -872,9 +890,10 @@ class TestMultipleInputs(object):
|
|||||||
tx = tx.sign([user_sk, user2_sk])
|
tx = tx.sign([user_sk, user2_sk])
|
||||||
|
|
||||||
assert b.is_valid_transaction(tx) == tx
|
assert b.is_valid_transaction(tx) == tx
|
||||||
assert len(tx.fulfillments) == 3
|
assert len(tx.fulfillments) == len(inputs)
|
||||||
assert len(tx.conditions) == 3
|
assert len(tx.conditions) == len(inputs)
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_multiple_owners_before_multiple_owners_after_single_input(self, b,
|
def test_multiple_owners_before_multiple_owners_after_single_input(self, b,
|
||||||
user_sk,
|
user_sk,
|
||||||
user_vk):
|
user_vk):
|
||||||
@ -890,6 +909,11 @@ class TestMultipleInputs(object):
|
|||||||
block = b.create_block([tx])
|
block = b.create_block([tx])
|
||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
|
# vote block valid
|
||||||
|
vote = b.vote(block.id, b.get_last_voted_block().id, True)
|
||||||
|
b.write_vote(vote)
|
||||||
|
|
||||||
|
# get input
|
||||||
tx_link = b.get_owned_ids(user_vk).pop()
|
tx_link = b.get_owned_ids(user_vk).pop()
|
||||||
tx_input = b.get_transaction(tx_link.txid).to_inputs()
|
tx_input = b.get_transaction(tx_link.txid).to_inputs()
|
||||||
|
|
||||||
@ -900,25 +924,17 @@ class TestMultipleInputs(object):
|
|||||||
assert len(tx.fulfillments) == 1
|
assert len(tx.fulfillments) == 1
|
||||||
assert len(tx.conditions) == 1
|
assert len(tx.conditions) == 1
|
||||||
|
|
||||||
def test_multiple_owners_before_multiple_owners_after_multiple_inputs(self,
|
@pytest.mark.usefixtures('inputs_shared')
|
||||||
b,
|
def test_multiple_owners_before_multiple_owners_after_multiple_inputs(self, b,
|
||||||
user_sk,
|
user_sk, user_vk,
|
||||||
user_vk):
|
user2_sk, user2_vk):
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
# create a new users
|
||||||
user3_sk, user3_vk = crypto.generate_key_pair()
|
user3_sk, user3_vk = crypto.generate_key_pair()
|
||||||
user4_sk, user4_vk = crypto.generate_key_pair()
|
user4_sk, user4_vk = crypto.generate_key_pair()
|
||||||
|
|
||||||
transactions = []
|
|
||||||
for i in range(3):
|
|
||||||
tx = Transaction.create([b.me], [user_vk, user2_vk])
|
|
||||||
tx = tx.sign([b.me_private])
|
|
||||||
transactions.append(tx)
|
|
||||||
block = b.create_block(transactions)
|
|
||||||
b.write_block(block, durability='hard')
|
|
||||||
|
|
||||||
tx_links = b.get_owned_ids(user_vk)
|
tx_links = b.get_owned_ids(user_vk)
|
||||||
inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link
|
inputs = sum([b.get_transaction(tx_link.txid).to_inputs() for tx_link
|
||||||
in tx_links], [])
|
in tx_links], [])
|
||||||
@ -927,8 +943,8 @@ class TestMultipleInputs(object):
|
|||||||
tx = tx.sign([user_sk, user2_sk])
|
tx = tx.sign([user_sk, user2_sk])
|
||||||
|
|
||||||
assert b.is_valid_transaction(tx) == tx
|
assert b.is_valid_transaction(tx) == tx
|
||||||
assert len(tx.fulfillments) == 3
|
assert len(tx.fulfillments) == len(inputs)
|
||||||
assert len(tx.conditions) == 3
|
assert len(tx.conditions) == len(inputs)
|
||||||
|
|
||||||
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_vk):
|
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_vk):
|
||||||
from bigchaindb_common import crypto
|
from bigchaindb_common import crypto
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import rethinkdb as r
|
import rethinkdb as r
|
||||||
@ -285,9 +287,10 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b):
|
|||||||
vote_pipeline = vote.create_pipeline()
|
vote_pipeline = vote.create_pipeline()
|
||||||
vote_pipeline.setup(indata=inpipe, outdata=outpipe)
|
vote_pipeline.setup(indata=inpipe, outdata=outpipe)
|
||||||
|
|
||||||
inpipe.put(block.to_dict())
|
|
||||||
inpipe.put(block2.to_dict())
|
|
||||||
vote_pipeline.start()
|
vote_pipeline.start()
|
||||||
|
inpipe.put(block.to_dict())
|
||||||
|
time.sleep(1)
|
||||||
|
inpipe.put(block2.to_dict())
|
||||||
vote_out = outpipe.get()
|
vote_out = outpipe.get()
|
||||||
vote2_out = outpipe.get()
|
vote2_out = outpipe.get()
|
||||||
vote_pipeline.terminate()
|
vote_pipeline.terminate()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user