Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
3rdIteration committed Mar 15, 2024
2 parents 6032656 + 94485c2 commit 74d0974
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ If you need help, [your best bet is to look at my BTCRecover playlist on YouTube
* Helium
* Litecoin
* Monacoin
* MultiversX
* Polkadot (sr25519, like those produced by polkadot.js)
* Ripple
* Secret Network
Expand Down
3 changes: 2 additions & 1 deletion btcrecover/btcrpass.py
Original file line number Diff line number Diff line change
Expand Up @@ -6240,7 +6240,7 @@ def parse_arguments(effective_argv, wallet = None, base_iterator = None,
if args.wallet_type == "cardano":
loaded_wallet = WalletCardano(args.addrs, args.addressdb, mnemonic,
args.language, args.bip32_path, args.performance)
elif args.wallet_type in ['avalanche', 'tron', 'solana', 'cosmos', 'tezos','stellar']:
elif args.wallet_type in ['avalanche', 'tron', 'solana', 'cosmos', 'tezos','stellar','multiversx']:
loaded_wallet = WalletPyCryptoHDWallet(args.mpk, args.addrs, args.addr_limit, args.addressdb, mnemonic,
args.language, args.bip32_path, args.wallet_type, args.performance)
elif args.wallet_type in ['polkadotsubstrate']:
Expand Down Expand Up @@ -6819,6 +6819,7 @@ def parse_mapfile(map_file, running_hash = None, feature_name = "map", same_perm
#
# Remove the trailing newline, then split the line exactly
# once on the specified delimiter (default: whitespace)
if args.delimiter: args.delimiter = args.delimiter.encode().decode('unicode_escape')
split_line = line.strip("\r\n").split(args.delimiter, 1)
if split_line in ([], [tstr('')]): continue # ignore empty lines
if len(split_line) == 1:
Expand Down
32 changes: 32 additions & 0 deletions btcrecover/btcrseed.py
Original file line number Diff line number Diff line change
Expand Up @@ -2536,6 +2536,38 @@ def _verify_seed(self, mnemonic, passphrase = None):

return False


############### MultiverseX ###############

@register_selectable_wallet_class('MultiversX BIP39/44')
class WalletMultiversX(WalletPyCryptoHDWallet):

def _verify_seed(self, mnemonic, passphrase = None):
if passphrase:
testSaltList = [passphrase]
else:
testSaltList = self._derivation_salts

for salt in testSaltList:

wallet = py_crypto_hd_wallet.HdWalletBipFactory(py_crypto_hd_wallet.HdWalletBip44Coins.ELROND)

wallet2 = wallet.CreateFromMnemonic("Elrond", mnemonic = " ".join(mnemonic), passphrase = salt.decode())

wallet2.Generate(addr_num=self._addrs_to_generate, addr_off=self._address_start_index, acc_idx=0,
change_idx=py_crypto_hd_wallet.HdWalletBipChanges.CHAIN_EXT)

test_addresses_dicts = wallet2.ToDict()['address']

test_addresses = test_addresses_dicts.values()

for test_address in test_addresses:
if test_address['address'] in self._known_hash160s:
return True

return False


# This uses the PyCryptoHDWallet implementation of Cardano Shelly, which is a bit more limited in terms of derivation path
# and wallet support, but is also several times faster. (ToDo: Implement speed improvement in to other implementation)
#
Expand Down
9 changes: 9 additions & 0 deletions btcrecover/test/test_passwords.py
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,15 @@ def test_address_ethereumvalidator(self):
address_limit=2
)

@skipUnless(can_load_PyCryptoHDWallet, "requires Py_Crypto_HD_Wallet module")
def test_address_PyCryptoHDWallet_multiversx(self):
self.WalletPyCryptoHDWallet_tester(
wallet_type="multiversx",
address_limit=1,
addresses= ["erd1t20rq7jqlspn5an5kw0vk75536x3m64ll0pcsx7g5v95daea6fhqqza54a"],
mnemonic= "ocean hidden kidney famous rich season gloom husband spring convince attitude boy"
)

@skipUnless(can_load_PyCryptoHDWallet, "requires Py_Crypto_HD_Wallet module")
def test_address_PyCryptoHDWallet_solana(self):
self.WalletPyCryptoHDWallet_tester(
Expand Down
5 changes: 5 additions & 0 deletions btcrecover/test/test_seeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,11 @@ def test_singlexpubaddress_mybitcoinwallet_single_bech32(self):
correct_mnemonic = "spatial stereo thrive reform shallow blouse minimum foster eagle game answer worth size stumble theme crater bounce stay extra duty man weather awesome search",
checksinglexpubaddress = True)

@skipUnless(can_load_PyCryptoHDWallet, "requires Py_Crypto_HD_Wallet module")
def test_WalletPyCryptoHDWallet_MultiverseX(self):
self.address_tester(btcrseed.WalletMultiversX, "erd16jn439kmwgqj9j0xjnwk2swg0p7j2jrnvpp4p7htc7wypnx27ttqe9l98m", 2,
"agree process hard hello artefact govern obtain wedding become robust fish bar alcohol about speak unveil mind bike shift latin pole base ugly artefact")

@skipUnless(can_load_PyCryptoHDWallet, "requires Py_Crypto_HD_Wallet module")
def test_WalletPyCryptoHDWallet_Tron(self):
self.address_tester(btcrseed.WalletTron, "TLDrhbxkBGa1doxtez2bEx4iQ3DmKg9UdM", 2,
Expand Down
6 changes: 6 additions & 0 deletions docs/Usage_Examples/basic_seed_recoveries.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,10 @@ python seedrecover.py --wallet-type stacks --addrs SP11KHP08F4KQ06MWESBY48VMXRBK
One missing word, address generation limit of 1. (So address needs to be in the first account)
```
python seedrecover.py --wallet-type tron --addrs TLxkYzNpMCEz5KThVuZzoyjde1UfsJKof6 --mnemonic "have hint welcome skate cinnamon rabbit cable payment gift uncover column duck scissors wedding decorate under marine hurry scrub rapid change roast print arch" --addr-limit 1
```

### Basic Elrond Recoveries
One missing word, address generation limit of 2. (So address needs to be in the first account)
```
python seedrecover.py --wallet-type elrond --addrs erd16jn439kmwgqj9j0xjnwk2swg0p7j2jrnvpp4p7htc7wypnx27ttqe9l98m --mnemonic "agree process hard hello artefact govern obtain wedding become robust fish bar alcohol about speak unveil mind bike shift latin pole base ugly artefact" --addr-limit 2
```
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ If you have found a bug, please open an issue on Github here: [https://github.co
* Helium
* Litecoin
* Monacoin
* MultiversX
* Polkadot (sr25519, like those produced by polkadot.js)
* Ripple
* Secret Network
Expand Down
121 changes: 121 additions & 0 deletions seedrecover_batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python3

# seedrecover.py -- Bitcoin mnemonic sentence recovery tool
# Copyright (C) 2014-2017 Christopher Gurnee
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version
# 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/

# If you find this program helpful, please consider a small
# donation to the developer at the following Bitcoin address:
#
# 3Au8ZodNHPei7MQiSVAWb7NB2yqsb48GW4
#
# Thank You!

# PYTHON_ARGCOMPLETE_OK - enables optional bash tab completion

import compatibility_check, copy

from btcrecover import btcrseed
import sys, multiprocessing

if __name__ == "__main__":
print()
print("Starting", btcrseed.full_version())

btcrseed.register_autodetecting_wallets()

batch_seed_file = open("batch_seeds.txt", "r")
batch_seed_list = batch_seed_file.readlines()
for mnemonic in batch_seed_list:
# Make a copy of the arguments
temp_argv = copy.deepcopy(sys.argv)

# Skip comments
if mnemonic[0] == '#' or len(mnemonic.strip()) == 0:
continue

# Split seeds from any comments
temp_argv.append("--mnemonic")
temp_argv.append(mnemonic.split("#")[0].strip())

print("Running Seed:", mnemonic.split("#")[0].strip())

try:
mnemonic_sentence, path_coin = btcrseed.main(temp_argv[1:])
except:
print("Generated Exception...")
continue

if mnemonic_sentence:
if not btcrseed.tk_root: # if the GUI is not being used
print()
print(
"If this tool helped you to recover funds, please consider donating 1% of what you recovered, in your crypto of choice to:")
print("BTC: 37N7B7sdHahCXTcMJgEnHz7YmiR4bEqCrS ")
print("BCH: qpvjee5vwwsv78xc28kwgd3m9mnn5adargxd94kmrt ")
print("LTC: M966MQte7agAzdCZe5ssHo7g9VriwXgyqM ")
print("ETH: 0x72343f2806428dbbc2C11a83A1844912184b4243 ")

# Selective Donation Addressess depending on path being recovered... (To avoid spamming the dialogue with shitcoins...)
# TODO: Implement this better with a dictionary mapping in seperate PY file with BTCRecover specific donation addys... (Seperate from YY Channel)
if path_coin == 28:
print("VTC: vtc1qxauv20r2ux2vttrjmm9eylshl508q04uju936n ")

if path_coin == 22:
print("MONA: mona1q504vpcuyrrgr87l4cjnal74a4qazes2g9qy8mv ")

if path_coin == 5:
print("DASH: Xx2umk6tx25uCWp6XeaD5f7CyARkbemsZG ")

if path_coin == 121:
print("ZEN: znUihTHfwm5UJS1ywo911mdNEzd9WY9vBP7 ")

if path_coin == 3:
print("DOGE: DMQ6uuLAtNoe5y6DCpxk2Hy83nYSPDwb5T ")

print()
print("Find me on Reddit @ https://www.reddit.com/user/Crypto-Guide")
print()
print(
"You may also consider donating to Gurnec, who created and maintained this tool until late 2017 @ 3Au8ZodNHPei7MQiSVAWb7NB2yqsb48GW4")
print()
print("Seed found:", mnemonic_sentence) # never dies from printing Unicode

# print this if there's any chance of Unicode-related display issues
if any(ord(c) > 126 for c in mnemonic_sentence):
print("HTML Encoded Seed:", mnemonic_sentence.encode("ascii", "xmlcharrefreplace").decode())

if btcrseed.tk_root: # if the GUI is being used
btcrseed.show_mnemonic_gui(mnemonic_sentence, path_coin)

retval = 0
break

elif mnemonic_sentence is None:
retval = 1 # An error occurred or Ctrl-C was pressed inside btcrseed.main()

else:
retval = 0 # "Seed not found" has already been printed to the console in btcrseed.main()

# Wait for any remaining child processes to exit cleanly (to avoid error messages from gc)
for process in multiprocessing.active_children():
process.join(1.0)

# Wait for any remaining child processes to exit cleanly (to avoid error messages from gc)
for process in multiprocessing.active_children():
process.join(1.0)

batch_seed_file.close()
sys.exit(retval)

0 comments on commit 74d0974

Please sign in to comment.