mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge pull request #793 from bigchaindb/modify-get-transaction
get_transaction will now return a tx from backlog, even if there are some in invalid blocks
This commit is contained in:
commit
04824df012
@ -189,19 +189,25 @@ class Bigchain(object):
|
||||
return False
|
||||
|
||||
def get_transaction(self, txid, include_status=False):
|
||||
"""Retrieve a transaction with `txid` from bigchain.
|
||||
"""Get the transaction with the specified `txid` (and optionally its status)
|
||||
|
||||
Queries the bigchain for a transaction, if it's in a valid or invalid
|
||||
block.
|
||||
This query begins by looking in the bigchain table for all blocks containing
|
||||
a transaction with the specified `txid`. If one of those blocks is valid, it
|
||||
returns the matching transaction from that block. Else if some of those
|
||||
blocks are undecided, it returns a matching transaction from one of them. If
|
||||
the transaction was found in invalid blocks only, or in no blocks, then this
|
||||
query looks for a matching transaction in the backlog table, and if it finds
|
||||
one there, it returns that.
|
||||
|
||||
Args:
|
||||
txid (str): transaction id of the transaction to query
|
||||
txid (str): transaction id of the transaction to get
|
||||
include_status (bool): also return the status of the transaction
|
||||
the return value is then a tuple: (tx, status)
|
||||
|
||||
Returns:
|
||||
A :class:`~.models.Transaction` instance if the transaction
|
||||
was found, otherwise ``None``.
|
||||
was found in a valid block, an undecided block, or the backlog table,
|
||||
otherwise ``None``.
|
||||
If :attr:`include_status` is ``True``, also returns the
|
||||
transaction's status if the transaction was found.
|
||||
"""
|
||||
@ -209,6 +215,7 @@ class Bigchain(object):
|
||||
response, tx_status = None, None
|
||||
|
||||
validity = self.get_blocks_status_containing_tx(txid)
|
||||
check_backlog = True
|
||||
|
||||
if validity:
|
||||
# Disregard invalid blocks, and return if there are no valid or undecided blocks
|
||||
@ -216,10 +223,14 @@ class Bigchain(object):
|
||||
if status != Bigchain.BLOCK_INVALID}
|
||||
if validity:
|
||||
|
||||
# The transaction _was_ found in an undecided or valid block,
|
||||
# so there's no need to look in the backlog table
|
||||
check_backlog = False
|
||||
|
||||
tx_status = self.TX_UNDECIDED
|
||||
# If the transaction is in a valid or any undecided block, return it. Does not check
|
||||
# if transactions in undecided blocks are consistent, but selects the valid block before
|
||||
# undecided ones
|
||||
# if transactions in undecided blocks are consistent, but selects the valid block
|
||||
# before undecided ones
|
||||
for target_block_id in validity:
|
||||
if validity[target_block_id] == Bigchain.BLOCK_VALID:
|
||||
tx_status = self.TX_VALID
|
||||
@ -228,8 +239,7 @@ class Bigchain(object):
|
||||
# Query the transaction in the target block and return
|
||||
response = self.backend.get_transaction_from_block(txid, target_block_id)
|
||||
|
||||
else:
|
||||
# Otherwise, check the backlog
|
||||
if check_backlog:
|
||||
response = self.backend.get_transaction_from_backlog(txid)
|
||||
|
||||
if response:
|
||||
|
@ -245,7 +245,7 @@ class TestBigchainApi(object):
|
||||
inputs = input_tx.to_inputs()
|
||||
tx = Transaction.transfer(inputs, [user_vk], input_tx.asset)
|
||||
tx = tx.sign([user_sk])
|
||||
b.write_transaction(tx)
|
||||
# There's no need to b.write_transaction(tx) to the backlog
|
||||
|
||||
# create block
|
||||
block = b.create_block([tx])
|
||||
@ -257,8 +257,37 @@ class TestBigchainApi(object):
|
||||
response = b.get_transaction(tx.id)
|
||||
|
||||
# should be None, because invalid blocks are ignored
|
||||
# and a copy of the tx is not in the backlog
|
||||
assert response is None
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_read_transaction_invalid_block_and_backlog(self, b, user_vk, user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
input_tx = b.get_owned_ids(user_vk).pop()
|
||||
input_tx = b.get_transaction(input_tx.txid)
|
||||
inputs = input_tx.to_inputs()
|
||||
tx = Transaction.transfer(inputs, [user_vk], input_tx.asset)
|
||||
tx = tx.sign([user_sk])
|
||||
|
||||
# Make sure there's a copy of tx in the backlog
|
||||
b.write_transaction(tx)
|
||||
|
||||
# create block
|
||||
block = b.create_block([tx])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
# vote the block invalid
|
||||
vote = b.vote(block.id, b.get_last_voted_block().id, False)
|
||||
b.write_vote(vote)
|
||||
|
||||
# a copy of the tx is both in the backlog and in an invalid
|
||||
# block, so get_transaction should return a transaction,
|
||||
# and a status of TX_IN_BACKLOG
|
||||
response, status = b.get_transaction(tx.id, include_status=True)
|
||||
assert tx.to_dict() == response.to_dict()
|
||||
assert status == b.TX_IN_BACKLOG
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_genesis_block(self, b):
|
||||
import rethinkdb as r
|
||||
|
Loading…
x
Reference in New Issue
Block a user