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

Commit fc6a005

Browse files
author
Brord van Wierst
committed
Added step and bundlecreation
1 parent efd176d commit fc6a005

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

python-regression/tests/features/steps/transaction_steps.py

+28
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,34 @@ def create_inconsistent_transaction(step, node):
129129

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

132+
@step(r'a split bundle is generated referencing the previous transaction with:')
133+
def create_split_bundle(step):
134+
"""
135+
Create a bundle that reuses the last transaction from another bundle in its own
136+
137+
This test fails if we do not find the correct balance after confirming the second bundle(reattachment)
138+
:param step.hashes: A gherkin table present in the feature file specifying the
139+
arguments and the associated type.
140+
"""
141+
node = world.config['nodeId']
142+
previous = world.responses['evaluate_and_send'][node][0]
143+
seed = get_step_value(step, "seed")
144+
api = api_utils.prepare_api_call(node, seed=seed)
145+
146+
tag = get_step_value(step, "tag")[0]
147+
value = int(get_step_value(step, "value"))
148+
addressTo = get_step_value(step, "address")[0]
149+
150+
response = api.get_inputs(start=0, stop=1, threshold=0, security_level=3)
151+
addressFrom = response['inputs'][0]
152+
153+
bundles = bundle_scenario_setup.create_split_bundles(api, seed, addressFrom, addressTo, static.SPLIT_REST_ADDRESS, tag, value, previous)
154+
155+
api.broadcast_and_store(bundles[0].as_tryte_strings())
156+
api.broadcast_and_store(bundles[1].as_tryte_strings())
157+
158+
set_previous_transaction(node, [bundles[1][0].hash])
159+
set_world_object(node, "reattachSplitSpend", [bundles[1][0].hash])
132160

133161
@step(r'a stitching transaction is issued on "([^"]*)" with the tag "([^"]*)"')
134162
def issue_stitching_transaction(step, node, tag):

python-regression/util/transaction_bundle_logic/bundle_scenario_setup.py

+105-1
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,108 @@ def create_fake_transfer_bundle(api, seed, tag, value):
7979
bundle.add_inputs([Address(addresses[0], value, 0, 1), Address(addresses[1], value, 1, 1)])
8080
bundle.finalize()
8181
bundle.sign_inputs(KeyGenerator(seed))
82-
return bundle
82+
return bundle
83+
84+
def create_split_bundles(api, seedFrom, addressFrom, addressTo, addressRest, tag, value, reference):
85+
"""
86+
Create a bundle that reuses the last transaction form another bundle in its own
87+
88+
:param api: Api used to create and attach the first bundle
89+
:param seedfrom: The seed used for signing, addressFrom should be created form this
90+
:param addressFrom: The address we will use as input
91+
:param addressTo: The address we will use to send value to
92+
:param addressRest: Where the rest of the balance gets send to, if any
93+
:param tag: The tag that will be associated with the transaction
94+
:param value: The value we will send
95+
:param reference: The reference we use to connect the trunk with
96+
"""
97+
bundle1 = ProposedBundle()
98+
bundle1.add_transaction(ProposedTransaction(
99+
address = Address(addressTo),
100+
tag = Tag(tag),
101+
value = value
102+
))
103+
bundle1.add_inputs([Address(
104+
addressFrom,
105+
balance = addressFrom.balance,
106+
key_index = addressFrom.key_index,
107+
security_level = addressFrom.security_level
108+
),
109+
])
110+
bundle1.send_unspent_inputs_to(Address(addressRest))
111+
bundle1.finalize()
112+
bundle1.sign_inputs(KeyGenerator(seedFrom))
113+
114+
gtta_response = api.get_transactions_to_approve(3)
115+
116+
trunk = reference
117+
branch = gtta_response.get('branchTransaction')
118+
119+
attached_original_trytes = api.attach_to_tangle(trunk, branch, bundle1.as_tryte_strings()).get('trytes')
120+
121+
# So we have the original bundle attached, time to construct the new one
122+
# We need to re-attach, but take special care, so we dont use the api, rather we do it ourself
123+
124+
re_attached_trytes = custom_attach(attached_original_trytes, 14)
125+
126+
original_bundle = Bundle.from_tryte_strings(attached_original_trytes)
127+
128+
re_attached_bundle = Bundle.from_tryte_strings(re_attached_trytes)
129+
return [original_bundle, re_attached_bundle]
130+
131+
def custom_attach(trytes, mwm):
132+
"""
133+
Custom attach to to tangle.
134+
135+
Takes already attached bundle trytes, and except for the the head transaction,
136+
updates `attachment_timestamp` and re-does the pow, resulting in a new
137+
nonce and transaction hash.
138+
139+
The head transaction remains the same as in the original bundle.
140+
141+
:param trytes: List[TransactionTrytes]
142+
:param mwm: int
143+
"""
144+
# Install the pow package together with pyota:
145+
# $ pip install pyota[pow]
146+
from pow.ccurl_interface import get_powed_tx_trytes, get_hash_trytes, \
147+
get_current_ms
148+
149+
previoustx = None
150+
151+
# Construct bundle object
152+
bundle = Bundle.from_tryte_strings(trytes)
153+
154+
# and we need the head tx first
155+
for txn in reversed(bundle.transactions):
156+
if (not previoustx): # this is the head transaction
157+
# head tx stays the same, it is the original
158+
previoustx = txn.hash
159+
continue
160+
161+
# It is not a head transaction
162+
# only updae the trunk reference
163+
txn.trunk_transaction_hash = previoustx # the previous transaction
164+
txn.attachment_timestamp = get_current_ms()
165+
166+
# Let's do the pow locally
167+
txn_string = txn.as_tryte_string().__str__()
168+
# returns a python unicode string
169+
powed_txn_string = get_powed_tx_trytes(txn_string, mwm)
170+
# construct trytestring from python string
171+
powed_txn_trytes = TryteString(powed_txn_string)
172+
# compute transaction hash
173+
hash_string = get_hash_trytes(powed_txn_string)
174+
hash_trytes = TryteString(hash_string)
175+
hash_= TransactionHash(hash_trytes)
176+
177+
# Create powed txn object
178+
powed_txn = Transaction.from_tryte_string(
179+
trytes=powed_txn_trytes,
180+
hash_=hash_
181+
)
182+
183+
previoustx = powed_txn.hash
184+
# put that back in the bundle
185+
bundle.transactions[txn.current_index] = powed_txn
186+
return bundle.as_tryte_strings()

0 commit comments

Comments
 (0)