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

Commit 76e72d0

Browse files
committed
[#61] Refactored BundleValidatorTestCase.
1 parent a6ecf24 commit 76e72d0

File tree

2 files changed

+241
-332
lines changed

2 files changed

+241
-332
lines changed

iota/transaction/validator.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from typing import Generator, List, Optional, Text, Tuple
66

7-
from iota.crypto import Curl
87
from iota.crypto.kerl import Kerl
98
from iota.crypto.signing import validate_signature_fragments
109
from iota.transaction.base import Bundle, Transaction
@@ -13,6 +12,20 @@
1312
'BundleValidator',
1413
]
1514

15+
16+
#
17+
# In very rare cases, the IOTA protocol may switch hash algorithms.
18+
# When this happens, the IOTA Foundation will create a snapshot, so
19+
# that all new objects on the Tangle use the new hash algorithm.
20+
#
21+
# However, the snapshot will still contain references to addresses
22+
# created using the legacy hash algorithm, so the bundle validator has
23+
# to be able to use that as a fallback when validation fails.
24+
#
25+
SUPPORTED_SPONGE = Kerl
26+
LEGACY_SPONGE = None # Curl
27+
28+
1629
class BundleValidator(object):
1730
"""
1831
Checks a bundle and its transactions for problems.
@@ -129,7 +142,7 @@ def _create_validator(self):
129142
# Input is malformed; signature fragments after the first
130143
# should have zero value.
131144
yield (
132-
'Transaction {i} has invalid amount '
145+
'Transaction {i} has invalid value '
133146
'(expected 0, actual {actual}).'.format(
134147
actual = txn.value,
135148

@@ -171,40 +184,42 @@ def _get_bundle_signature_errors(self, groups):
171184
:return:
172185
List of error messages. If empty, signature fragments are valid.
173186
"""
174-
# Start with Kerl. If we encounter any errors, we'll go back and
175-
# try again with Curl instead.
176-
# Note that we keep track of how far we got with Kerl; this will be
177-
# important later.
178-
kerl_pos = None
179-
kerl_errors = []
180-
181-
for kerl_pos, group in enumerate(groups): # type: Tuple[int, List[Transaction]]
182-
error = self._get_group_signature_error(group, Kerl)
187+
# Start with the currently-supported hash algo.
188+
current_pos = None
189+
current_errors = []
190+
for current_pos, group in enumerate(groups): # type: Tuple[int, List[Transaction]]
191+
error = self._get_group_signature_error(group, SUPPORTED_SPONGE)
183192
if error:
184-
kerl_errors.append(error)
193+
current_errors.append(error)
194+
195+
# Pause and retry with the legacy algo.
185196
break
186197

187-
# If Kerl failed, then go back and try with Curl.
188-
if kerl_errors:
198+
# If validation failed, then go back and try with the legacy algo
199+
# (only applies if we are currently transitioning to a new algo).
200+
if current_errors and LEGACY_SPONGE:
189201
for group in groups:
190-
if self._get_group_signature_error(group, Curl):
191-
# Curl doesn't work, either; no point in continuing.
202+
# noinspection PyTypeChecker
203+
if self._get_group_signature_error(group, LEGACY_SPONGE):
204+
# Legacy algo doesn't work, either; no point in continuing.
192205
break
193206
else:
194207
# If we get here, then we were able to validate the signature
195-
# fragments successfully using Curl.
208+
# fragments successfully using the legacy algorithm.
196209
return []
197210

198-
# If we get here, then Curl validation failed.
199-
# We know that the bundle is invalid, but we will continue
200-
# validating with Kerl, so that we can return an error message for
201-
# each invalid input.
202-
kerl_errors.extend(filter(None, (
203-
self._get_group_signature_error(group, Kerl)
204-
for group in groups[kerl_pos+1:]
211+
# If we get here, then validation also failed when using the legacy
212+
# algorithm.
213+
214+
# At this point, we know that the bundle is invalid, but we will
215+
# continue validating with the supported algorithm anyway, so that
216+
# we can return an error message for every invalid input.
217+
current_errors.extend(filter(None, (
218+
self._get_group_signature_error(group, SUPPORTED_SPONGE)
219+
for group in groups[current_pos+1:]
205220
)))
206221

207-
return kerl_errors
222+
return current_errors
208223

209224
@staticmethod
210225
def _get_group_signature_error(group, sponge_type):
@@ -233,8 +248,8 @@ def _get_group_signature_error(group, sponge_type):
233248

234249
return (
235250
'Transaction {i} has invalid signature '
236-
'(using {fragments} fragments).'.format(
237-
fragments = len(group),
238-
i = group[0].current_index,
239-
)
251+
'(using {fragments} fragments).'.format(
252+
fragments = len(group),
253+
i = group[0].current_index,
254+
)
240255
)

0 commit comments

Comments
 (0)