Skip to content

Instantly share code, notes, and snippets.

@ChypherC0d3
Created August 30, 2024 10:51
Show Gist options
  • Save ChypherC0d3/d8e2817a97fe10a1c4e1b15d27e2333a to your computer and use it in GitHub Desktop.
Save ChypherC0d3/d8e2817a97fe10a1c4e1b15d27e2333a to your computer and use it in GitHub Desktop.
Random_Derivation_ETH_Wallets.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"authorship_tag": "ABX9TyOLhhYy2cmMonToKhEwfV9v",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/CY0xZ/d8e2817a97fe10a1c4e1b15d27e2333a/random_derivation_eth_wallets.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "kXRHaexcJj5D",
"outputId": "e8cae678-fd85-4e9f-b08d-00a6fb1c1228"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Collecting mnemonic\n",
" Downloading mnemonic-0.21-py3-none-any.whl.metadata (3.4 kB)\n",
"Collecting bip44\n",
" Downloading bip44-0.1.4-py3-none-any.whl.metadata (2.5 kB)\n",
"Collecting bip32<4.0,>=3.1 (from bip44)\n",
" Downloading bip32-3.4-py3-none-any.whl.metadata (4.6 kB)\n",
"Collecting mnemonic\n",
" Downloading mnemonic-0.20-py3-none-any.whl.metadata (2.9 kB)\n",
"Collecting pycryptodome<4.0.0,>=3.16.0 (from bip44)\n",
" Downloading pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.4 kB)\n",
"Collecting base58~=2.0 (from bip32<4.0,>=3.1->bip44)\n",
" Downloading base58-2.1.1-py3-none-any.whl.metadata (3.1 kB)\n",
"Collecting coincurve<19,>=15.0 (from bip32<4.0,>=3.1->bip44)\n",
" Downloading coincurve-18.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.8 kB)\n",
"Requirement already satisfied: asn1crypto in /usr/local/lib/python3.10/dist-packages (from coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (1.5.1)\n",
"Requirement already satisfied: cffi>=1.3.0 in /usr/local/lib/python3.10/dist-packages (from coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (1.17.0)\n",
"Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.3.0->coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (2.22)\n",
"Downloading bip44-0.1.4-py3-none-any.whl (5.1 kB)\n",
"Downloading mnemonic-0.20-py3-none-any.whl (62 kB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.0/62.0 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hDownloading bip32-3.4-py3-none-any.whl (10 kB)\n",
"Downloading pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.1 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.1/2.1 MB\u001b[0m \u001b[31m20.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hDownloading base58-2.1.1-py3-none-any.whl (5.6 kB)\n",
"Downloading coincurve-18.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m21.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hInstalling collected packages: pycryptodome, mnemonic, base58, coincurve, bip32, bip44\n",
"Successfully installed base58-2.1.1 bip32-3.4 bip44-0.1.4 coincurve-18.0.0 mnemonic-0.20 pycryptodome-3.20.0\n"
]
}
],
"source": [
"pip install mnemonic bip44 web3 eth-utils pandas openpyxl"
]
},
{
"cell_type": "code",
"source": [
"######################################################################################################\n",
"######################################################################################################\n",
"############### How random is the random generation of wallets? ##########################\n",
"######################################################################################################\n",
"######################################################################################################"
],
"metadata": {
"id": "_nz7oKIH6RTq"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from mnemonic import Mnemonic\n",
"from bip44 import Wallet\n",
"from eth_utils import to_checksum_address, keccak\n",
"\n",
"# Function to convert public key to Ethereum address\n",
"def public_key_to_eth_address(public_key):\n",
" # Ethereum address is the last 20 bytes of the keccak-256 hash of the public key\n",
" return to_checksum_address(keccak(public_key[1:])[-20:])\n",
"\n",
"# Define the mnemonics provided earlier\n",
"mnemonics = [\n",
" \"border summer salt divorce muscle palm ahead predict mimic enroll west secret\",\n",
" \"trouble enforce giant bright trend climb gather mean jungle account window offer\",\n",
" \"eagle waste honey local raise mystery rent guard swing clever addict walnut\",\n",
" \"cement spawn uphold village thunder envelope cry scatter inquiry voyage recipe manual\",\n",
" \"garage rapid carbon broken merge blue sword include execute dove equip trigger\",\n",
" \"basic comic puppy aware sound private market elbow galaxy mean dragon floor\",\n",
" \"lab bullet lonely lunch achieve hobby genre shrimp title tiger release faculty\",\n",
" \"view piano duty goddess owner decline bless cargo output medal torch grid\",\n",
" \"clip shift rigid useful hub spatial badge solid guilt modify craft edit\",\n",
" \"wreck empty coconut hidden silent alter refuse lottery fatal mystery brave treat\"\n",
"]\n",
"\n",
"# Function to derive addresses from mnemonic\n",
"def derive_addresses(mnemonic, num_addresses=10):\n",
" wallet = Wallet(mnemonic)\n",
" addresses = []\n",
" for i in range(num_addresses):\n",
" account = wallet.derive_account(\"eth\", account=0, change=0, address_index=i + 1)\n",
" public_key = account[1] # Get the public key from the tuple\n",
" address = public_key_to_eth_address(public_key)\n",
" addresses.append(address)\n",
" return addresses\n",
"\n",
"# Derive addresses for each mnemonic\n",
"derived_addresses = {mnemonic: derive_addresses(mnemonic) for mnemonic in mnemonics}\n",
"\n",
"# Display the derived addresses\n",
"for mnemonic, addresses in derived_addresses.items():\n",
" print(f\"Mnemonic: {mnemonic}\")\n",
" for idx, address in enumerate(addresses):\n",
" print(f\" Address {idx + 1}: {address}\")\n",
" print(\"\\n\")\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "S4C1CpCpJkoB",
"outputId": "06f26886-43f2-4010-f148-5c2924aec3da"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Mnemonic: border summer salt divorce muscle palm ahead predict mimic enroll west secret\n",
" Address 1: 0xe07a4ed98baf83Ccd17922471Abb9962e0242339\n",
" Address 2: 0x0a285873DBE0dBC997549F29E6f60F3671AE1945\n",
" Address 3: 0x2D094eb4bb7185c0BeCcfd7cbd190B4aE83D93dc\n",
" Address 4: 0x7ECbF7EeCA5b042c9EcD9e6f3ACA61459DD98a80\n",
" Address 5: 0xBD7ba6b0A9a1c0ce6A8322473C795749CB1DD955\n",
" Address 6: 0x36401f40E384804Ff8D42A786F896945B29BE22F\n",
" Address 7: 0xf881EA148E00a9B566C3967D1f5Ca8844E18EE58\n",
" Address 8: 0x95fB68Bd8d9b5b3FA9eb39665689D99Ed81C7bfB\n",
" Address 9: 0xC06D0Bb04F15b8ccF859bA905fA67A05fe130392\n",
" Address 10: 0x5F78bb71EbA3433E3a59bbA1a8ae98c67BdC12D1\n",
"\n",
"\n",
"Mnemonic: trouble enforce giant bright trend climb gather mean jungle account window offer\n",
" Address 1: 0x05DC9948942c30c9e6Aa60B9b9CD124444754455\n",
" Address 2: 0x8b6AcA4f6633733d3A12C9600ca1ce10686082Af\n",
" Address 3: 0x854c710673B0B4067050d41f6b46e0e717d83dC4\n",
" Address 4: 0x4FeedcfF19763444D8BAD089afaC659C9cfee6cc\n",
" Address 5: 0x307F78970d4fd0AC14c510C67dDbA443563f840b\n",
" Address 6: 0xdF661C6fc03CFfaf7f585152B99564c9a0287492\n",
" Address 7: 0x5DD81b2B98dfe6b840c112569307f596018C963d\n",
" Address 8: 0xf3F952a9a60fA18afdb789716044E027138D8CBa\n",
" Address 9: 0xeb571765c0700e041c3A478E8a46B0bb4936Ea79\n",
" Address 10: 0xC248D7FB46Ef9e518E16D63e6bf8f1c9A0869eB2\n",
"\n",
"\n",
"Mnemonic: eagle waste honey local raise mystery rent guard swing clever addict walnut\n",
" Address 1: 0xAF0a784F1c2f6e5b47098aE0F4775BfD4c08c786\n",
" Address 2: 0xB72042C12Edf0BF3BdEF0c300fbDB3f63a7f29A1\n",
" Address 3: 0x9e445D270411720139326C673Fd94E3fc169BCf9\n",
" Address 4: 0x6559d1F21f1E0E2A60fc11F69323AFc911Ff7144\n",
" Address 5: 0x0621094A0E0999Ac0cAF833731Ff4742377cEc76\n",
" Address 6: 0xd3080a83A81be48fc684c4277d09e0d584Bb1886\n",
" Address 7: 0x625154Ab7DA47eFa2A26Cf9D3F7fC4e0B2e3ee7e\n",
" Address 8: 0x17D1843Cc8a81685032d94D92a9dd987Bf1Dd97c\n",
" Address 9: 0x8E8C6D22AA3b4c7448E797F97f8F7a12e3FB0bF6\n",
" Address 10: 0xa916827626B19D6BD7e2515fA27eC06cf2e12292\n",
"\n",
"\n",
"Mnemonic: cement spawn uphold village thunder envelope cry scatter inquiry voyage recipe manual\n",
" Address 1: 0x3AF18f825107B23c9d178b7E2c7A4bD955DbD1fB\n",
" Address 2: 0x323b925b2eC338FFeB07EE37947f2bDC1A0b8f11\n",
" Address 3: 0xA95C9e89bE32e842907c4c54fab2967a6D25F484\n",
" Address 4: 0x2A37Fc59982B588A92d46533eCA16A5C347E32F7\n",
" Address 5: 0x2478fc740807e8091E2c883a09487B782D2ED7a6\n",
" Address 6: 0x635290d58e30A73DF54610D2281700cA76a5a120\n",
" Address 7: 0x1a0f1fEa44260B9740DA21CF42c4E6CE01E915C9\n",
" Address 8: 0xb158F812dbdAf1480393eb4617088324b2C28351\n",
" Address 9: 0xb0646122094d8eD11802fb90700Aebddd8bc36da\n",
" Address 10: 0xc353b843419359764a9dfA0ba0b701A0F1cAF5cc\n",
"\n",
"\n",
"Mnemonic: garage rapid carbon broken merge blue sword include execute dove equip trigger\n",
" Address 1: 0x5b1019144653A6EBA786f935C72B19F73b0b581d\n",
" Address 2: 0xcCbDf432aD1A8c4C915B1c5D6d21Fc63D994b5a7\n",
" Address 3: 0xaCB08BB3c9B91F77C7E72dd0e0D18a1AF18C6EB8\n",
" Address 4: 0xD4e4D1ee1f857fDE52977933e3efb28948FcE91D\n",
" Address 5: 0x0a36Ab11C8904aF4F88ec824151ff961dF7315Bf\n",
" Address 6: 0xe65d787Fb56Fde22170B6c527998673ac2aCbbCd\n",
" Address 7: 0xEd54346348d288347a2AaB9EAf2a384d62dB8650\n",
" Address 8: 0x23ed7D5c2d5dCf234Fc9D9E058Aaf72f22672b6e\n",
" Address 9: 0x523ba137c46c712e8e20F225B514D7C718d7b4d0\n",
" Address 10: 0x464490fbafaCae901c92ebBe0d7bC1109B29e8e1\n",
"\n",
"\n",
"Mnemonic: basic comic puppy aware sound private market elbow galaxy mean dragon floor\n",
" Address 1: 0xc59E06f0FE3F45EAB800F0B3b0063E6A2DeC4C4F\n",
" Address 2: 0x5D37c0ea01042cf8D753F13Abb9c1674f020512F\n",
" Address 3: 0x19533EEbE95f522aBDF9A6b1392354C7426264CD\n",
" Address 4: 0xf10B59fcea74B3a69040e2BaE87b01a3A904faa6\n",
" Address 5: 0x30dC612764AdAC30aE06DF0F63D0e8f801B78FAB\n",
" Address 6: 0x3Dc958c2a3E93232F2cCd1270d4c8bFE684427e7\n",
" Address 7: 0x63d9aC69710619c340037fc0D1D5170674732411\n",
" Address 8: 0x921483Ab2d2a18015a05fb21a9DC48BE1B77D6cb\n",
" Address 9: 0x5D4b04405d3b99c7278ef307CD6F51d4452D5181\n",
" Address 10: 0x0634044ea49ba82D055d5E699324b7618093aB11\n",
"\n",
"\n",
"Mnemonic: lab bullet lonely lunch achieve hobby genre shrimp title tiger release faculty\n",
" Address 1: 0x35B44e7103F99b0ab4D8eAEf39864c413fBAf378\n",
" Address 2: 0xA03F78302078E9872aBBf0518221996baB50E889\n",
" Address 3: 0x33eB2d2e60268771946913F9F9E6ebaED6179f20\n",
" Address 4: 0xc8ec209F1f71884e397635BD82b2aD901A10b6E7\n",
" Address 5: 0xaD05BA998A861E19E3c75e78D22c98AF99c16aFA\n",
" Address 6: 0x8F9d6fA182Ec0F214ef6894069d98F55Ef7E8fa9\n",
" Address 7: 0x7f0f9054EBDeAab5490a9DCa1a1EA2cF880917aB\n",
" Address 8: 0xa88228fb2fdE57Ba9A67A16B75A9661eC3A6e08A\n",
" Address 9: 0xfBd4fE134973715cbb8e364B6B2b127F0b753b5E\n",
" Address 10: 0x0E1523b410C2b7E0B150591E70Cf67833ea1F382\n",
"\n",
"\n",
"Mnemonic: view piano duty goddess owner decline bless cargo output medal torch grid\n",
" Address 1: 0x96bc0F5E93cad4C90eB0eB282f62779F248f913B\n",
" Address 2: 0x98effea26910ebEA48f7F3e90D8F3eb053a9934c\n",
" Address 3: 0xC8b6c1F2A025386E4Da31aFe946D2908913423Da\n",
" Address 4: 0x05A53a1dA897e9155957e50CE3365EeC25A3c499\n",
" Address 5: 0x99b4f3722BAaF783051154993819993f8314Ad96\n",
" Address 6: 0x804dCc9A4424cD283a7D3eE3EF1dB67c6896A112\n",
" Address 7: 0x90844aD31d3cab1692e682f9f8001c46abEa7715\n",
" Address 8: 0x7aF171Dd7808A747293850accbc47b53015b4279\n",
" Address 9: 0x97B2B07Be9c5eFA05Ee82Fe91Ac922a9aFB849De\n",
" Address 10: 0x1EE4fb39bf91Ef7438E0e588F7e7162707BB8536\n",
"\n",
"\n",
"Mnemonic: clip shift rigid useful hub spatial badge solid guilt modify craft edit\n",
" Address 1: 0x5387221C6B4E739EE9265B472CBfC7eE4D7bD6ED\n",
" Address 2: 0x7CB5eB03986350D9ADF24cDfCFcc4B185C713dF3\n",
" Address 3: 0xf6c25e514FA4a60Cfc4c22dC58DDA65E119C2E9A\n",
" Address 4: 0xbc6C75916a311D6537851eA557ab29f1f3432C40\n",
" Address 5: 0x59988B385750CAA1eCc3c2605539Cc2caf8f5cF2\n",
" Address 6: 0x3901C4293F9c93ab5cd6166Ea98bF12cd0bb1c76\n",
" Address 7: 0x1b5A1B7174C30DC6A765cC1c57031F807a93cfE4\n",
" Address 8: 0x7B9c69412c33eECe103CD21EFD399f3770c81d16\n",
" Address 9: 0xC45b56c46bDdCC9d5bFbe6c34a30e287dF5B29a1\n",
" Address 10: 0xf08a87589E8A8d38149B21Dcc84DdAB83e1D0744\n",
"\n",
"\n",
"Mnemonic: wreck empty coconut hidden silent alter refuse lottery fatal mystery brave treat\n",
" Address 1: 0xF029f99B780F0FbA1D345C67Ca2153ae3C129A03\n",
" Address 2: 0xe7479eeDbf24f0f7e08723D459A4634ae0F9c241\n",
" Address 3: 0xac9e0F383163FA9c1aef50Ad013Ed23C7c8FCC2E\n",
" Address 4: 0x64C3a1659c1A3fddBA6deCfFaD49596C9b6499e3\n",
" Address 5: 0x9F9DA53D0cd131Ca9caeBdFac2527e61A5421a2b\n",
" Address 6: 0xaB1FB5CaCBCa03DDCDd642D253172690f8945663\n",
" Address 7: 0x1fa02bA82841E4E0b93B9A043C8182C8a637223e\n",
" Address 8: 0x441ad8e3F61Ae54DB3D545baF749A85058dfCbF4\n",
" Address 9: 0x7D0c7Ecd3ef5166Abb7E8506D27B8D11afa4620d\n",
" Address 10: 0xeDADB17deAB70532Fc693FD5152186326aeFa58e\n",
"\n",
"\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"pip install"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "SapgJWHJJvy9",
"outputId": "6559732b-588b-4289-8f80-49020007c2c3"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Requirement already satisfied: mnemonic in /usr/local/lib/python3.10/dist-packages (0.20)\n",
"Requirement already satisfied: bip44 in /usr/local/lib/python3.10/dist-packages (0.1.4)\n",
"Requirement already satisfied: eth-utils in /usr/local/lib/python3.10/dist-packages (5.0.0)\n",
"Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (2.1.4)\n",
"Requirement already satisfied: openpyxl in /usr/local/lib/python3.10/dist-packages (3.1.5)\n",
"Requirement already satisfied: bip32<4.0,>=3.1 in /usr/local/lib/python3.10/dist-packages (from bip44) (3.4)\n",
"Requirement already satisfied: pycryptodome<4.0.0,>=3.16.0 in /usr/local/lib/python3.10/dist-packages (from bip44) (3.20.0)\n",
"Requirement already satisfied: eth-hash>=0.3.1 in /usr/local/lib/python3.10/dist-packages (from eth-utils) (0.7.0)\n",
"Requirement already satisfied: eth-typing>=5.0.0 in /usr/local/lib/python3.10/dist-packages (from eth-utils) (5.0.0)\n",
"Requirement already satisfied: hexbytes>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from eth-utils) (1.2.1)\n",
"Requirement already satisfied: cytoolz>=0.10.1 in /usr/local/lib/python3.10/dist-packages (from eth-utils) (0.12.3)\n",
"Requirement already satisfied: numpy<2,>=1.22.4 in /usr/local/lib/python3.10/dist-packages (from pandas) (1.26.4)\n",
"Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.10/dist-packages (from pandas) (2.8.2)\n",
"Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2024.1)\n",
"Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2024.1)\n",
"Requirement already satisfied: et-xmlfile in /usr/local/lib/python3.10/dist-packages (from openpyxl) (1.1.0)\n",
"Requirement already satisfied: base58~=2.0 in /usr/local/lib/python3.10/dist-packages (from bip32<4.0,>=3.1->bip44) (2.1.1)\n",
"Requirement already satisfied: coincurve<19,>=15.0 in /usr/local/lib/python3.10/dist-packages (from bip32<4.0,>=3.1->bip44) (18.0.0)\n",
"Requirement already satisfied: toolz>=0.8.0 in /usr/local/lib/python3.10/dist-packages (from cytoolz>=0.10.1->eth-utils) (0.12.1)\n",
"Requirement already satisfied: typing-extensions>=4.5.0 in /usr/local/lib/python3.10/dist-packages (from eth-typing>=5.0.0->eth-utils) (4.12.2)\n",
"Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n",
"Requirement already satisfied: asn1crypto in /usr/local/lib/python3.10/dist-packages (from coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (1.5.1)\n",
"Requirement already satisfied: cffi>=1.3.0 in /usr/local/lib/python3.10/dist-packages (from coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (1.17.0)\n",
"Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.3.0->coincurve<19,>=15.0->bip32<4.0,>=3.1->bip44) (2.22)\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"from itertools import permutations\n",
"from mnemonic import Mnemonic\n",
"from bip44 import Wallet\n",
"from eth_utils import to_checksum_address, keccak\n",
"import pandas as pd\n",
"\n",
"# Function to convert public key to Ethereum address\n",
"def public_key_to_eth_address(public_key):\n",
" return to_checksum_address(keccak(public_key[1:])[-20:])\n",
"\n",
"# Original mnemonic words\n",
"mnemonic_words = \"wreck empty coconut hidden silent alter refuse lottery fatal mystery brave treat\".split()\n",
"\n",
"# Get all possible permutations of the mnemonic words\n",
"mnemonic_permutations = list(permutations(mnemonic_words))\n",
"\n",
"# Function to derive addresses from mnemonic\n",
"def derive_addresses(mnemonic, num_addresses=3):\n",
" wallet = Wallet(mnemonic)\n",
" addresses = []\n",
" for i in range(num_addresses):\n",
" account = wallet.derive_account(\"eth\", account=0, change=0, address_index=i)\n",
" public_key = account[1] # Get the public key from the tuple\n",
" address = public_key_to_eth_address(public_key)\n",
" addresses.append(address)\n",
" return addresses\n",
"\n",
"# Prepare data for Excel export\n",
"data = []\n",
"\n",
"for permutation in mnemonic_permutations:\n",
" mnemonic = \" \".join(permutation)\n",
" addresses = derive_addresses(mnemonic)\n",
" data.append([mnemonic, *addresses])\n",
"\n",
"# Create a DataFrame\n",
"df = pd.DataFrame(data, columns=[\"Mnemonic\", \"ETH Address 1\", \"ETH Address 2\", \"ETH Address 3\"])\n",
"\n",
"# Export to Excel\n",
"output_path = \"eth_addresses_permutations.xlsx\"\n",
"df.to_excel(output_path, index=False)\n",
"\n",
"print(f\"Excel file has been created: {output_path}\")\n"
],
"metadata": {
"id": "TNW6s_bBMnG_"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from math import factorial\n",
"\n",
"# Calculate the number of permutations of 12 words\n",
"num_words = 12\n",
"num_permutations = factorial(num_words)\n",
"\n",
"num_permutations"
],
"metadata": {
"id": "RXEiTaH0Mx2X"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Calculate the number of combinations for a 12-word mnemonic phrase from a set of 2048 words\n",
"num_words_total = 2048\n",
"num_combinations = num_words_total ** 12\n",
"\n",
"num_combinations"
],
"metadata": {
"id": "4KXzG1FjN4Qh"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import itertools\n",
"import numpy as np\n",
"from numba import cuda\n",
"from eth_utils import to_checksum_address, keccak\n",
"\n",
"# Number of words in mnemonic\n",
"num_words = 12\n",
"\n",
"# Hypothetical function to derive addresses on GPU (simplified example)\n",
"@cuda.jit\n",
"def derive_addresses_on_gpu(permutations, addresses):\n",
" idx = cuda.grid(1)\n",
" if idx < permutations.shape[0]:\n",
" mnemonic = permutations[idx]\n",
" # Convert mnemonic to Ethereum address (simplified)\n",
" addresses[idx] = keccak(mnemonic.encode('utf-8'))[-20:]\n",
"\n",
"# Generate permutations (this step is still CPU-bound and needs optimization)\n",
"words = [\"wreck\", \"empty\", \"coconut\", \"hidden\", \"silent\", \"alter\", \"refuse\", \"lottery\", \"fatal\", \"mystery\", \"brave\", \"treat\"]\n",
"permutations = list(itertools.permutations(words)) # This will still be CPU-bound\n",
"\n",
"# Convert permutations to numpy array for GPU processing\n",
"permutations_np = np.array([' '.join(p) for p in permutations], dtype=np.object)\n",
"\n",
"# Allocate memory on GPU\n",
"addresses_gpu = cuda.device_array(len(permutations_np), dtype=np.object)\n",
"\n",
"# Launch kernel\n",
"threads_per_block = 256\n",
"blocks_per_grid = (len(permutations_np) + (threads_per_block - 1)) // threads_per_block\n",
"derive_addresses_on_gpu[blocks_per_grid, threads_per_block](permutations_np, addresses_gpu)\n",
"\n",
"# Copy back results\n",
"addresses = addresses_gpu.copy_to_host()\n",
"\n",
"# Print some of the results\n",
"print(addresses[:10])\n"
],
"metadata": {
"id": "zaGA7FvfOYo6"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import secrets\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from scipy.stats import chisquare\n",
"\n",
"# Generate a large number of private keys\n",
"def generate_private_keys(num_keys=1000000):\n",
" keys = []\n",
" for _ in range(num_keys):\n",
" key = secrets.token_bytes(32) # 32 bytes for a 256-bit private key\n",
" keys.append(int.from_bytes(key, byteorder='big'))\n",
" return keys\n",
"\n",
"# Perform a frequency test on the keys\n",
"def frequency_test(keys):\n",
" bit_counts = [0] * 256\n",
" for key in keys:\n",
" for i in range(256):\n",
" if key & (1 << i):\n",
" bit_counts[i] += 1\n",
" return bit_counts\n",
"\n",
"# Generate and analyze private keys\n",
"private_keys = generate_private_keys()\n",
"bit_counts = frequency_test(private_keys)\n",
"\n",
"# Plot the results\n",
"plt.bar(range(256), bit_counts)\n",
"plt.title('Bit Frequency in Private Keys')\n",
"plt.xlabel('Bit Position')\n",
"plt.ylabel('Frequency')\n",
"plt.show()\n",
"\n",
"# Perform a chi-square test to check uniform distribution\n",
"chi2, p = chisquare(bit_counts)\n",
"print(f\"Chi-square statistic: {chi2}, p-value: {p}\")\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 490
},
"id": "zIVBXRW8OZNt",
"outputId": "5a8e0939-7d50-4d90-b54a-a20e5decea9f"
},
"execution_count": null,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
],
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAlUAAAHHCAYAAACWQK1nAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABHqUlEQVR4nO3deVyVdf7//+dhO4AKuAGSG7mGG4VJjGkujGjkZDqFZolLlgWTStrkTF+3FstcGzGnRbHUccml1NIUt0rcUEbTctQ0LFnMBRQTEK7fH/04H48gIF4G6ON+u51bnuv9ut7X67zPEZ9d5zoHi2EYhgAAAHBTHMq7AQAAgNsBoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCqjALBaLxo8fX95toBQGDhyohg0blncbdsaPHy+LxVLebQB3DEIV8AeKi4uTxWKxu3l7e6tz58768ssvS9x/+/btGj9+vM6fP1+q4w0cOLDQ8Qpu69atu8lHg1tpy5Ytds+Xs7Oz7r77bg0YMEA//vhjebdn8+abb2rVqlWmz9uwYUM98sgjhbZ/8skncnR0VPfu3XX58mXTjwvcDKfybgC4E02cOFH+/v4yDENpaWmKi4vTww8/rNWrV9v9Q/Lbb7/Jyen//ppu375dEyZM0MCBA+Xl5VWqY1mtVn344YeFtrdp0+amHwf+zwcffKD8/HzT533xxRd1//33Kzc3V3v37tX777+vtWvX6sCBA/Lz8yt231dffVWvvPKK6T1d7c0339Rf//pX9erV65YeR5IWLlyogQMHKjQ0VKtWrZKrq+stPyZwIwhVQDno0aOH2rZta7s/ZMgQ+fj46D//+Y9dqDLjHw0nJyc99dRTpa7PyspSlSpVbvq4dxpnZ+dbMm+HDh3017/+VZI0aNAgNW3aVC+++KLmz5+vMWPGFLlPwXPo5ORkF8ors8WLFysyMlJdunTRZ599RqBChcTbf0AF4OXlJTc3t0L/AF59TdX48eM1evRoSZK/v7/tbaETJ06U+bgF19wcOnRITz75pKpXr64HH3zQNr5gwQIFBQXJzc1NNWrUUN++fXXy5MlC87z//vtq1KiR3Nzc1K5dO3399dfq1KmTOnXqZKspeOvz2n4L3ubasmWL3fadO3eqe/fu8vT0lLu7ux566CF9++23RfZ/9OhR29k7T09PDRo0SJcuXSrU54IFC9SuXTu5u7urevXq6tixo7766itJUmRkpGrVqqXc3NxC+3Xr1k3NmjUrdi2vvabqxIkTslgsmjJlim19rFar7r//fu3evbvYuYrTpUsXSdLx48clFf8cXntNVcuWLdW5c+dCc+bn5+uuu+6yhTdJmjJliv70pz+pZs2acnNzU1BQkD799FO7/SwWi7KysjR//nzb63HgwIG28V9++UWDBw+Wj4+PrFarWrRooblz597wY166dKmeeuopderUSZ9//nmhQFXS63TcuHFydnbW6dOnC8397LPPysvLy/ZW4p49exQWFqZatWrJzc1N/v7+Gjx48A33jDsToQooBxkZGfr11191+vRpHTx4UM8//7wuXrxY7Bml3r17q1+/fpKk6dOn65NPPtEnn3yi2rVrl3i8X3/91e6WkZFhN/7444/r0qVLevPNNzV06FBJ0htvvKEBAwaoSZMmmjZtmkaMGKH4+Hh17NjR7pqujz76SM8995x8fX01efJktW/fXn/5y1+KDF+ltWnTJnXs2FGZmZkaN26c3nzzTZ0/f15dunTRrl27CtU/8cQTunDhgiZNmqQnnnhCcXFxmjBhgl3NhAkT9PTTT8vZ2VkTJ07UhAkTVK9ePW3atEmS9PTTT+vMmTNav3693X6pqanatGnTDZ3tu9qiRYv0zjvv6LnnntPrr7+uEydOqHfv3kWGt9I4duyYJKlmzZp224t6Dq8VERGhbdu2KTU11W77N998o1OnTqlv3762bTNnztS9996riRMn6s0335STk5Mef/xxrV271lbzySefyGq1qkOHDrbX43PPPSdJSktL0wMPPKCNGzcqOjpaM2fOVOPGjTVkyBDNmDGj1I93+fLl6t+/vzp27KjVq1fLzc3Nbrw0r9Onn35aV65c0ZIlS+z2zcnJ0aeffqo+ffrI1dVV6enp6tatm06cOKFXXnlF//rXv9S/f3/t2LGj1P3iDmcA+MPMmzfPkFToZrVajbi4uEL1koxx48bZ7r/zzjuGJOP48eOlOl5kZGSRx3vooYcMwzCMcePGGZKMfv362e134sQJw9HR0XjjjTfsth84cMBwcnKybc/JyTG8vb2NwMBAIzs721b3/vvv2x3n6sd+be+bN282JBmbN282DMMw8vPzjSZNmhhhYWFGfn6+re7SpUuGv7+/8ec//9m2raD/wYMH28352GOPGTVr1rTdP3LkiOHg4GA89thjRl5enl1twTHy8vKMunXrGhEREXbj06ZNMywWi/Hjjz8axYmMjDQaNGhgu3/8+HFDklGzZk3j7Nmztu2fffaZIclYvXp1sfMVrMvcuXON06dPG6dOnTLWrl1rNGzY0LBYLMbu3bvt1uDa5/DqsQKHDx82JBn/+te/7OpeeOEFo2rVqsalS5ds267+s2H8/ly3bNnS6NKli932KlWqGJGRkYWOPWTIEKNOnTrGr7/+are9b9++hqenZ6H5r9WgQQPDz8/PcHJyMjp16mRkZWUVqint69QwDCMkJMQIDg62q1uxYoXda2/lypWGJNvaAjeKM1VAOYiNjdWGDRu0YcMGLViwQJ07d9YzzzyjFStWmH4sV1dX27EKblOnTrWrGTZsmN39FStWKD8/X0888YTdGS5fX181adJEmzdvlvT7WyXp6ekaNmyYXFxcbPsPHDhQnp6eZeo3KSlJR44c0ZNPPqkzZ87Yjp2VlaWuXbtq27ZthS4Iv7b/Dh066MyZM8rMzJQkrVq1Svn5+Ro7dqwcHOx/7BW8Pebg4KD+/fvr888/14ULF2zjCxcu1J/+9Cf5+/uX6fFERESoevXqdr1JKvUn+AYPHqzatWvLz89P4eHhtrfbrr4mTyq8BkVp2rSpAgMD7c7Y5OXl6dNPP1XPnj3tzgJd/edz584pIyNDHTp00N69e0s8jmEYWr58uXr27CnDMOxeQ2FhYcrIyCjVPGfPntWVK1dUt27dQmeopNK/TiVpwIAB2rlzp+1Mn/T7c1uvXj099NBDkmT78MeaNWvKfCYRd7bb4wpGoJJp166d3T+K/fr107333qvo6Gg98sgjdgHlZjk6Oio0NLTYmmsDw5EjR2QYhpo0aVJkfcFF2T/99JMkFaor+Ph/WRw5ckTS79c4XU9GRoZdUKlfv77deMHYuXPn5OHhoWPHjsnBwUEBAQHFHnvAgAF6++23tXLlSg0YMECHDx9WYmKi5syZU6bHUlJvpTF27Fh16NBBjo6OqlWrlu65554iLz4vbeiLiIjQP/7xD/3yyy+66667tGXLFqWnpysiIsKubs2aNXr99deVlJSk7Oxs2/bSfO/V6dOndf78eb3//vt6//33i6xJT08vcZ6uXbuqfv36eu+991SjRg3NnDnTbry0r1Pp98c9YsQILVy4UGPHjlVGRobWrFmjkSNH2h7TQw89pD59+mjChAmaPn26OnXqpF69eunJJ5+U1WotsV+AUAVUAA4ODurcubNmzpypI0eOqEWLFn/o8a89C5Cfny+LxaIvv/xSjo6OheqrVq16w8e43j/GeXl5hY4tSe+8844CAwOL3Ofa4xfVo/T7GZMbERAQoKCgIC1YsEADBgzQggUL5OLioieeeOKG5jGzt1atWpUYiqXCz+H1REREaMyYMVq2bJlGjBihpUuXytPTU927d7fVfP311/rLX/6ijh07avbs2apTp46cnZ01b948LVq0qMRjFDyHTz311HXDcevWrUvV76xZs3Tu3Dm9++67ql69ut2X4d7I67R69ep65JFHbKHq008/VXZ2tt21chaLRZ9++ql27Nih1atXa/369Ro8eLCmTp2qHTt2lOl1jzsLoQqoIK5cuSJJunjx4nVr/qhvx27UqJEMw5C/v7+aNm163boGDRpI+v2MQcGn0iQpNzdXx48ft/surIIzNNd+cWnB2a6rjy1JHh4epQoTpdGoUSPl5+fr0KFD1w1qBQYMGKCYmBilpKRo0aJFCg8PtzsrVtn5+/urXbt2WrJkiaKjo7VixQr16tXL7kzM8uXL5erqqvXr19ttnzdvXqH5inpN1q5dW9WqVVNeXt5NP4cODg76+OOPlZGRoQkTJqhGjRp68cUXJZX+dVpgwIABevTRR7V7924tXLhQ9957b5H/A/PAAw/ogQce0BtvvKFFixapf//+Wrx4sZ555pmbeiy4/XFNFVAB5Obm6quvvpKLi4vuueee69YVfH9Uab9Rvax69+4tR0dHTZgwodAZFcMwdObMGUlS27ZtVbt2bc2ZM0c5OTm2mri4uEI9FoSlbdu22bbl5eUVensoKChIjRo10pQpU4oMmEV9LL4kvXr1koODgyZOnFjoeqxrH1+/fv1ksVg0fPhw/fjjj2X+1F9FFhERoR07dmju3Ln69ddfC7315+joKIvFYncW8cSJE0V+c3qVKlUKPdeOjo7q06ePli9fru+++67QPjf6HDo7O+vTTz9V+/btNWLECH3yySeSSv86LdCjRw/VqlVLb7/9trZu3VrouT137lyheQpC+NVvgQLXw5kqoBx8+eWX+uGHHyT9fm3JokWLdOTIEb3yyivy8PC4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AIAJCFUAAAAmIFQBAACYoEyh6scffzS7DwAAgEqtTKGqcePG6ty5sxYsWKDLly+b3RMAAEClU6ZQtXfvXrVu3VoxMTHy9fXVc889p127dpndGwAAQKVRplAVGBiomTNn6tSpU5o7d65SUlL04IMPqmXLlpo2bZpOnz5dqnnee+89tW7dWh4eHvLw8FBISIi+/PJL2/jly5cVFRWlmjVrqmrVqurTp4/S0tLs5khOTlZ4eLjc3d3l7e2t0aNH68qVK3Y1W7Zs0X333Ser1arGjRsrLi6uUC+xsbFq2LChXF1dFRwcXCgklqYXAABw57qpC9WdnJzUu3dvLVu2TG+//baOHj2qUaNGqV69ehowYIBSUlKK3b9u3bp66623lJiYqD179qhLly569NFHdfDgQUnSyJEjtXr1ai1btkxbt27VqVOn1Lt3b9v+eXl5Cg8PV05OjrZv36758+crLi5OY8eOtdUcP35c4eHh6ty5s5KSkjRixAg988wzWr9+va1myZIliomJ0bhx47R37161adNGYWFhSk9Pt9WU1AsAALiz3VSo2rNnj1544QXVqVNH06ZN06hRo3Ts2DFt2LBBp06d0qOPPlrs/j179tTDDz+sJk2aqGnTpnrjjTdUtWpV7dixQxkZGfroo480bdo0denSRUFBQZo3b562b9+uHTt2SJK++uorHTp0SAsWLFBgYKB69Oih1157TbGxscrJyZEkzZkzR/7+/po6daruueceRUdH669//aumT59u62PatGkaOnSoBg0apICAAM2ZM0fu7u6aO3euJJWqFwAAcGcrU6iaNm2aWrVqpT/96U86deqUPv74Y/300096/fXX5e/vrw4dOiguLk579+4t9Zx5eXlavHixsrKyFBISosTEROXm5io0NNRW07x5c9WvX18JCQmSpISEBLVq1Uo+Pj62mrCwMGVmZtrOdiUkJNjNUVBTMEdOTo4SExPtahwcHBQaGmqrKU0vRcnOzlZmZqbdDQAA3J6cyrLTe++9p8GDB2vgwIGqU6dOkTXe3t766KOPSpzrwIEDCgkJ0eXLl1W1alWtXLlSAQEBSkpKkouLi7y8vOzqfXx8lJqaKklKTU21C1QF4wVjxdVkZmbqt99+07lz55SXl1dkzQ8//GCbo6ReijJp0iRNmDChxDUAAACVX5lC1ZEjR0qscXFxUWRkZIl1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2/aIiAitW7fOtOYAAAAqizJdU/XVV19p/fr1qlu3rt32Jk2a6KeffjKlMQAAgMqkTGeqsrKy7M5QFTh79qysVutNNwUAAFDZlClUdejQQR9//LHtvsViUX5+viZPnqzOnTub1hwAAEBlUaa3/yZPnqyuXbtqz549ysnJ0csvv6yDBw/q7Nmz+vbbb83uEQAAoMIr05mqli1b6n//+58efPBBPfroo8rKylLv3r21b98+NWrUyOweAQAAKrwbPlOVm5ur7t27a86cOfrnP/95K3oCAACodG74TJWzs7P2799/K3oBAACotMr09t9TTz2ljz76yOxeAAAAKq0yXah+5coVzZ07Vxs3blRQUFCh3/k3bdo0U5oDAACoLG4oVP34449q2LChvvvuO913332SpP/97392NRaLxbzuAAAAKokbClVNmjRRSkqKNm/eLOn3X0vz7rvvysfH55Y0BwAAUFnc0DVVhmHY3f/yyy+VlZVlakMAAACVUZkuVC9wbcgCAAC4U91QqLJYLIWumeIaKgAAgBu8psowDA0cOND2S5MvX76sYcOGFfr034oVK8zrEAAAoBK4oVAVGRlpd/+pp54ytRkAAIDK6oZC1bx5825VHwAAAJXaTV2oDgAAgN8RqgAAAExQrqFq0qRJuv/++1WtWjV5e3urV69eOnz4sF3N5cuXFRUVpZo1a6pq1arq06eP0tLS7GqSk5MVHh4ud3d3eXt7a/To0bpy5YpdzZYtW3TffffJarWqcePGiouLK9RPbGysGjZsKFdXVwUHB2vXrl033AsAALgzlWuo2rp1q6KiorRjxw5t2LBBubm56tatm90Xio4cOVKrV6/WsmXLtHXrVp06dUq9e/e2jefl5Sk8PFw5OTnavn275s+fr7i4OI0dO9ZWc/z4cYWHh6tz585KSkrSiBEj9Mwzz2j9+vW2miVLligmJkbjxo3T3r171aZNG4WFhSk9Pb3UvQAAgDtXmX6hslnWrVtndz8uLk7e3t5KTExUx44dlZGRoY8++kiLFi1Sly5dJP1+sfw999yjHTt26IEHHtBXX32lQ4cOaePGjfLx8VFgYKBee+01/f3vf9f48ePl4uKiOXPmyN/fX1OnTpUk3XPPPfrmm280ffp0hYWFSfr9l0APHTpUgwYNkiTNmTNHa9eu1dy5c/XKK6+UqhcAAHDnqlDXVGVkZEiSatSoIUlKTExUbm6uQkNDbTXNmzdX/fr1lZCQIElKSEhQq1at7H7/YFhYmDIzM3Xw4EFbzdVzFNQUzJGTk6PExES7GgcHB4WGhtpqStPLtbKzs5WZmWl3AwAAt6cKE6ry8/M1YsQItW/fXi1btpQkpaamysXFRV5eXna1Pj4+Sk1NtdVc+wudC+6XVJOZmanffvtNv/76q/Ly8oqsuXqOknq51qRJk+Tp6Wm71atXr5SrAQAAKpsKE6qioqL03XffafHixeXdimnGjBmjjIwM2+3kyZPl3RIAALhFyvWaqgLR0dFas2aNtm3bprp169q2+/r6KicnR+fPn7c7Q5SWliZfX19bzbWf0iv4RN7VNdd+Si8tLU0eHh5yc3OTo6OjHB0di6y5eo6SermW1Wq1/UofAABweyvXM1WGYSg6OlorV67Upk2b5O/vbzceFBQkZ2dnxcfH27YdPnxYycnJCgkJkSSFhITowIEDdp/S27Bhgzw8PBQQEGCruXqOgpqCOVxcXBQUFGRXk5+fr/j4eFtNaXoBAAB3rnI9UxUVFaVFixbps88+U7Vq1WzXJnl6esrNzU2enp4aMmSIYmJiVKNGDXl4eOhvf/ubQkJCbJ+269atmwICAvT0009r8uTJSk1N1auvvqqoqCjbWaJhw4Zp1qxZevnllzV48GBt2rRJS5cu1dq1a229xMTEKDIyUm3btlW7du00Y8YMZWVl2T4NWJpeAADAnatcQ9V7770nSerUqZPd9nnz5mngwIGSpOnTp8vBwUF9+vRRdna2wsLCNHv2bFuto6Oj1qxZo+eff14hISGqUqWKIiMjNXHiRFuNv7+/1q5dq5EjR2rmzJmqW7euPvzwQ9vXKUhSRESETp8+rbFjxyo1NVWBgYFat26d3cXrJfUCAADuXOUaqgzDKLHG1dVVsbGxio2NvW5NgwYN9MUXXxQ7T6dOnbRv375ia6KjoxUdHX1TvQAAgDtThfn0HwAAQGVGqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCgAAwASEKgAAABMQqgAAAExAqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCgAAwASEKgAAABMQqgAAAExAqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCgAAwASEKgAAABMQqgAAAExAqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCgAAwASEKgAAABMQqgAAAExAqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATECoAgAAMAGhCgAAwATlGqq2bdumnj17ys/PTxaLRatWrbIbNwxDY8eOVZ06deTm5qbQ0FAdOXLErubs2bPq37+/PDw85OXlpSFDhujixYt2Nfv371eHDh3k6uqqevXqafLkyYV6WbZsmZo3by5XV1e1atVKX3zxxQ33AgAA7lzlGqqysrLUpk0bxcbGFjk+efJkvfvuu5ozZ4527typKlWqKCwsTJcvX7bV9O/fXwcPHtSGDRu0Zs0abdu2Tc8++6xtPDMzU926dVODBg2UmJiod955R+PHj9f7779vq9m+fbv69eunIUOGaN++ferVq5d69eql77777oZ6AQAAdy6n8jx4jx491KNHjyLHDMPQjBkz9Oqrr+rRRx+VJH388cfy8fHRqlWr1LdvX33//fdat26ddu/erbZt20qS/vWvf+nhhx/WlClT5Ofnp4ULFyonJ0dz586Vi4uLWrRooaSkJE2bNs0WvmbOnKnu3btr9OjRkqTXXntNGzZs0KxZszRnzpxS9QIAAO5sFfaaquPHjys1NVWhoaG2bZ6engoODlZCQoIkKSEhQV5eXrZAJUmhoaFycHDQzp07bTUdO3aUi4uLrSYsLEyHDx/WuXPnbDVXH6egpuA4pekFAADc2cr1TFVxUlNTJUk+Pj522318fGxjqamp8vb2tht3cnJSjRo17Gr8/f0LzVEwVr16daWmppZ4nJJ6KUp2drays7Nt9zMzM4t5xAAAoDKrsGeqbgeTJk2Sp6en7VavXr3ybgkAANwiFTZU+fr6SpLS0tLstqelpdnGfH19lZ6ebjd+5coVnT171q6mqDmuPsb1aq4eL6mXoowZM0YZGRm228mTJ0t41AAAoLKqsKHK399fvr6+io+Pt23LzMzUzp07FRISIkkKCQnR+fPnlZiYaKvZtGmT8vPzFRwcbKvZ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f39/NWrUSNWqVbPbfs899+jbb7+12/btt98qICDAdt/NzU09e/bUu+++qy1btighIUEHDhwo8jjOzs7F9uTh4SE/P78Sjwmg/HFNFYBKKTs7W6mpqZKkc+fOadasWbp48aJ69uxZZH2DBg1ksVi0Zs0aPfzww3Jzc7Ndk3UjRo8erSeeeEL33nuvQkNDtXr1aq1YsUIbN26UJMXFxSkvL0/BwcFyd3fXggUL5ObmpgYNGhQ5X8OGDRUfH6/27dvLarWqevXqRR5z3LhxatSokQIDAzVv3jwlJSVp4cKFN9w/gFuHM1UAKqV169apTp06qlOnjoKDg7V7924tW7ZMnTp1KrL+rrvu0oQJE/TKK6/Ix8dH0dHRZTpur169NHPmTE2ZMkUtWrTQv//9b82bN892XC8vL33wwQdq3769WrdurY0bN2r16tXX/d6pqVOnasOGDapXr57uvffeImtefPFFxcTE6KWXXlKrVq20bt06ff7552rSpEmZHgOAW8NiGIZR3k0AAABUdpypAgAAMAGhCgAAwASEKgAAABMQqgAAAExAqAIAADABoQoAAMAEhCoAAAATEKoAAABMQKgCAAAwAaEKAADABIQqAAAAExCqAAAATPD/Abi0wwPkx9n6AAAAAElFTkSuQmCC\n"
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Chi-square statistic: 126.51910364694623, p-value: 0.9999999999991498\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"from web3 import Web3\n",
"\n",
"# Conectar a un nodo de Ethereum usando Infura\n",
"infura_url = 'https://mainnet.infura.io/v3/{\"YOUR INFURA APY KEY}'\n",
"web3 = Web3(Web3.HTTPProvider(infura_url))\n",
"\n",
"# Verificar la conexión\n",
"if web3.is_connected():\n",
" print(\"Connected to Ethereum\")\n",
"else:\n",
" print(\"Not connected\")\n",
"\n",
"# Rango de bloques para extraer datos\n",
"start_block = 1000000\n",
"end_block = 1010000\n",
"\n",
"# Extraer claves públicas\n",
"public_keys = []\n",
"\n",
"for block_number in range(start_block, end_block):\n",
" block = web3.eth.get_block(block_number, full_transactions=True)\n",
" for tx in block.transactions:\n",
" try:\n",
" # Verificar si la transacción tiene los campos necesarios\n",
" if hasattr(tx, 'v') and hasattr(tx, 'r') and hasattr(tx, 's') and hasattr(tx, 'rawTransaction'):\n",
" # Intentar recuperar la clave pública\n",
" public_key = web3.eth.account.recover_transaction(tx.rawTransaction)\n",
" public_keys.append(public_key)\n",
" except Exception as e:\n",
" print(f\"Error processing transaction {tx.hash}: {str(e)}\")\n",
" continue\n",
"\n",
"# Analizar claves públicas para encontrar agrupamientos\n",
"from collections import Counter\n",
"\n",
"# Contar la frecuencia de cada clave pública\n",
"key_counts = Counter(public_keys)\n",
"\n",
"# Identificar claves repetidas\n",
"repeated_keys = [key for key, count in key_counts.items() if count > 1]\n",
"\n",
"# Mostrar resultados\n",
"print(f\"Total number of unique public keys: {len(public_keys)}\")\n",
"print(f\"Number of repeated public keys: {len(repeated_keys)}\")\n",
"\n",
"# Si hay claves repetidas, imprimir algunas de ellas\n",
"if repeated_keys:\n",
" print(\"Some repeated public keys:\")\n",
" for key in repeated_keys[:10]: # Mostrar las primeras 10 claves repetidas\n",
" print(key)\n"
],
"metadata": {
"id": "E_1dcvfZP_0i",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "8180b893-682c-4d93-a7e7-f16bdda19552"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Connected to Ethereum\n",
"Total number of unique public keys: 0\n",
"Number of repeated public keys: 0\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"import numpy as np\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"# Assuming public_keys is a list of hexadecimal strings\n",
"public_key_values = [int(key, 16) for key in public_keys]\n",
"public_key_values = np.array(public_key_values).reshape(-1, 1)\n",
"\n",
"# Optional: Normalize the data\n",
"scaler = StandardScaler()\n",
"public_key_values_normalized = scaler.fit_transform(public_key_values)\n",
"\n",
"# Split the data into training and test sets\n",
"X_train, X_test = train_test_split(public_key_values_normalized, test_size=0.2, random_state=42)\n"
],
"metadata": {
"id": "YQrIRe6aQ-aQ"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from sklearn.cluster import KMeans\n",
"\n",
"# Perform K-Means clustering\n",
"kmeans = KMeans(n_clusters=3, random_state=42)\n",
"kmeans.fit(X_train)\n",
"\n",
"# Predict cluster labels for the test set\n",
"labels = kmeans.predict(X_test)\n",
"\n",
"# Visualize the clusters\n",
"plt.scatter(X_test, np.zeros_like(X_test), c=labels, cmap='viridis')\n",
"plt.title('K-Means Clustering of Public Keys')\n",
"plt.xlabel('Normalized Public Key Value')\n",
"plt.ylabel('Cluster')\n",
"plt.show()\n"
],
"metadata": {
"id": "Db8jlJhBRCfz"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from sklearn.neural_network import MLPClassifier\n",
"\n",
"# Create a simple neural network\n",
"mlp = MLPClassifier(hidden_layer_sizes=(100, 50), max_iter=300, random_state=42)\n",
"\n",
"# Fit the model\n",
"mlp.fit(X_train, labels)\n",
"\n",
"# Evaluate the model\n",
"accuracy = mlp.score(X_test, labels)\n",
"print(f\"Model accuracy: {accuracy * 100:.2f}%\")\n"
],
"metadata": {
"id": "7gvgFgHHRFOI"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment