Skip to content

Commit

Permalink
design and code updates
Browse files Browse the repository at this point in the history
  • Loading branch information
SaniExp committed Sep 30, 2023
1 parent c6642b3 commit d03e133
Show file tree
Hide file tree
Showing 7 changed files with 454 additions and 232 deletions.
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ Table Of Contents

# Roll2Mnemonic

This multifaceted tool empowers you to effortlessly create secure mnemonic seed phrases using either manual dice rolls or coin tosses. It then goes a step further by generating corresponding private keys and public addresses for all available Bitcoin script types. Whether you prefer manual or automated methods, this tool has you covered.
This multifaceted tool empowers you to effortlessly create secure mnemonic seed phrases using either manual dice rolls, coin tosses or seed phrases. It then goes a step further by generating corresponding private keys and public addresses for all available Bitcoin script types. Whether you prefer manual or automated methods, this tool has you covered.

## Features

- **Dice Roll:**
1. Manual Dice Roll: You have the option to roll physical dice or coin toss and input the data into the program as binary (1 or 0) or numbers (1 to 6). This method ensures true randomness in generating your mnemonic seed phrase.
2. Automated Dice Roll: If you prefer a quicker approach, the program can generate random dice rolls for you. The automated dice roll function guarantees the randomness required for secure seed phrase generation.
- **Mnemonic Seed Generation:** Once the dice roll data is collected, the program seamlessly proceeds to generate a valid checksum then generates a BIP39 mnemonic seed phrase. This seed phrase is the foundation for generating Bitcoin private keys and public addresses.
- **Mnemonic Code Converter:** The mnemonic seed phrase is then passed through to the Mnemonic Code Converter within the same program. This converter is capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR).
- **Dice Roll To Mnemonic:**
1. Physical Dice or Coin Toss: You have the flexibility to roll physical dice or conduct a coin toss and input the resulting data as either binary (1 or 0) or numbers (1 to 6). This method ensures absolute randomness for generating your mnemonic seed phrase.
2. Dice Roll From Entropy: For a quicker approach, the program can generate random dice rolls for you. The automated dice roll function guarantees the essential randomness needed for a secure seed phrase.
3. Mnemonic Seed Generation: After collecting the dice roll data, the program seamlessly proceeds to generate a valid checksum and creates a BIP39 mnemonic seed phrase. This seed phrase forms the cornerstone for generating Bitcoin private keys and public addresses.
4. Mnemonic Code Converter: The generated mnemonic seed phrase is then processed through the Mnemonic Code Converter, capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR).
- **Seed To Mnemonic:**
1. Generate Hex Seed From Entropy: The program can generate a Hex seed from entropy. The automated function guarantees the essential randomness required for secure seed generation.
2. Mnemonic Seed Generation: After collecting the Hex seed, the program seamlessly proceeds to generate a valid checksum and creates a BIP39 mnemonic seed phrase.
3. Own Mnemonic Seed Phrase: You have the option to enter your own mnemonic seed phrase into the program.
4. Mnemonic Code Converter: The generated mnemonic seed phrase is then processed through the Mnemonic Code Converter, capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR).
- **QR Code Generator:** A built in QR code generator from text.


Expand Down Expand Up @@ -82,7 +87,7 @@ https://www.python.org/downloads/
https://pip.pypa.io/en/stable/installation/
```

3. Clone or download the repository and extract it.
3. Clone or download the repository (Make sure you have the latest release), and extract it.

4. Cloning dependencies, same method for all operating systems:

Expand Down Expand Up @@ -139,7 +144,7 @@ Now your offline device should have all the required dependencies to run offline
## Demo Video
[![Video](http://img.youtube.com/vi/TV6SB6fHE-s/0.jpg)](http://www.youtube.com/watch?v=TV6SB6fHE-s)
[![Video](http://img.youtube.com/vi/zpM8gb1_vQQ/0.jpg)](https://www.youtube.com/watch?v=zpM8gb1_vQQ)
## Support and Feedback
Expand Down
32 changes: 29 additions & 3 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from mnemonic import Mnemonic
import platform
import subprocess
import keyboard
import os
import locale
import datetime
from mnemonic import Mnemonic
from bip32utils import BIP32Key
import hashlib
import binascii
Expand All @@ -15,13 +16,17 @@
from bitcoinaddress.key.key import Key
from bitcoinaddress.address import Address
from bitcoinutils.setup import setup
from bitcoinutils.keys import P2pkhAddress, PrivateKey
from bitcoinutils.keys import P2pkhAddress, PrivateKey, PublicKey
from art import *
import tkinter as tk
from tkinter import ttk
import qrcode
from PIL import Image, ImageTk



# Set the locale to your preferred formatting (e.g., en_US.UTF-8)
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

# Functions to print text in color
def print_red(*args):
text = ' '.join(map(str, args))
Expand Down Expand Up @@ -65,6 +70,27 @@ def print_centered_art_text(text, convert, fonttype):
# Print centered text
tprint(centered_text, font=fonttype)

def maximize_window():
system = platform.system()

if system == 'Windows':
# Windows: Send Win + Up Arrow
keyboard.press_and_release('win+up')
elif system == 'Darwin':
# macOS: Send Ctrl + Command + F
keyboard.press_and_release('ctrl+cmd+f')
elif system == 'Linux':
try:
# Linux: Send Alt + F10 (using wmctrl if available)
subprocess.check_output(['wmctrl', '--version'])
subprocess.run(['wmctrl', '-r', ':ACTIVE:', '-b', 'add,maximized_vert,maximized_horz'])
except subprocess.CalledProcessError:
# If wmctrl is not available, send Alt + F10 using keyboard
keyboard.press_and_release('alt+f10')
else:
print(f"Unsupported operating system: {system}")


# Function to check if a seed phrase is valid
def is_valid_seed(seed_phrase):
try:
Expand Down
18 changes: 12 additions & 6 deletions diceroll.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ def word_to_binary(word, word_list):
binary_representation = bin(index)[2:].zfill(11)
return binary_representation

import random

def roll_dice(n):
return [int(random.randint(1, 6) % 2 == 0) for _ in range(n)] # odd numbers are 0, even numbers are 1
# return [int(random.randint(1, 6) > 3) for _ in range(n)] # You can enable this code to convert from (1, 2 or 3) to 0 and (4, 5 or 6) to 1

auto_dice_list = []
for i in range(10000):
auto_dice = [int(random.randint(1, 1000)) for _ in range(n)]
auto_dice_list.append(auto_dice)
auto_dice = random.choice(auto_dice_list)
auto_dice_binary = [1 if num % 2 == 0 else 0 for num in auto_dice] # odd numbers are converted 0, even numbers are converted 1
return auto_dice_binary

def roll_dice_auto(num_words):
while True:
mnemo = Mnemonic("english")
Expand Down Expand Up @@ -104,7 +111,8 @@ def roll_dice_auto(num_words):
print()
print_red(f" You've chosen to generate a {num_words}-word mnemonic seed phrase."
f"\n This requires rolling {mnemonic_bits} bits randomly and calculating {bit_checksum} bits for a valid checksum, totaling {total_bits} bits."
f"\n The dice will be rolled {mnemonic_bits} times.")
f"\n For each bit in the {mnemonic_bits} bits, a 1,000-sided dice will be roll 10,000 times and the results will be stored in a list."
f"\n Subsequently, a random number will be selected from the list and transformed into 0 if it's odd or 1 if it's even.")
print()
# Print the appended messages if the seed is valid
for msg in print_list_blue[:-3]:
Expand All @@ -115,8 +123,6 @@ def roll_dice_auto(num_words):
for msg in print_list_blue[-3:]:
print_blue(msg)
return mnemonic



def roll_dice_manual_binary(num_words):
mnemo = Mnemonic("english")
Expand Down
106 changes: 49 additions & 57 deletions mccmainnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,30 +109,40 @@ def generate_mainnet_addresses(seed_phrase, num_child_keys, passphrase):
TaprootWIFR = address_key_taprootR.WalletImportFormat()
TaprootWIFC = address_key_taprootC.WalletImportFormat()

# Pubic addresses
# Public Keys
setup("mainnet")
LegacyR = PrivateKey(LegacyWIFR).get_public_key().get_address().to_string()
LegacyC = PrivateKey(LegacyWIFC).get_public_key().get_address().to_string()
NestedR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey())
NestedC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey())
NativeR = PrivateKey(NativeWIFR).get_public_key().get_segwit_address().to_string()
NativeC = PrivateKey(NativeWIFC).get_public_key().get_segwit_address().to_string()
TaprootR = PrivateKey(TaprootWIFR).get_public_key().get_taproot_address().to_string()
TaprootC = PrivateKey(TaprootWIFC).get_public_key().get_taproot_address().to_string()
LegacyPKR = PrivateKey(LegacyWIFR).get_public_key().to_hex(compressed=True)
LegacyPKC = PrivateKey(LegacyWIFC).get_public_key().to_hex(compressed=True)
NestedPKR = binascii.hexlify(address_key_nestedR.PublicKey()).decode('utf-8')
NestedPKC = binascii.hexlify(address_key_nestedC.PublicKey()).decode('utf-8')
NativePKR = PrivateKey(NativeWIFR).get_public_key().to_hex(compressed=True)
NativePKC = PrivateKey(NativeWIFC).get_public_key().to_hex(compressed=True)
TaprootPKR = PrivateKey(TaprootWIFR).get_public_key().to_hex(compressed=True)
TaprootPKC = PrivateKey(TaprootWIFC).get_public_key().to_hex(compressed=True)

# Pubic addresses
LegacyAddR = PublicKey(LegacyPKR).get_address().to_string()
LegacyAddC = PublicKey(LegacyPKC).get_address().to_string()
NestedAddR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey())
NestedAddC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey())
NativeAddR = PublicKey(NativePKR).get_segwit_address().to_string()
NativeAddC = PublicKey(NativePKC).get_segwit_address().to_string()
TaprootAddR = PublicKey(TaprootPKR).get_taproot_address().to_string()
TaprootAddC = PublicKey(TaprootPKC).get_taproot_address().to_string()

# Append keys, addresses & WIFs to addresses lists
addresses["Legacy (P2PKH)R"].append((xprv_root_key, legacy_acc_ext_xpub_key, "", "44", LegacyR, LegacyWIFR))
addresses["Legacy (P2PKH)C"].append(("44", LegacyC, LegacyWIFC))
addresses["Nested SegWit (P2SH-P2WPKH)R"].append((yprv_root_key, nested_acc_ext_xpub_key, nested_acc_ext_ypub_key, "49", NestedR, NestedWIFR))
addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedC, NestedWIFC))
addresses["Native SegWit (P2WPKH)R"].append((zprv_root_key, native_acc_ext_xpub_key, native_acc_ext_zpub_key, "84", NativeR, NativeWIFR))
addresses["Native SegWit (P2WPKH)C"].append(("84", NativeC, NativeWIFC))
addresses["Taproot (P2TR)R"].append((xprv_root_key, taproot_acc_ext_xpub_key, "", "86", TaprootR, TaprootWIFR))
addresses["Taproot (P2TR)C"].append(("86", TaprootC, TaprootWIFC))
addresses["Legacy (P2PKH)R"].append((xprv_root_key, legacy_acc_ext_xpub_key, "", "44", LegacyAddR, LegacyPKR, LegacyWIFR))
addresses["Legacy (P2PKH)C"].append(("44", LegacyAddC, LegacyPKC, LegacyWIFC))
addresses["Nested SegWit (P2SH-P2WPKH)R"].append((yprv_root_key, nested_acc_ext_xpub_key, nested_acc_ext_ypub_key, "49", NestedAddR, NestedPKR, NestedWIFR))
addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedAddC, NestedPKC, NestedWIFC))
addresses["Native SegWit (P2WPKH)R"].append((zprv_root_key, native_acc_ext_xpub_key, native_acc_ext_zpub_key, "84", NativeAddR, NativePKR, NativeWIFR))
addresses["Native SegWit (P2WPKH)C"].append(("84", NativeAddC, NativePKC, NativeWIFC))
addresses["Taproot (P2TR)R"].append((xprv_root_key, taproot_acc_ext_xpub_key, "", "86", TaprootAddR, TaprootPKR, TaprootWIFR))
addresses["Taproot (P2TR)C"].append(("86", TaprootAddC, TaprootPKC, TaprootWIFC))

return addresses, bip39_root_key

def print_address_details(script_type, addresses):
def print_address_details(script_type, addresses, is_full):
print()
print()

Expand All @@ -151,75 +161,57 @@ def print_address_details(script_type, addresses):
print_green(f" Acc. Ext. Pub. Key: {extpubkey2}")

format_info = {
"Legacy (P2PKH)": (38, 111),
"Nested SegWit (P2SH-P2WPKH)": (38, 111),
"Native SegWit (P2WPKH)": (46, 119),
"Taproot (P2TR)": (66, 139)
"Legacy (P2PKH)": (37, 111) if not is_full else (38, 182),
"Nested SegWit (P2SH-P2WPKH)": (37, 111) if not is_full else (38, 182),
"Native SegWit (P2WPKH)": (45, 119) if not is_full else (46, 190),
"Taproot (P2TR)": (65, 139) if not is_full else (66, 210)
}

if script_type in format_info:
address_width, line_width = format_info[script_type]
address_width, line_width = format_info[script_type]
header_template = f" Derivation Path".ljust(28)
address_template = "Bitcoin Address".ljust(address_width)
wif_template = "Private Key / WIF (Wallet Import Format)"
pk_template = "Public Key".ljust(70) if is_full else ""

print_purple(" Receive Addresses:")
print_cyan(f"{header_template} {address_template} {wif_template}")
print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}")
print_cyan(f" " + "-" * line_width)

for index, (rootkey, extpubkey1, extpubkey2, BIP, address, wif) in enumerate(addresses[f'{script_type}R']):
for index, (rootkey, extpubkey1, extpubkey2, BIP, address, PK, wif) in enumerate(addresses[f'{script_type}R']):
path = f" m/{BIP}'/0'/0'/0/{index}".ljust(20)
address = address.ljust(address_width)
print(f" {path} {address} {wif}")
pk = PK.ljust(70) if is_full else ""
print(f" {path} {address} {pk} {wif}")

print()
print_purple(" Change Addresses:")
print_cyan(f"{header_template} {address_template} {wif_template}")
print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}")
print_cyan(f" " + "-" * line_width)

for index, (BIP, address, wif) in enumerate(addresses[f'{script_type}C']):
for index, (BIP, address, PK, wif) in enumerate(addresses[f'{script_type}C']):
path = f" m/{BIP}'/0'/0'/1/{index}".ljust(20)
address = address.ljust(address_width)
print(f" {path} {address} {wif}")
pk = PK.ljust(70) if is_full else ""
print(f" {path} {address} {pk} {wif}")

# Function to generate wallets
def generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase):
def generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase, list_type):
if is_valid_seed(seed_phrase): #Recheck if the mnemonic seed phrase is valid
seed = Mnemonic("english").to_seed(seed_phrase, passphrase=passphrase)
hex_seed = binascii.hexlify(seed).decode('utf-8')

# Format Information box
creator_info = f"Created By : Sani Fahs"
twitter_info = f"Twitter : @SaniExp"
github_info = f"GitHub : https://github.com/FahsSani"
lightning_info = f"Lightning Donations : sani@walletofsatoshi.com"
max_info_length = max(len(creator_info), len(twitter_info), len(github_info), len(lightning_info))
box_width = max_info_length + 4 # Adjust the box width based on the max info length
info_box = " " + "+" + "-" * (box_width - 2) + "+"
info_box += f"\n | {creator_info.ljust(max_info_length)} |"
info_box += f"\n | {twitter_info.ljust(max_info_length)} |"
info_box += f"\n | {github_info.ljust(max_info_length)} |"
info_box += f"\n | {lightning_info.ljust(max_info_length)} |"
info_box += "\n +" + "-" * (box_width - 2) + "+"

addresses, bip39_root_key = generate_mainnet_addresses(seed_phrase, num_child_keys, passphrase=passphrase)

# Clear terminal
clear_terminal()

# Print title
text3 = "* ROLL TO MNEMONIC *"
print_centered_art_text(text3, 5, "Standard")

# Print data
print_bright_orange(info_box)
print()
print_red(" Mnemonic Seed Phrase:", seed_phrase)
print_red(" Passphrase :", passphrase)
print_red(f"\n Mnemonic Seed Phrase: {seed_phrase}")
print_red(f" Passphrase : {passphrase}")
print_red(" BIP39 Seed Hex :", hex_seed)

for script_type in ["Legacy (P2PKH)", "Nested SegWit (P2SH-P2WPKH)", "Native SegWit (P2WPKH)", "Taproot (P2TR)"]:
print_address_details(script_type, addresses)
if list_type == "AddMain":
print_address_details(script_type, addresses, is_full=False)
else:
print_address_details(script_type, addresses, is_full=True)

print()
print_red(" To verify the mnemonic seed phrase, keys and addresses, visit: https://iancoleman.io/bip39/")
Expand Down
Loading

0 comments on commit d03e133

Please sign in to comment.