@@ -321,6 +321,31 @@ class Codex32String:
321321
322322 def __init__ (self , s = "" ):
323323 self .s = s
324+ self .hrp , data = bech32_decode (self .s )
325+ _ , s = self .s .rsplit ("1" , 1 )
326+ if len (s ) < 94 and len (s ) > 44 :
327+ checksum_len = 13
328+ elif len (s ) >= 96 and len (s ) < 125 :
329+ checksum_len = 15
330+ else :
331+ raise InvalidLength (f"{ len (s )} must be 45-93 or 96 to 124" )
332+ threshold_char = s [0 ]
333+ if threshold_char .isdigit () and threshold_char != "1" :
334+ k = int (threshold_char )
335+ else :
336+ raise InvalidThreshold (threshold_char )
337+ self .k = k
338+ self .ident = s [1 :5 ]
339+ self .share_index = s [5 ]
340+ self .payload = s [6 : len (s ) - checksum_len ]
341+ self .checksum = s [- checksum_len :]
342+ if self .k == 0 and self .share_index .lower () != "s" :
343+ raise InvalidShareIndex (self .share_index + "must be 's' when k=0" )
344+ if not ms32_verify_checksum (data ):
345+ raise InvalidChecksum (f"string={ s } " )
346+ incomplete_group = (len (self .payload ) * 5 ) % 8
347+ if incomplete_group > 4 :
348+ raise IncompleteGroup (str (incomplete_group ))
324349
325350 def __str__ (self ):
326351 return self .s
@@ -333,79 +358,44 @@ def __eq__(self, other):
333358 def __hash__ (self ):
334359 return hash (self .s )
335360
336- def sanity_check (self ):
337- """Perform sanity check on the codex32 string."""
338- parts = self .parts
339- incomplete_group = (len (parts .payload ) * 5 ) % 8
340- if incomplete_group > 4 :
341- raise IncompleteGroup (str (incomplete_group ))
361+ @property
362+ def data (self ):
363+ """Return the payload data bytes."""
364+ return bytes (convertbits (bech32_to_u5 (self .payload ), 5 , 8 , False ))
342365
343366 @classmethod
344367 def from_unchecksummed_string (cls , s , hrp = "ms" ):
345368 """Create Codex32String from unchecksummed string."""
346- hrp , data = bech32_decode (s , hrp = hrp )
369+ _ , data = bech32_decode (s , hrp = hrp )
347370 ret = cls (bech32_encode (data + ms32_create_checksum (data ), hrp ))
348- ret .sanity_check ()
349371 return ret
350372
351373 @classmethod
352374 def from_string (cls , s , hrp = "ms" ):
353375 """Create Codex32String from a codex32 string."""
354- _ , data = bech32_decode (s , hrp = hrp )
355- if not ms32_verify_checksum (data ):
356- raise InvalidChecksum (f"string={ s } " )
357376 ret = cls (s )
358- ret .sanity_check ()
359- return ret
360-
361- @property
362- def parts (self ):
363- """Get parts of the codex32 string."""
364- hrp , s = self .s .rsplit ("1" , 1 ) if "1" in self .s else ("" , self .s )
365- if len (s ) < 94 and len (s ) > 44 :
366- checksum_len = 13
367- elif len (s ) >= 96 and len (s ) < 125 :
368- checksum_len = 15
369- else :
370- raise InvalidLength (f"{ len (s )} must be 45-93 or 96 to 124" )
371- threshold_char = s [0 ]
372- if threshold_char .isdigit () and threshold_char != "1" :
373- k = int (threshold_char )
374- else :
375- raise InvalidThreshold (threshold_char )
376- ret = Parts (
377- hrp = hrp ,
378- k = k ,
379- ident = s [1 :5 ],
380- share_index = s [5 ],
381- payload = s [6 : len (s ) - checksum_len ],
382- checksum = s [- checksum_len :],
383- )
384- if ret .k == 0 and ret .share_index .lower () != "s" :
385- raise InvalidShareIndex (ret .share_index + "must be 's' when k=0" )
386377 return ret
387378
388379 @classmethod
389- def interpolate_at (cls , shares , target ):
380+ def interpolate_at (cls , shares , target = "s" ):
390381 """Interpolate to a specific target share index."""
391382 indices = []
392383 ms32_shares = []
393- s0_parts = shares [0 ]. parts
384+ s0_parts = shares [0 ]
394385 if s0_parts .k > len (shares ):
395386 raise ThresholdNotPassed (f"threshold={ s0_parts .k } , n_shares={ len (shares )} " )
396387 for share in shares :
397- parts = share .parts
398388 if len (shares [0 ].s ) != len (share .s ):
399389 raise MismatchedLength (f"{ len (shares [0 ].s )} , { len (share .s )} " )
400- if s0_parts .hrp != parts .hrp :
401- raise MismatchedHrp (f"{ s0_parts .hrp } , { parts .hrp } " )
402- if s0_parts .k != parts .k :
403- raise MismatchedThreshold (f"{ s0_parts .k } , { parts .k } " )
404- if s0_parts .ident != parts .ident :
405- raise MismatchedId (f"{ s0_parts .ident } , { parts .ident } " )
406- if parts .share_index in indices :
407- raise RepeatedIndex (parts .share_index )
408- indices .append (parts .share_index )
390+ if s0_parts .hrp != share .hrp :
391+ raise MismatchedHrp (f"{ s0_parts .hrp } , { share .hrp } " )
392+ if s0_parts .k != share .k :
393+ raise MismatchedThreshold (f"{ s0_parts .k } , { share .k } " )
394+ if s0_parts .ident != share .ident :
395+ raise MismatchedId (f"{ s0_parts .ident } , { share .ident } " )
396+ if share .share_index in indices :
397+ raise RepeatedIndex (share .share_index )
398+ indices .append (share .share_index )
409399 ms32_shares .append (bech32_decode (share .s )[1 ])
410400 for i , share in enumerate (shares ):
411401 if indices [i ] == target :
@@ -432,45 +422,3 @@ def from_seed(cls, data, ident="", hrp="ms", k=0, share_idx="s", pad_val=None):
432422 combined = header + payload
433423 ret = bech32_encode (combined + ms32_create_checksum (combined ), hrp )
434424 return cls (ret )
435-
436-
437- class Parts :
438- """Class representing parts of a Codex32 string."""
439-
440- # pylint: disable=too-many-arguments,too-many-positional-arguments
441- def __init__ (self , hrp , k , ident , share_index , payload , checksum ):
442- self .hrp = hrp
443- self .k = k
444- self .ident = ident
445- self .share_index = share_index
446- self .payload = payload
447- self .checksum = checksum
448-
449- @property
450- def data (self ):
451- """Get data from payload."""
452- return bytes (convertbits (bech32_to_u5 (self .payload ), 5 , 8 , False ))
453-
454- def __eq__ (self , other ):
455- if not isinstance (other , Parts ):
456- return False
457- return (
458- self .hrp == other .hrp
459- and self .k == other .k
460- and self .ident == other .ident
461- and self .share_index == other .share_index
462- and self .payload == other .payload
463- and self .checksum == other .checksum
464- )
465-
466- def __hash__ (self ):
467- return hash (
468- (
469- self .hrp ,
470- self .k ,
471- self .ident ,
472- self .share_index ,
473- self .payload ,
474- self .checksum ,
475- )
476- )
0 commit comments