@@ -79,4 +79,108 @@ def create_fake_transfer_bundle(api, seed, tag, value):
79
79
bundle .add_inputs ([Address (addresses [0 ], value , 0 , 1 ), Address (addresses [1 ], value , 1 , 1 )])
80
80
bundle .finalize ()
81
81
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