Skip to content

Commit da709e7

Browse files
onvej-slpjkundert
authored andcommitted
Support slip39 extendable backups
1 parent b4fb8ef commit da709e7

File tree

3 files changed

+231
-11
lines changed

3 files changed

+231
-11
lines changed

slip39/api.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ def create(
983983
iteration_exponent: int = 1,
984984
cryptopaths: Optional[Sequence[Union[str,Tuple[str,str],Tuple[str,str,str]]]] = None, # default: ETH, BTC at default path, format
985985
strength: Optional[int] = None, # Default: 128
986+
extendable: bool = True,
986987
) -> Tuple[str,int,Dict[str,Tuple[int,List[str]]], Sequence[Sequence[Account]], bool]:
987988
"""Creates a SLIP-39 encoding for supplied master_secret Entropy, and 1 or more Cryptocurrency
988989
accounts. Returns the Details, in a form directly compatible with the layout.produce_pdf API.
@@ -1084,7 +1085,8 @@ def create(
10841085
groups = g_dims,
10851086
master_secret = master_secret,
10861087
passphrase = passphrase,
1087-
iteration_exponent= iteration_exponent
1088+
iteration_exponent= iteration_exponent,
1089+
extendable = extendable
10881090
)
10891091

10901092
groups = {
@@ -1112,6 +1114,7 @@ def mnemonics(
11121114
passphrase: Optional[Union[bytes,str]] = None,
11131115
iteration_exponent: int = 1,
11141116
strength: int = BITS_DEFAULT,
1117+
extendable: bool = True,
11151118
) -> List[List[str]]:
11161119
"""Generate SLIP39 mnemonics for the supplied group_threshold of the given groups. Will generate a
11171120
random master_secret, if necessary.
@@ -1143,6 +1146,7 @@ def mnemonics(
11431146
passphrase = passphrase or b"", # python-shamir-mnemonic requires bytes
11441147
extendable = False,
11451148
iteration_exponent = iteration_exponent,
1149+
extendable = extendable,
11461150
)
11471151

11481152

slip39/api_test.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,30 @@ def test_account_format():
229229
assert acct.address == 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu'
230230

231231

232+
def test_slip39_non_extendable_compatibility():
233+
"""Test that SLIP-39 non-extendable backup of a wallet generated by Trezor can be recevered"""
234+
# The 4th vector from https://github.com/trezor/python-shamir-mnemonic/blob/master/vectors.json
235+
mnemonics = [
236+
"shadow pistol academic always adequate wildlife fancy gross oasis cylinder mustang wrist rescue view short owner flip making coding armed",
237+
"shadow pistol academic acid actress prayer class unknown daughter sweater depict flip twice unkind craft early superior advocate guest smoking"
238+
]
239+
account = Account( crypto="Bitcoin", format="legacy" )
240+
account.from_mnemonic( "\n".join(mnemonics), passphrase = 'TREZOR', path="m/" )
241+
assert account.xprvkey == "xprv9s21ZrQH143K2nNuAbfWPHBtfiSCS14XQgb3otW4pX655q58EEZeC8zmjEUwucBu9dPnxdpbZLCn57yx45RBkwJHnwHFjZK4XPJ8SyeYjYg"
242+
243+
244+
def test_slip39_extendable_trezor_compatibility():
245+
"""Test that SLIP-39 extendable backup of a wallet generated by Trezor can be recevered"""
246+
# The 43th vector from https://github.com/trezor/python-shamir-mnemonic/blob/master/vectors.json
247+
mnemonics = [
248+
"enemy favorite academic acid cowboy phrase havoc level response walnut budget painting inside trash adjust froth kitchen learn tidy punish",
249+
"enemy favorite academic always academic sniff script carpet romp kind promise scatter center unfair training emphasis evening belong fake enforce"
250+
]
251+
account = Account( crypto="Bitcoin", format="legacy" )
252+
account.from_mnemonic( "\n".join(mnemonics), passphrase = 'TREZOR', path="m/" )
253+
assert account.xprvkey == "xprv9s21ZrQH143K4FS1qQdXYAFVAHiSAnjj21YAKGh2CqUPJ2yQhMmYGT4e5a2tyGLiVsRgTEvajXkxhg92zJ8zmWZas9LguQWz7WZShfJg6RS"
254+
255+
232256
def test_account_from_mnemonic():
233257
"""Test all the ways the entropy 0xffff...ffff can be encoded and HD Wallets derived."""
234258
# Raw 0xffff...ffff entropy as Seed. Not BIP-39 decoded (hashed) via mnemonic to produce Seed.
@@ -397,11 +421,11 @@ def test_create():
397421

398422
assert details_xmas.groups == {
399423
"fren": ( 3, [
400-
"academic acid academic acne academic academic academic academic academic academic academic academic academic academic academic academic academic carpet making building",
401-
"academic acid academic agree depart dance galaxy acrobat mayor disaster quick justice ordinary agency plunge should pupal emphasis security obtain",
402-
"academic acid academic amazing crush royal faint spit briefing craft floral negative work depend prune adapt merit romp home elevator",
403-
"academic acid academic arcade cargo unfold aunt spider muscle bedroom triumph theory gather dilemma building similar chemical object cinema salon",
404-
"academic acid academic axle crush swing purple violence teacher curly total equation clock mailman display husband tendency smug laundry disaster"
424+
"academic agency academic acne academic academic academic academic academic academic academic academic academic academic academic academic academic arena diet involve",
425+
"academic agency academic agree closet maximum rumor beyond organize taught game helpful fishing brother bumpy nervous presence document buyer reject",
426+
"academic agency academic amazing arena meaning advocate hearing hunting pecan lilac device oasis teacher traffic retailer criminal scene flip true",
427+
"academic agency academic arcade cover acne safari item vanish else superior focus skin webcam venture clay loan various impact client",
428+
"academic agency academic axle carpet blimp stilt intend august racism webcam replace gather rich sweater mandate maximum rumor drink scene"
405429
] ),
406430
}
407431

0 commit comments

Comments
 (0)