Skip to content
This repository was archived by the owner on Jan 13, 2023. It is now read-only.

Commit 5ce1c99

Browse files
committed
[#10] Completed multisig example script.
1 parent 6909773 commit 5ce1c99

File tree

4 files changed

+61
-8
lines changed

4 files changed

+61
-8
lines changed

examples/multisig.py

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
from typing import List
1717

18-
from iota import Address, ProposedTransaction, Tag, TransactionTrytes, \
19-
TryteString
20-
from iota.crypto.types import Digest, Seed
18+
from iota import Address, Bundle, BundleValidator, ProposedTransaction, Tag, \
19+
TransactionTrytes, TryteString
20+
from iota.crypto.types import Digest, PrivateKey, Seed
2121
from iota.multisig import MultisigIota
2222
from iota.multisig.types import MultisigAddress
2323

@@ -181,10 +181,59 @@
181181
182182
Note that we must apply signatures in the same order as when we created
183183
the multisig address!
184+
185+
This step normally happens on separate computers, so that participants
186+
don't have to share their private keys (except when doing m-of-n).
187+
188+
https://github.com/iotaledger/wiki/blob/master/multisigs.md#how-m-of-n-works
189+
190+
For this example, the structure of the bundle looks like this:
191+
192+
- Transaction 0: Spend IOTAs.
193+
- Transactions 1-8: Transactions that will hold the signature
194+
fragments for the multisig input:
195+
- 1-3: Generated from ``digest_1`` (security level 3).
196+
- 4-6: Generated from ``digest_2`` (security level 3).
197+
- 7-8: Generated from ``digest_3`` (security level 2).
198+
199+
Note that transactions 1-8 don't have signatures yet; we need the
200+
corresponding private keys in order to create those!
184201
"""
185-
# :todo:
186-
signed_trytes = None # type: List[TransactionTrytes]
202+
bundle = Bundle.from_tryte_strings(prepared_trytes)
203+
204+
# Note that we must use the same parameters that we provided to the
205+
# ``get_digests`` method, in order to generate the correct value to
206+
# sign the input!
207+
gpk_result = api_1.get_private_keys(index=0, count=1, security_level=3)
208+
private_key_1 = gpk_result['keys'][0] # type: PrivateKey
209+
private_key_1.sign_input_transactions(bundle, 1)
210+
211+
gpk_result = api_2.get_private_keys(index=42, count=1, security_level=3)
212+
private_key_2 = gpk_result['keys'][0] # type: PrivateKey
213+
private_key_2.sign_input_transactions(bundle, 4)
187214

215+
gpk_result = api_3.get_private_keys(index=8, count=1, security_level=2)
216+
private_key_3 = gpk_result['keys'][0] # type: PrivateKey
217+
private_key_3.sign_input_transactions(bundle, 7)
218+
219+
# Once we've applied the signatures, convert the Bundle back into tryte
220+
# sequences so that we can broadcast them to the tangle.
221+
signed_trytes = bundle.as_tryte_strings()
222+
223+
"""
224+
Step 4.5 (Optional): Validate the signatures.
225+
226+
This step is purely optional. We are including it in this example
227+
script so that you can see that the resulting signature fragments are
228+
valid.
229+
"""
230+
validator = BundleValidator(bundle)
231+
if not validator.is_valid():
232+
raise ValueError(
233+
'Bundle failed validation:\n{errors}'.format(
234+
errors = '\n'.join((' - ' + e) for e in validator.errors),
235+
),
236+
)
188237

189238
"""
190239
Step 5: Broadcast the bundle.

iota/crypto/types.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,13 @@ def get_digest(self):
181181

182182
return Digest(TryteString.from_trits(digest), self.key_index)
183183

184-
def sign_bundle_at(self, bundle, start_index):
184+
def sign_input_transactions(self, bundle, start_index):
185185
# type: (Bundle, int) -> None
186186
"""
187-
Signs the input at the specified index.
187+
Signs the inputs starting at the specified index.
188+
189+
:param bundle:
190+
The bundle that contains the input transactions to sign.
188191
189192
:param start_index:
190193
The index of the first input transaction.

iota/multisig/commands/prepare_multisig_transfer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import List, Optional
66

77
import filters as f
8+
89
from iota import Address, ProposedTransaction
910
from iota.commands import FilterCommand, RequestFilter
1011
from iota.commands.core import GetBalancesCommand

iota/transaction/creation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def sign_input_at(self, start_index, private_key):
404404
if not self.hash:
405405
raise RuntimeError('Cannot sign inputs until bundle is finalized.')
406406

407-
private_key.sign_bundle_at(self, start_index)
407+
private_key.sign_input_transactions(self, start_index)
408408

409409
def _create_input_transactions(self, addy):
410410
# type: (Address) -> None

0 commit comments

Comments
 (0)