Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Test: (In)valid bundle regressions #1784

Open
wants to merge 29 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ Feature: Test Bootstrapping With LS
|keys |values |type |
|state |True |bool |


Scenario: Old transactions are pruned
Takes a node with a large db and transaction pruning enabled, and checks to make sure that the transactions below
the pruning depth are no longer present.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Feature: Test transaction confirmation
Scenario: Zero Value Transactions are confirmed
In this test, a number of zero value transactions will be made to a specified node.
A milestone will be issued that references these transactions, and this should
confirm the transations.
confirm the transactions.

Given "10" transactions are issued on "nodeA-m3" with:
|keys |values |type |
Expand All @@ -12,7 +12,7 @@ Feature: Test transaction confirmation
|tag |ZERO9VALUE |string |

#In the default DB, the current index is 50. The next milestone issued should be 51.
When a milestone is issued with index 51 and references:
Then a milestone is issued with index 51 and references:
|keys |values |type |
|transactions |evaluate_and_send |responseValue |

Expand Down Expand Up @@ -43,11 +43,10 @@ Feature: Test transaction confirmation
| keys | values | type |
| states | False | boolListMixed |


Scenario: Value Transactions are confirmed
In this test, a number of value transactions will be made to a specified node.
A milestone will be issued that references these transactions, and this should
confirm the transations.
confirm the transactions.

Given "10" transactions are issued on "nodeA-m3" with:
|keys |values |type |
Expand All @@ -57,7 +56,7 @@ Feature: Test transaction confirmation
|tag |VALUE9TRANSACTION |string |

#In the default test, the latest sent index will be 51. The next milestone issued should be 52.
When a milestone is issued with index 52 and references:
Then a milestone is issued with index 52 and references:
|keys |values |type |
|transactions |evaluate_and_send |responseValue |

Expand Down Expand Up @@ -87,3 +86,73 @@ Feature: Test transaction confirmation
| keys | values | type |
| states | False | boolListMixed |

Scenario: Valid value transfer bundle that doesnt affect ledger state
We want to ascertain that ledger state is always calculated correctly.
Even in the presence of a bundle that handles funds but without changing address

Given "1" transaction is issued on "nodeA-m3" with:
|keys |values |type |
|address |TEST_ADDRESS |staticValue |
|value |0 |int |
|tag |ZERO9VALUE |string |

And a value bundle which moves funds back and forth from an address is generated referencing the previous transaction with:
|keys |values |type |
|seed |THE_BANK |staticList |
|value |100 |int |
|tag |FAKE9VALUE |string |

And a transaction is issued referencing the previous transaction
|keys |values |type |
|seed |THE_BANK |staticList |
|address |TEST_ADDRESS |staticValue |
|value |11 |int |
|tag |VALUE9TRANSACTION |string |

#In the default test, the latest sent index will be 52. The next milestone issued should be 53.
Then a milestone is issued with index 53 and references:
|keys |values |type |
|transactions |previousTransaction |responseValue |

#Give the node time to solidify the milestone
And we wait "15" second/seconds

When "getBalances" is called on "nodeA-m3" with:
|keys |values |type |
|addresses |FAKE_SPEND_ADDRESSES |staticList |

Then the response for "getBalances" should return with:
|keys |values |type |
|balances |0 |int |

Scenario: Double spend only affects the ledger once
We want to ascertain that ledger state is always calculated correctly.
Even in the presence of double spend, the confirmed state should have spent only once

Given "1" transaction is issued on "nodeA-m3" with:
|keys |values |type |
|address |TEST_ADDRESS |staticValue |
|value |0 |int |
|tag |ZERO9VALUE |string |

And a double spend is generated referencing the previous transaction with:
|keys |values |type |
|seed |DOUBLE_SPEND_SEED |staticValue |
|value |1000 |int |
|tag |FAKE9VALUE |string |

#In the default test, the latest sent index will be 53. The next milestone issued should be 54.
Then a milestone is issued with index 54 and references:
|keys |values |type |
|transactions |firstDoubleSpend |responseValue |

#Give the node time to solidify the milestone
And we wait "15" second/seconds

When "getBalances" is called on "nodeA-m3" with:
|keys |values |type |
|addresses |DOUBLE_SPEND_ADDRESSES |staticList |

Then the response for "getBalances" should return with:
|keys |values |type |
|balances |1000 0 |intList |
4 changes: 2 additions & 2 deletions python-regression/tests/features/machine3/config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defaults: &transaction_tests_config_files
db: https://s3.eu-central-1.amazonaws.com/iotaledger-dbfiles/dev/Transactions_Tests_db.tar
db_checksum: 756237276479da4b01deaa0c1211ca65a4c8ec6f081452ea7e8153648c53bd67
db: https://s3.eu-central-1.amazonaws.com/iotaledger-dbfiles/dev/TransactionsTestsDb.tar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the change to this DB documented?
Talk to @DyrellC about how to document this

db_checksum: 4d94ae65b38ea0f8461d5ec24e5140b20eb86590d54e87e30aa9a72b26a131be
iri_args: ['--testnet-coordinator',
'EFPNKGPCBXXXLIBYFGIGYBYTFFPIOQVNNVVWTTIYZO9NFREQGVGDQQHUUQ9CLWAEMXVDFSSMOTGAHVIBH',
'--milestone-start',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Feature: Test API calls on Machine 1
Given "getBalances" is called on "nodeA-m4" with:
|keys |values |type |
|addresses |TEST_EMPTY_ADDRESS |staticList |
|threshold |100 |int |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should have been part of #1768
usually I would say to move this to another PR but I am getting soft

|threshold |100 |int |

Then the response for "getBalances" should return with:
|keys |values |type |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,12 @@ def check_response_for_value(step, api_call):
expected_values = {}
args = step.hashes
api_utils.prepare_options(args, expected_values)

for expected_value_key in expected_values:
if expected_value_key in response_values:
expected_value = expected_values[expected_value_key]
response_value = response_values[expected_value_key]

if isinstance(response_value, list) and api_call != 'getTrytes' and api_call != 'getInclusionStates':
if isinstance(response_value, list) and isinstance(expected_value, list) != True and api_call != 'getTrytes' and api_call != 'getInclusionStates':
response_value = response_value[0]

assert expected_value == response_value, "The expected value {} does not match""\
Expand Down
111 changes: 97 additions & 14 deletions python-regression/tests/features/steps/transaction_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from util import static_vals as static
from util import logger as log
from util.test_logic import api_test_logic as api_utils
from util.transaction_bundle_logic import transaction_logic as transactions
from util.transaction_bundle_logic import bundle_scenario_setup, transaction_logic as transactions
from util.milestone_logic import milestones
from time import sleep

Expand Down Expand Up @@ -32,6 +32,78 @@ def generate_transaction_and_attach(step, node):
setattr(static, "TEST_STORE_TRANSACTION", transaction.get('trytes'))
return transaction

@step(r'a value bundle which moves funds back and forth from an address is generated referencing the previous transaction with:')
def fake_value_transaction(step):
"""
Creates a bundle that both receives and sends value between 2 addresses.
This makes the total ledger change zero
:param step.hashes: A gherkin table present in the feature file specifying the
arguments and the associated type.
"""

node = world.config['nodeId']
previous = world.responses['evaluate_and_send'][node][0]

seed = get_step_value(step, "seed")[0]
api = api_utils.prepare_api_call(node, seed=seed)

logger.info('Finding Transactions')
gtta_transactions = api.get_transactions_to_approve(depth=3)

trunk = previous
branch = gtta_transactions['branchTransaction']

value = int(get_step_value(step, "value"))
tag = get_step_value(step, "tag")

bundle = bundle_scenario_setup.create_fake_transfer_bundle(api, seed, tag, value)

argument_list = {'trunk_transaction': trunk, 'branch_transaction': branch,
'trytes': bundle.as_tryte_strings(), 'min_weight_magnitude': 14}

bundle = transactions.attach_store_and_broadcast(api, argument_list)
transaction_trytes = bundle.get('trytes')
transaction_hash = Transaction.from_tryte_string(transaction_trytes[0])
set_previous_transaction(node, [transaction_hash.hash])

@step(r'a double spend is generated referencing the previous transaction with:')
def create_double_spent(step):
"""
Creates two bundles which both try to spend the same address.
This test fails if they are both confirmed
:param step.hashes: A gherkin table present in the feature file specifying the
arguments and the associated type.
"""
node = world.config['nodeId']
previous = world.responses['evaluate_and_send'][node][0]
seed = get_step_value(step, "seed")
api = api_utils.prepare_api_call(node, seed=seed)

tag = get_step_value(step, "tag")[0]
value = int(get_step_value(step, "value"))

response = api.get_inputs(start=0, stop=1, threshold=0, security_level=2)
addressFrom = response['inputs'][0]

bundles = bundle_scenario_setup.create_double_spend_bundles(seed, addressFrom, static.DOUBLE_SPEND_ADDRESSES[0], static.DOUBLE_SPEND_ADDRESSES[1], tag, value)

logger.info('Finding Transactions')
gtta_transactions = api.get_transactions_to_approve(depth=3)
trunk1 = previous
branch1 = gtta_transactions['branchTransaction']
trunk2 = previous
branch2 = gtta_transactions['trunkTransaction']

argument_list = {'trunk_transaction': trunk1, 'branch_transaction': branch1,
'trytes': bundles[0].as_tryte_strings(), 'min_weight_magnitude': 14}
firstDoubleSpend = Transaction.from_tryte_string( transactions.attach_store_and_broadcast(api, argument_list).get('trytes')[0] )

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

argument_list = {'trunk_transaction': trunk2, 'branch_transaction': branch2,
'trytes': bundles[1].as_tryte_strings(), 'min_weight_magnitude': 14}
secondDoubleSpend = Transaction.from_tryte_string( transactions.attach_store_and_broadcast(api, argument_list).get('trytes')[0] )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


set_previous_transaction(node, [firstDoubleSpend.hash])
set_world_object(node, "firstDoubleSpend", [firstDoubleSpend.hash])

@step(r'an inconsistent transaction is generated on "([^"]+)"')
def create_inconsistent_transaction(step, node):
Expand All @@ -55,10 +127,7 @@ def create_inconsistent_transaction(step, node):
transaction_trytes = transaction.get('trytes')
transaction_hash = Transaction.from_tryte_string(transaction_trytes[0])

if 'inconsistentTransactions' not in world.responses:
world.responses['inconsistentTransactions'] = {}
world.responses['inconsistentTransactions'][node] = transaction_hash.hash

set_world_object(node, 'inconsistentTransactions', transaction_hash.hash)

@step(r'a stitching transaction is issued on "([^"]*)" with the tag "([^"]*)"')
def issue_stitching_transaction(step, node, tag):
Expand All @@ -84,10 +153,7 @@ def issue_stitching_transaction(step, node, tag):

# Finds transaction hash and stores it in world
bundlehash = api.find_transactions(bundles=[bundle.hash])
if 'previousTransaction' not in world.responses:
world.responses['previousTransaction'] = {}
world.responses['previousTransaction'][node] = bundlehash['hashes'][0]

set_previous_transaction(node, bundlehash['hashes'][0])

@step(r'a transaction is issued referencing the previous transaction')
def reference_stitch_transaction(step):
Expand All @@ -99,13 +165,16 @@ def reference_stitch_transaction(step):

transaction_bundle = transactions.create_transaction_bundle(referencing_address, 'REFERENCE9TAG', 0)
branch = api.get_transactions_to_approve(depth=3)['branchTransaction']
options = {'trunk_transaction': stitch, 'branch_transaction': branch, 'trytes':
options = {'trunk_transaction': stitch[0], 'branch_transaction': branch, 'trytes':
transaction_bundle.as_tryte_strings(), 'min_weight_magnitude': 9}

transactions.attach_store_and_broadcast(api, options)
transaction = transactions.attach_store_and_broadcast(api, options)
transaction_trytes = transaction.get('trytes')
transaction_hash = Transaction.from_tryte_string(transaction_trytes[0])

set_previous_transaction(node, [transaction_hash.hash])

@step(r'"(\d+)" transactions are issued on "([^"]+)" with:')
@step(r'"(\d+)" transactions? (?:is|are) issued on "([^"]+)" with:')
def issue_multiple_transactions(step, num_transactions, node):
transactions_to_store = []
world.responses['evaluate_and_send'] = {}
Expand Down Expand Up @@ -154,7 +223,6 @@ def issue_a_milestone_with_reference(step, index):

milestones.update_latest_milestone(world.config, node, milestone)


@step(r'the next (\d+) milestones are issued')
def issue_several_milestones(step, num_milestones):
node = world.config['nodeId']
Expand All @@ -170,7 +238,6 @@ def issue_several_milestones(step, num_milestones):
#Give node a moment to update solid milestone
wait_for_update(index, api)


@step(r'milestone (\d+) is issued on "([^"]+)"')
def issue_a_milestone(step, index, node):
"""
Expand All @@ -193,6 +260,22 @@ def issue_a_milestone(step, index, node):
milestone_hash2 = Transaction.from_tryte_string(milestone['trytes'][1]).hash
world.config['latestMilestone'][node] = [milestone_hash, milestone_hash2]

def set_previous_transaction(node, txHash):
set_world_object(node, 'previousTransaction', txHash)

def set_world_object(node, objectName, value):
if objectName not in world.responses:
world.responses[objectName] = {}
world.responses[objectName][node] = value

def get_step_value(step, key_name):
for arg_index, arg in enumerate(step.hashes):
if arg['keys'] == key_name :
if arg['type'] == "staticValue" or arg['type'] == "staticList":
return getattr(static, arg['values'])
else:
return arg['values']
return 0

def wait_for_update(index, api):
updated = False
Expand Down
10 changes: 10 additions & 0 deletions python-regression/util/static_vals.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
"THIS9TEST9ADDRESS9HAS9ONE9HUNDRED9IOTA9NINE99999999999999999999999999999999999999",
"THIS9TEST9ADDRESS9HAS9ONE9HUNDRED9IOTA9TEN999999999999999999999999999999999999999"]

FAKE_SPEND_ADDRESSES = ["CTCFZQHZ9MVOQVKOASZJFFQYCYSUZOIXFUDGBNQQWNUVNYXJVOYHMQPJVVKNICNRCUDEWXJIEDKXCLVWY",
"DRDSKHQ9XHRFMXXHTGZPGUIKWVQYSDQDPUTHEUXEROVUTAQDRCJIWLARCTAQHMYAUVNYNVCEBD9QNC9SD"]

DOUBLE_SPEND_SEED = "THIS9DOUBLE9SPEND9ADDRESS9HAS9ONE9THOUSAND9IOTA9999999999999999999999999999999999"
DOUBLE_SPEND_ADDRESSES = ["YIYPLJDLF9MNSCAORRGFNJNDXOFQZXEXTPDD9TROXZCJPY9AWDTIJY9RKIPLUDPFPLKZRP9NKHPKBJAYA",
"DHGTQLJRYMJTHSYGKCAJYMMWHYYM9XKGYMMKYLEUWOQOAMORGTSWMRHVZ9VKPRTDUGUPBKRB9WMQOBRHY"]

SPLIT_BUNDLE_SEED = "THIS9SPLIT9BUNDLE9ADDRESS9HAS9ONE9THOUSAND9IOTA9999999999999999999999999999999999"
SPLIT_TO_ADDRESS = ["9JMLFZINDAQ99YYDWSYDZMADO9PHWTIZOXHKTSNYFMFMFOQVNAWCATWECJBRYRGPHMBZHYAPTQFFEWZKC"]
SPLIT_REST_ADDRESS = "USUXAWWGZSEJICZQJSMJSEYBBDOPGBJFEOYAMDMXKZAOPDDJBMUXIETNYXGRFWWROIOTRDYODJEALZRE9"

SIDE_TANGLE_ADDRESS = "SIDE9TANGLE9999999999999999999999999999999999999999999999999999999999999999999999"
STITCHING_ADDRESS = "STITCHING9TRANSACTIONS99999999999999999999999999999999999999999999999999999999999"
Expand Down
4 changes: 3 additions & 1 deletion python-regression/util/test_logic/api_test_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def prepare_options(args, option_list):

fetch_list = {
'int': value_fetch.fetch_int,
'intList': value_fetch.fetch_int_list,
'string': value_fetch.fetch_string,
'list': value_fetch.fetch_list,
'nodeAddress': value_fetch.fetch_node_address,
Expand Down Expand Up @@ -136,7 +137,8 @@ def fetch_call(api_call, api, options):
try:
response = call_list[api_call](**options)
except ValueError as e:
logger.error(str(e))
if "filter_errors" in e.context:
logger.info(e.context["filter_errors"])
response = None

return response
Expand Down
13 changes: 12 additions & 1 deletion python-regression/util/test_logic/value_fetch_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ def fetch_int(value):
"""
return int(value)

def fetch_int_list(value):
"""
Returns an array of int representations of the input value.
:param value: The input value
:return: The int list
"""
int_list = value.split()
return [int(x) for x in int_list]

def fetch_string(value):
"""
Expand Down Expand Up @@ -95,7 +103,10 @@ def fetch_static_list(value):
:return: The stored object in list format
"""
static_value = getattr(static, value)
return [static_value]
if isinstance(static_value, list):
return static_value
else:
return [static_value]


def fetch_bool(value):
Expand Down
3 changes: 1 addition & 2 deletions python-regression/util/threading_logic/pool_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@ def fetch_results(future_result, timeout):
logger.debug('Response: {}'.format(response))
return response
except Exception as err:
logger.debug(err)
logger.info(err)
logger.error(err)
Loading