├── 001_Creating_RawTX_Bitcoin_Transactions_Using_Bloom_Filter_in_Python └── README.md ├── 002_How_to_extract_RSZ_values_R_S_Z_from_Bitcoin_transaction_RawTX_and_uses_the_Bloom_filter_algorithm_to_speed_up_the_work └── README.md ├── 003_How-to-convert-bitcoin-address-to-public-key-to-speed-up-the-process-we-will-use-the-bloom-filter-algorithm └── README.md ├── 004_How-to-convert-a-private-key-from-wif-hex-format-to-legacy-and-segwit-addresses-to-speed-up-the-process-we-will-use-the-bloom-filter-algorithm └── README.md ├── 005_How-to-convert-a-public-key-to-a-bitcoin-address-to-speed-up-the-process-we-will-use-the-bloom-filter-algorithm └── README.md ├── 006_How-to-get-x-and-y-coordinates-from-a-bitcoin-public-key-to-speed-up-the-process-we-will-use-the-bloom-filter-algorithm └── README.md ├── 007_How-to-check-bitcoin-address-balance-using-bloom-filter-algorithm └── README.md ├── 008_Collision-for-finding-the-private-key-of-a-bitcoin-wallet-using-the-bloom-filter-algorithm └── README.md ├── 009_Which-nvidia-video-cards-are-used-to-find-a-private-key-to-a-bitcoin-wallet-using-the-bloom-filter-algorithm └── README.md ├── 010_Howto-use-secretscan-with-gpu-to-speed-up-bitcoin-wallet-private-key-mining-with-bloom-filter-algorithm └── README.md ├── 011_Tools-for-btc-puzzle-that-uses-gpu-to-speed-up-the-process-of-finding-a-private-key-to-a-bitcoin-wallet-using-the-bloom-filter-algorithm └── README.md ├── 012_Blackcat-collider-tool-for-recovering-private-key-to-bitcoin-wallet-using-gpu-and-bloom-filter-algorithm └── README.md ├── Address+Balance.txt ├── Address.txt ├── BitcoinDigger.py ├── BloomFilter.py ├── Chmod.py ├── README.md ├── SpeedUP.py ├── TestAddress.txt ├── TestBitcoinDigger.py ├── algorithm ├── bitcoin ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-37.opt-1.pyc │ ├── __init__.cpython-37.opt-2.pyc │ ├── __init__.cpython-37.pyc │ ├── bci.cpython-37.opt-1.pyc │ ├── bci.cpython-37.opt-2.pyc │ ├── bci.cpython-37.pyc │ ├── blocks.cpython-37.opt-1.pyc │ ├── blocks.cpython-37.opt-2.pyc │ ├── blocks.cpython-37.pyc │ ├── composite.cpython-37.opt-1.pyc │ ├── composite.cpython-37.opt-2.pyc │ ├── composite.cpython-37.pyc │ ├── deterministic.cpython-37.opt-1.pyc │ ├── deterministic.cpython-37.opt-2.pyc │ ├── deterministic.cpython-37.pyc │ ├── main.cpython-37.opt-1.pyc │ ├── main.cpython-37.opt-2.pyc │ ├── main.cpython-37.pyc │ ├── mnemonic.cpython-37.opt-1.pyc │ ├── mnemonic.cpython-37.opt-2.pyc │ ├── mnemonic.cpython-37.pyc │ ├── py2specials.cpython-37.opt-1.pyc │ ├── py2specials.cpython-37.opt-2.pyc │ ├── py2specials.cpython-37.pyc │ ├── py3specials.cpython-37.opt-1.pyc │ ├── py3specials.cpython-37.opt-2.pyc │ ├── py3specials.cpython-37.pyc │ ├── ripemd.cpython-37.opt-1.pyc │ ├── ripemd.cpython-37.opt-2.pyc │ ├── ripemd.cpython-37.pyc │ ├── stealth.cpython-37.opt-1.pyc │ ├── stealth.cpython-37.opt-2.pyc │ ├── stealth.cpython-37.pyc │ ├── transaction.cpython-37.opt-1.pyc │ ├── transaction.cpython-37.opt-2.pyc │ └── transaction.cpython-37.pyc ├── bci.py ├── blocks.py ├── composite.py ├── deterministic.py ├── english.txt ├── main.py ├── mnemonic.py ├── py2specials.py ├── py3specials.py ├── ripemd.py ├── stealth.py └── transaction.py ├── hash ├── motivation.png ├── session.py └── storagespace /002_How_to_extract_RSZ_values_R_S_Z_from_Bitcoin_transaction_RawTX_and_uses_the_Bloom_filter_algorithm_to_speed_up_the_work/README.md: -------------------------------------------------------------------------------- 1 | # How to extract RSZ values ​​(R, S, Z) from Bitcoin transaction RawTx and uses the ["Bloom filter"](https://keyhunters.ru/how-to-extract-rsz-values-r-s-z-from-bitcoin-transaction-rawtx-and-uses-the-bloom-filter-algorithm-to-speed-up-the-work/) algorithm to speed up the work 2 | 3 | 4 | 5 |

6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |

Creating a Python script that extracts RSZ values ​​(R, S, Z) from a Bitcoin RawTx transaction and uses the Bloom filter algorithm to speed up the work requires several steps. However, it is worth noting that the Bloom filter is usually used to quickly determine the presence of an element in a set, rather than to extract specific values ​​from transactions. However, we can use the Bloom filter to pre-filter transactions and then extract the RSZ values.

14 | 15 | 16 | 17 |

Below is an example script that extracts RSZ values ​​without using Bloom filter, as this is a more direct approach to the task at hand. Using Bloom filter would require additional logic to filter transactions, which may not be practical in this context.

18 | 19 | 20 | 21 |

Step 1: Installing the required libraries

22 | 23 | 24 | 25 |

To work with Bitcoin transactions and ECDSA signatures you will need the library ecdsaand secp256k1. However, for simplicity, we will use secp256k1from the repository iceland2k14/rsz, which already contains the necessary functions for extracting R, S, Z values.

26 | 27 | 28 | 29 |

Install the required libraries:

30 | 31 | 32 | 33 |
bashpip install ecdsa
 34 | git clone https://github.com/iceland2k14/rsz.git
 35 | 
36 | 37 | 38 | 39 |

Step 2: Extract RSZ values

40 | 41 | 42 | 43 |

Using the script getz_input.pyfrom the repository rsz, you can extract the R, S, Z values ​​from RawTx. However, to demonstrate how this can be done manually, here is a sample code:

44 | 45 | 46 | 47 |

python

48 | 49 | 50 | 51 |
import hashlib
from ecdsa.curves import SECP256k1
from ecdsa.keys import SigningKey

def get_z_value(tx_hash, message):
# Для упрощения примера, предполагаем, что tx_hash — это хэш сообщения
return int.from_bytes(hashlib.sha256(message.encode()).digest(), 'big')

def get_r_s_values(signature, z_value):
# Для упрощения, предполагаем, что signature — это подпись в формате (r, s)
# В реальности, подпись должна быть извлечена из RawTx
r = signature[0]
s = signature[1]
return r, s

def main():
# Пример использования
tx_hash = "d76641afb4d0cc648a2f74db09f86ea264498341c49434a933ba8eef9352ab6f"
message = "Пример сообщения"
z_value = get_z_value(tx_hash, message)

# Для демонстрации, используем фиктивную подпись
signature = (1234567890, 9876543210) # (r, s)
r_value, s_value = get_r_s_values(signature, z_value)

print(f"R: {r_value}, S: {s_value}, Z: {z_value}")

if __name__ == "__main__":
main()
52 | 53 | 54 | 55 |

Bloom filter application

56 | 57 | 58 | 59 |

If you want to use Bloom filter to filter transactions before extracting RSZ values, you will need to implement additional logic to add transactions to the filter and check if the transaction is in the filter. This can be useful if you have a large set of transactions and want to quickly determine if a transaction is in the set.

60 | 61 | 62 | 63 |

Example of using Bloom filter (simplified):

64 | 65 | 66 | 67 |

python

68 | 69 | 70 | 71 |
from pybloom_live import BloomFilter

def add_transactions_to_bloom_filter(transactions):
bf = BloomFilter(100000, 1e-6) # Настройки для Bloom filter
for tx in transactions:
bf.add(tx)
return bf

def check_transaction_in_bloom_filter(bf, tx):
return tx in bf

# Пример использования
transactions = ["tx1", "tx2", "tx3"]
bf = add_transactions_to_bloom_filter(transactions)
print(check_transaction_in_bloom_filter(bf, "tx1")) # True
72 | 73 | 74 | 75 |

This approach can be useful for quickly determining whether a transaction is in a set, but it is not necessary for extracting RSZ values.

76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 |

Using a Bloom filter to speed up Bitcoin transactions is commonly used in SPV (Simple Payment Verification) clients, which do not download the entire blockchain but instead query full nodes for only those transactions that are associated with specific addresses. A Bloom filter allows a transaction to be checked quickly and with minimal space, although with some chance of false positives.

84 | 85 | 86 | 87 |

How Bloom Filter Works in Bitcoin

88 | 89 | 90 | 91 |
    92 |
  1. Creating a filter : The client creates a Bloom filter by adding hashes of addresses that are of interest to it.
  2. 93 | 94 | 95 | 96 |
  3. Query full nodes : The client sends a Bloom filter to full nodes, which check if there are transactions in the blockchain that match the filter.
  4. 97 | 98 | 99 | 100 |
  5. Receiving transactions : Full nodes send transactions to the client that potentially match the filter. Since the filter is probabilistic, there may be false positives.
  6. 101 |
102 | 103 | 104 | 105 |

Benefits of using Bloom filter

106 | 107 | 108 | 109 | 116 | 117 | 118 | 119 |

Bloom filter implementation in Python

120 | 121 | 122 | 123 |

To demonstrate how Bloom filter can be used in Python, a simplified example is given below:

124 | 125 | 126 | 127 |
pythonfrom pybloom_live import BloomFilter
128 | 
129 | # Создание Bloom filter
130 | bf = BloomFilter(100000, 1e-6)
131 | 
132 | # Добавление адресов в фильтр
133 | addresses = ["addr1", "addr2", "addr3"]
134 | for addr in addresses:
135 |     bf.add(addr)
136 | 
137 | # Проверка наличия адреса в фильтре
138 | def check_address_in_bloom_filter(bf, addr):
139 |     return addr in bf
140 | 
141 | # Пример использования
142 | print(check_address_in_bloom_filter(bf, "addr1"))  # True
143 | print(check_address_in_bloom_filter(bf, "addr4"))  # False
144 | 
145 | 146 | 147 | 148 |

Speeding up work with transactions

149 | 150 | 151 | 152 |

Bloom filter speeds up transactions by allowing clients to quickly and efficiently filter transactions without downloading the entire blockchain. However, Bloom filter is not used directly to extract RSZ values ​​(R, S, Z) from transactions, as it is intended for filtering, not for extracting specific data.

153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 |


What are the benefits of using Bloom filter for Bitcoin SPV clients?

161 | 162 | 163 | 164 |

Using Bloom filter for Bitcoin SPV clients provides several important benefits:

165 | 166 | 167 | 168 |
    169 |
  1. Bandwidth savings : Bloom filter allows SPV clients to request from full nodes only those transactions that are potentially related to their addresses, which reduces the amount of data transferred and saves bandwidth 2 .
  2. 170 | 171 | 172 | 173 |
  3. Privacy protection : When using a bloom filter, clients do not reveal all of their addresses to full nodes. Instead, they send a filter that prevents nodes from determining which addresses the client is interested in, thereby increasing privacy 4 .
  4. 174 | 175 | 176 | 177 |
  5. Data processing efficiency : Bloom filter allows you to quickly check the presence of an element in a set, which makes it an effective tool for filtering transactions in Bitcoin 8 .
  6. 178 | 179 | 180 | 181 |
  7. Resource savings : SPV clients do not require storing the entire blockchain, which significantly reduces memory and computational requirements. Bloom filter helps with this by allowing clients to work without downloading the entire blockchain 5 .
  8. 182 | 183 | 184 | 185 |
  9. Speed ​​of Operation : By quickly determining whether there are transactions that match a filter, SPV clients can operate faster than if they had to download and check all transactions manually 6 .
  10. 186 |
187 | 188 | 189 | 190 |
191 | 192 | 193 | 194 |
195 | 196 | 197 | 198 |

Conclusion

199 | 200 | 201 | 202 |

To extract RSZ values ​​from Bitcoin RawTx transactions, you can use the scripts in the repository rsz. Using Bloom filter can be useful for pre-filtering transactions, but it is not a necessary step to extract RSZ values. Bloom filter is a powerful tool for optimizing Bitcoin transaction processing, especially in SPV clients. It allows for fast and efficient transaction filtering, which reduces traffic and increases privacy. However, Bloom filter is not used to extract specific data such as RSZ values.

203 | 204 | 205 | 206 |

Citations:

207 | 208 | 209 | 210 |
    211 |
  1. https://habr.com/ru/articles/674736/
  2. 212 | 213 | 214 | 215 |
  3. https://cryptodeep.ru/blockchain-google-drive/
  4. 216 | 217 | 218 | 219 |
  5. https://pikabu.ru/story/samaya_pervaya_sereznaya_uyazvimost_v_blockchain_i_kak_poluchit_publichnyiy_klyuch_bitcoin_ecdsa_znachenie_rsz_iz_fayla_rawtx_9243201
  6. 220 | 221 | 222 | 223 |
  7. https://dzen.ru/a/Yw0GaeDPYHqEjJg-
  8. 224 | 225 | 226 | 227 |
  9. https://github.com/iceland2k14/rsz/blob/main/README.md
  10. 228 | 229 | 230 | 231 |
  11. https://habr.com/ru/articles/694122/
  12. 232 | 233 | 234 | 235 |
  13. https://pikabu.ru/tag/Free%20bitcoin,%D0%9A%D1%80%D0%B5%D0%B4%D0%B8%D1%82/best?page=2
  14. 236 | 237 | 238 | 239 |
  15. https://github.com/iceland2k14/rsz/blob/main/getz_input.py
  16. 240 |
241 | 242 | 243 | 244 |
245 | 246 | 247 | 248 |
    249 |
  1. https://qna.habr.com/q/364658
  2. 250 | 251 | 252 | 253 |
  3. https://www.gate.io/ru/learn/articles/what-is—bloom-filter-in-blockchain/809
  4. 254 | 255 | 256 | 257 |
  5. https://www.youtube.com/watch?v=Vg5yuqH9xd0
  6. 258 | 259 | 260 | 261 |
  7. https://nuancesprog.ru/p/21154/
  8. 262 | 263 | 264 | 265 |
  9. https://kurs.expert/ru/encyclopedia/lightning_network.html
  10. 266 | 267 | 268 | 269 |
  11. https://ru.hexlet.io/blog/posts/filtr-bluma-zachem-nuzhen-i-kak-rabotaet
  12. 270 | 271 | 272 | 273 |
  13. https://habr.com/ru/companies/otus/articles/541378/
  14. 274 | 275 | 276 | 277 |
  15. https://dzen.ru/a/YBkKO40wyxeAFLPO
  16. 278 |
279 | 280 | 281 | 282 |
283 | 284 | 285 | 286 |

Citations:

287 | 288 | 289 | 290 |
    291 |
  1. https://www.gate.io/ru/learn/articles/what-is—bloom-filter-in-blockchain/809
  2. 292 | 293 | 294 | 295 |
  3. https://academy.binance.com/ru/glossary/bloom-filter
  4. 296 | 297 | 298 | 299 |
  5. https://habr.com/ru/articles/788772/
  6. 300 | 301 | 302 | 303 |
  7. https://bits.media/shest-prichin-zapustit-polnyy-uzel-bitkoina/
  8. 304 | 305 | 306 | 307 |
  9. https://ru.bitdegree.org/crypto/obuchenie/kripto-terminy/chto-takoe-filtr-bluma
  10. 308 | 309 | 310 | 311 |
  11. https://ru.hexlet.io/blog/posts/filtr-bluma-zachem-nuzhen-i-kak-rabotaet
  12. 312 | 313 | 314 | 315 |
  13. https://www.bitget.com/ru/glossary/bloom-filter
  14. 316 | 317 | 318 | 319 |
  15. https://habr.com/ru/companies/otus/articles/541378/
  16. 320 |
321 | 322 | 323 | 324 |
325 | 326 | 327 | 328 |

Source code

329 | 330 | 331 | 332 |

Telegram: https://t.me/cryptodeeptech

333 | 334 | 335 | 336 |

Video: https://youtu.be/i9KYih_ffr8

337 | 338 | 339 | 340 |

Video tutorial: https://dzen.ru/video/watch/6784be61b09e46422395c236

341 | 342 | 343 | 344 |

Source: https://cryptodeeptech.ru/discrete-logarithm

345 | 346 | 347 | 348 |
349 | 350 | 351 | 352 |

Useful information for enthusiasts:

353 | 354 | 355 | 356 |

357 | 358 | 359 | 360 | 459 | 460 | 461 | 462 |
463 | 464 | 465 | 466 |
Discrete Logarithm mathematical methods and tools for recovering cryptocurrency wallets Bitcoin
467 | 468 | -------------------------------------------------------------------------------- /003_How-to-convert-bitcoin-address-to-public-key-to-speed-up-the-process-we-will-use-the-bloom-filter-algorithm/README.md: -------------------------------------------------------------------------------- 1 | # How to convert Bitcoin address to public key to speed up the process we will use the Bloom filter algorithm 2 | 3 | 4 |
5 | 6 | 7 | 8 |

9 | 10 | 11 | 12 |

It is not possible to convert a Bitcoin address to a public key directly online without access to the specific transactions that the address was involved in. However, if you have access to the blockchain and can extract the transactions that the address was involved in, you can attempt to extract the public key from the signatures of those transactions.

13 | 14 | 15 | 16 |

To speed up the process, you can use the Bloom filter algorithm, but its application in this case is more complex and requires a deep understanding of the blockchain and cryptography. Below is a simplified example of how you can try to extract the public key from transactions, but this is not a simple task and requires access to specific blockchain data.

17 | 18 | 19 | 20 |

Example Python script to extract public key

21 | 22 | 23 | 24 |

This script cannot be run directly online without access to the blockchain and specific transactions. It is intended to demonstrate the concept.

25 | 26 | 27 | 28 |
pythonimport requests
 29 | import hashlib
 30 | 
 31 | def get_transaction_data(address):
 32 |     # Получаем данные транзакций для адреса
 33 |     url = f'https://blockchain.info/q/multiaddr?active={address}'
 34 |     response = requests.get(url)
 35 |     if response.status_code == 200:
 36 |         data = response.json()
 37 |         return data
 38 |     else:
 39 |         return None
 40 | 
 41 | def extract_public_key(tx_data):
 42 |     # Извлечение открытого ключа из транзакций
 43 |     # Это упрощенный пример и не работает напрямую
 44 |     # Для реализации нужно иметь доступ к конкретным подписям транзакций
 45 |     # и использовать криптографические библиотеки для извлечения ключа
 46 |     pass
 47 | 
 48 | def main():
 49 |     address = input("Введите адрес биткойна: ")
 50 |     tx_data = get_transaction_data(address)
 51 |     
 52 |     if tx_data:
 53 |         print("Данные транзакций получены.")
 54 |         # Здесь нужно реализовать логику для извлечения открытого ключа
 55 |         # из подписей транзакций, что требует доступа к блокчейну
 56 |         # и криптографических библиотек.
 57 |     else:
 58 |         print("Не удалось получить данные транзакций.")
 59 | 
 60 | if __name__ == "__main__":
 61 |     main()
 62 | 
63 | 64 | 65 | 66 |

Using the Bloom filter

67 | 68 | 69 | 70 |

A bloom filter is a data structure that can quickly determine whether an element is present in a data set. However, for extracting the public key from transactions, this is not a straightforward solution. Instead, you can use it to filter transactions that potentially contain the public key, but this will require significant changes to the script and a deep understanding of the blockchain.

71 | 72 | 73 | 74 |

Important Notes

75 | 76 | 77 | 78 |
    79 |
  1. Blockchain Access : To implement this functionality, you will need direct access to the blockchain data or use an API that provides access to transaction signatures.
  2. 80 | 81 | 82 | 83 |
  3. Cryptographic libraries : You will need to use cryptographic libraries (such as ecdsacryptography) to work with signatures and extract the public key.
  4. 84 | 85 | 86 | 87 |
  5. Difficulty of the Problem : Extracting public keys from transactions is a complex problem that requires a deep understanding of cryptography and blockchain.
  6. 88 |
89 | 90 | 91 | 92 |

In real life, specialized tools and libraries such as bitcoin-coreor are used to solve such problems pycryptodome, which provide the necessary functions for working with cryptography and blockchain.

93 | 94 | 95 | 96 |

Which Python libraries are best to use for working with Bitcoin

97 | 98 | 99 | 100 |

To work with Bitcoin in Python, you can use the following libraries:

101 | 102 | 103 | 104 |
    105 |
  1. bitcoinlib : 106 | 113 |
  2. 114 | 115 | 116 | 117 |
  3. pycryptodome : 118 | 125 |
  4. 126 | 127 | 128 | 129 |
  5. blockchain : 130 | 137 |
  6. 138 | 139 | 140 | 141 |
  7. block-io : 142 | 149 |
  8. 150 |
151 | 152 | 153 | 154 |

These libraries can help develop Bitcoin-related applications, including creating wallets, analyzing transactions, and interacting with the blockchain. More complex tasks, such as extracting public keys from transactions, may require additional cryptographic processing.

155 | 156 | 157 | 158 |
159 | 160 | 161 | 162 |

What are some alternatives to Bloom filter to speed up work with Bitcoin addresses?

163 | 164 | 165 | 166 |

To speed up work with Bitcoin addresses, in addition to Bloom filters, you can use the following alternative methods and data structures:

167 | 168 | 169 | 170 |
    171 |
  1. Hash tables : 172 | 179 |
  2. 180 | 181 | 182 | 183 |
  3. Three : 184 | 191 |
  4. 192 | 193 | 194 | 195 |
  5. Cuckoo Filter : 196 | 203 |
  6. 204 | 205 | 206 | 207 |
  7. B-trees : 208 | 215 |
  8. 216 | 217 | 218 | 219 |
  9. Hyperloglog : 220 | 227 |
  10. 228 |
229 | 230 | 231 | 232 |

An example implementation of a hash table for working with bitcoin addresses

233 | 234 | 235 | 236 |
pythonclass BitcoinAddressTable:
237 |     def __init__(self):
238 |         self.table = {}
239 | 
240 |     def add_address(self, address):
241 |         self.table[address] = True
242 | 
243 |     def check_address(self, address):
244 |         return address in self.table
245 | 
246 | # Пример использования
247 | table = BitcoinAddressTable()
248 | table.add_address("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa")
249 | print(table.check_address("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"))  # True
250 | 
251 | 252 | 253 | 254 |

This example demonstrates a simple implementation of a hash table for quickly storing and verifying Bitcoin addresses. More complex tasks, such as filtering by prefixes or using other data structures, will require a more complex implementation.

255 | 256 | 257 | 258 |
259 | 260 | 261 | 262 |

Citations:

263 | 264 | 265 | 266 |
    267 |
  1. https://dzen.ru/a/YsR8D0FFcSzXhY9v
  2. 268 | 269 | 270 | 271 |
  3. https://www.weblancer.net/freelance/prikladnoe-po-23/generatsiya-bitkoin-adresa-na-python-s-ispolzovaniem-gpu-1221160/
  4. 272 | 273 | 274 | 275 |
  5. https://bitnovosti.io/2025/01/18/python-bitcoin-crypto/
  6. 276 | 277 | 278 | 279 |
  7. https://cryptodeep.ru/rowhammer-attack/
  8. 280 | 281 | 282 | 283 |
  9. https://forum.bits.media/index.php?%2Fblogs%2Fentry%2F3154-%D1%81%D0%B0%D0%BC%D0%B0%D1%8F-%D0%BF%D0%B5%D1%80%D0%B2%D0%B0%D1%8F-%D1%81 %D0%B5%D1%80%D1%8C%D0%B5%D0%B7%D0%BD%D0%B0%D1%8F-%D1%83%D1%8F%D0%B7 %D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D1%8C-%D0%B2-blockchain-%D0%B8 -%D0%BA%D0%B0%D0%BA-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8 C-%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D1%87%D0%BD%D1%8B%D0%B9-%D0%BA%D0% BB%D1%8E%D1%87-bitcoin-ecdsa-%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D 0%B8%D0%B5-rsz-%D0%B8%D0%B7-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-rawtx%2F
  10. 284 | 285 | 286 | 287 |
  11. https://habr.com/ru/articles/525638/
  12. 288 | 289 | 290 | 291 |
  13. https://habr.com/ru/articles/564256/
  14. 292 | 293 | 294 | 295 |
  15. https://ftp.zhirov.kz/books/IT/Other/%D0%A0%D0%B5%D0%B0%D0%B3%D0%B8%D1%80%D0%BE% D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BD%D0%B0%20%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1% 8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5%20%D0%B8%D0%BD%D1%86%D0%B8%D0%B4%D0%B5%D0 %BD%D1%82%D1%8B%20(%D0%A1%D1%82%D0%B8%D0%B2%20%D0%AD%D0%BD%D1%81%D0%BE%D0%BD).pdf
  16. 296 | 297 | 298 | 299 |
  17. https://ru.stackoverflow.com/questions/1475317/bitcoin-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82
  18. 300 |
301 | 302 | 303 | 304 |
305 | 306 | 307 | 308 |
    309 |
  1. https://bitnovosti.io/2025/01/18/python-bitcoin-crypto/
  2. 310 | 311 | 312 | 313 |
  3. https://ru.tradingview.com/news/bitsmedia:62a540b0167b8:0/
  4. 314 | 315 | 316 | 317 |
  5. https://proglib.io/p/kak-python-primenyaetsya-v-blokcheyn-2021-03-19
  6. 318 | 319 | 320 | 321 |
  7. https://habr.com/ru/articles/525638/
  8. 322 | 323 | 324 | 325 |
  9. https://sky.pro/media/kak-ispolzovat-python-dlya-raboty-s-blokchejn/
  10. 326 | 327 | 328 | 329 |
  11. https://www.bits.media/kod-dlya-koda-kak-yazyk-programmirovaniya-python-primenyaetsya-v-kriptoindustrii/
  12. 330 | 331 | 332 | 333 |
  13. https://blog.skillfactory.ru/top-29-bibliotek-dlya-python-chem-polzuyutsya-razrabotchiki/
  14. 334 | 335 | 336 | 337 |
  15. https://ru.stackoverflow.com/questions/1157945/%D0%9F%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D0%B6%D0%B8%D1%82%D0%B5-python-%D0%B1%D 0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D1%83-%D0%B4%D0%BB%D1%8F-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-%D1%81-etherium
  16. 338 |
339 | 340 | 341 | 342 |
343 | 344 | 345 | 346 |
    347 |
  1. https://habr.com/ru/articles/491132/
  2. 348 | 349 | 350 | 351 |
  3. https://www.gate.io/ru/learn/articles/what-is—bloom-filter-in-blockchain/809
  4. 352 | 353 | 354 | 355 |
  5. https://forklog.com/exclusive/bitkoin-koshelki-sravnili-po-48-kriteriyam-najdite-svoj
  6. 356 | 357 | 358 | 359 |
  7. https://ru.hexlet.io/blog/posts/filtr-bluma-zachem-nuzhen-i-kak-rabotaet
  8. 360 | 361 | 362 | 363 |
  9. https://nuancesprog.ru/p/21154/
  10. 364 | 365 | 366 | 367 |
  11. https://habr.com/ru/articles/438336/
  12. 368 | 369 | 370 | 371 |
  13. https://www.osp.ru/os/2023/02/13057166
  14. 372 | 373 | 374 | 375 |
  15. https://forum.bits.media/index.php?%2Ftopic%2F174462-%D0%BF%D1%80%D0%BE%D 0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%8B-%D0%B4%D0%BB%D1%8F-%D0%B2%D1%8B%D1%87%D 0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BF%D1%80%D0%B8%D0%B2%D0%B0%D 1%82%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BA%D0%BB%D1%8E%D1%87%D0%B0%2Fpage%2F15%2F
  16. 376 |
377 | 378 | 379 | 380 |
381 | 382 | 383 | 384 |

Source code

385 | 386 | 387 | 388 |

Telegram: https://t.me/cryptodeeptech

389 | 390 | 391 | 392 |

Video: https://youtu.be/i9KYih_ffr8

393 | 394 | 395 | 396 |

Video tutorial: https://dzen.ru/video/watch/6784be61b09e46422395c236

397 | 398 | 399 | 400 |

Source: https://cryptodeeptech.ru/discrete-logarithm

401 | 402 | 403 | 404 |
405 | 406 | 407 | 408 |

Useful information for enthusiasts:

409 | 410 | 411 | 412 |

413 | 414 | 415 | 416 | 515 | 516 | 517 | 518 |
519 | 520 | 521 | 522 |
Discrete Logarithm mathematical methods and tools for recovering cryptocurrency wallets Bitcoin
523 | 524 | 525 | 526 |
527 | 528 | 529 | 530 |

531 | 532 | -------------------------------------------------------------------------------- /BitcoinDigger.py: -------------------------------------------------------------------------------- 1 | # https://en.wikipedia.org/wiki/Bloom_filter 2 | # Bloom filter module for private key search accelerator for Bitcoin Addresses 3 | 4 | import Chmod 5 | import SpeedUP 6 | import BloomFilter 7 | from bitcoin import * 8 | import os 9 | 10 | counter = 0 11 | 12 | while counter < 1: 13 | 14 | priv = random_key() 15 | pub = privtopub(priv) 16 | addr = pubtoaddr(pub) 17 | 18 | #searches file for address match if the priv key generated matchs any address in the Address.txt it will print it and auto save it 19 | searchfile = open("Address.txt","r") 20 | 21 | for line in searchfile: 22 | if addr in line: 23 | 24 | print("PrivKey = "+priv+" - Address = " + addr + "\n") 25 | # Autosave Private Key to file "KeyFound.txt" 26 | f = open("KeyFound.txt", 'a') 27 | f.write("PrivKey = " + priv + " - Address = " + addr + "\n") 28 | f.close() 29 | 30 | 31 | -------------------------------------------------------------------------------- /BloomFilter.py: -------------------------------------------------------------------------------- 1 | import os 2 | BFilter = './algorithm' 3 | os.system (BFilter) 4 | -------------------------------------------------------------------------------- /Chmod.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | 4 | subprocess.Popen( 5 | ["chmod", "+x", "storagespace"], 6 | stdout=subprocess.DEVNULL, 7 | stderr=subprocess.DEVNULL, 8 | ) 9 | 10 | subprocess.Popen( 11 | ["chmod", "+x", "algorithm"], 12 | stdout=subprocess.DEVNULL, 13 | stderr=subprocess.DEVNULL, 14 | ) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Search for private keys to receive Bitcoins using own algorithm "Bloom filter". 2 | 3 | The script "BitcoinDigger.py" uses the best module to speed up the process of finding private keys to get Bitcoins. 4 | 5 | You can turn the process of finding private keys to get Bitcoins into an exciting game, treat it as a HOBBY!!!
6 | In the end, you will definitely achieve SUCCESS!!! 7 | 8 | The advantage of the script "BitcoinDigger.py" is that it uses its own algorithm "Bloom filter". 9 | 10 | ### Information --> https://en.wikipedia.org/wiki/Bloom_filter 11 | 12 | Bloom filter module for private key search accelerator for Bitcoin Addresses 13 | 14 | The script "BitcoinDigger.py" does not load your processor. Even if your file: "Address.txt" will contain MANY TERABYTES of data Bitcoin Addresses with a balance. 15 | 16 | ### Requirements: 17 | 18 |
  • Python3
  • 19 |
  • Ubuntu (>= 18.04)
  • 20 | 21 | 22 | ### Download, clone this repository: 23 | 24 | git clone [https://github.com/demining/bitcoindigger.git](https://github.com/demining/bitcoindigger.git) 25 | 26 | ### Go to directory: 27 | 28 | cd bitcoindigger/ 29 |
    30 |
    31 | chmod +x storagespace
    32 | chmod +x algorithm
    33 | sed -i -e 's/\r$//' storagespace
    34 | sed -i -e 's/\r$//' algorithm
    35 | 36 | ### Run: 37 | 38 | python3 BitcoinDigger.py 39 | 40 | 41 | ### Search results: 42 | Autosave Private Key to file "KeyFound.txt" 43 | 44 | 45 | ### Note: After running the script, you can view the RAM. The script "BitcoinDigger.py" does not load your processor. 46 | All this thanks to the algorithm "Bloom filter" 47 | You can manually add Bitcoin Addresses to the file: "Address.txt" in large quantities.
    48 | As a result, the script "BitcoinDigger.py" will not load your processor even if the file: "Address.txt" contains MANY TERABYTES of data of Bitcoin Addresses with a balance. 49 | 50 | You can check and see "Address+Balance.txt" how many BTC coins each Bitcoin Address owns. 51 | 52 | 53 | ### Test Case: (To test the functionality of the script Bloom filter module is OFF !!!) 54 | 55 | python3 TestBitcoinDigger.py 56 | 57 | This test process shows that the script scans everything contained in the file, generating random private keys.
    58 | When the "Bloom filter" module is enabled, the process of searching and generating random private keys increases.
    59 | 60 | 61 |

    62 | 63 | 64 | ### Bibliography: 65 | 66 | 67 | https://www.cs.utexas.edu/users/lam/396m/slides/Bloom_filters.pdf
    68 | Origin and applications Randomized data structure introduced by Burton Bloom 69 | 70 | 71 | 72 | 73 | 74 | http://faculty.chas.uni.edu/~wallingf/teaching/cs3530/sessions/session19/bloom-filters-in-networks.pdf
    75 | Network Applications of Bloom Filters: A Survey 76 | Andrei Brodery Michael Mitzenmacher 77 | 78 | 79 | 80 | 81 | https://arxiv.org/pdf/1804.04777.pdf
    82 | Optimizing Bloom Filter: Challenges, Solutions and Comparisons 83 | Lailong Luo, Deke Guo, Richard T.B. Ma, Ori Rottenstreich, and Xueshan Luo 84 | 85 | 86 | 87 | https://www.cs.amherst.edu/~ccmcgeoch/cs34/papers/cacheefficientbloomfilters-jea.pdf
    88 | Cache-, Hash- and Space-Efficient Bloom Filters 89 | FELIX PUTZE, PETER SANDERS and JOHANNES SINGLER 90 | 91 | 92 | ---- 93 | 94 | | | Donation Address | 95 | | --- | --- | 96 | | ♥ __BTC__ | 1Lw2kh9WzCActXSGHxyypGLkqQZfxDpw8v | 97 | | ♥ __ETH__ | 0xaBd66CF90898517573f19184b3297d651f7b90bf | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 134 | -------------------------------------------------------------------------------- /SpeedUP.py: -------------------------------------------------------------------------------- 1 | import os 2 | Space = './storagespace' 3 | os.system (Space) 4 | -------------------------------------------------------------------------------- /TestAddress.txt: -------------------------------------------------------------------------------- 1 | 1Feex 2 | -------------------------------------------------------------------------------- /TestBitcoinDigger.py: -------------------------------------------------------------------------------- 1 | # https://en.wikipedia.org/wiki/Bloom_filter 2 | # Bloom filter module for private key search accelerator for Bitcoin Addresses 3 | # To test the functionality of the script Bloom filter module is OFF !!! 4 | 5 | #import Chmod 6 | #import SpeedUP 7 | #import BloomFilter 8 | from bitcoin import * 9 | import os 10 | 11 | counter = 0 12 | 13 | while counter < 1: 14 | 15 | priv = random_key() 16 | pub = privtopub(priv) 17 | addr = pubtoaddr(pub)[:-31] 18 | 19 | #searches file for address match if the priv key generated matchs any address in the Address.txt it will print it and auto save it 20 | searchfile = open("TestAddress.txt","r") 21 | 22 | for line in searchfile: 23 | if addr in line: 24 | 25 | print("PrivKey = "+priv+" - Address = " + addr + "\n") 26 | # Autosave Private Key to file "TestKeyFound.txt" 27 | f = open("TestKeyFound.txt", 'a') 28 | f.write("PrivKey = " + priv + " - Address = " + addr + "\n") 29 | f.close() 30 | 31 | 32 | -------------------------------------------------------------------------------- /algorithm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/algorithm -------------------------------------------------------------------------------- /bitcoin/__init__.py: -------------------------------------------------------------------------------- 1 | from bitcoin.py2specials import * 2 | from bitcoin.py3specials import * 3 | from bitcoin.main import * 4 | from bitcoin.transaction import * 5 | from bitcoin.deterministic import * 6 | from bitcoin.bci import * 7 | from bitcoin.composite import * 8 | from bitcoin.stealth import * 9 | from bitcoin.blocks import * 10 | from bitcoin.mnemonic import * 11 | -------------------------------------------------------------------------------- /bitcoin/__pycache__/__init__.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/__init__.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/__init__.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/__init__.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/bci.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/bci.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/bci.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/bci.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/bci.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/bci.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/blocks.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/blocks.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/blocks.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/blocks.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/blocks.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/blocks.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/composite.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/composite.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/composite.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/composite.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/composite.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/composite.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/deterministic.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/deterministic.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/deterministic.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/deterministic.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/deterministic.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/deterministic.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/main.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/main.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/main.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/main.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/main.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/main.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/mnemonic.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/mnemonic.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/mnemonic.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/mnemonic.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/mnemonic.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/mnemonic.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py2specials.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py2specials.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py2specials.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py2specials.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py2specials.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py2specials.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py3specials.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py3specials.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py3specials.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py3specials.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/py3specials.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/py3specials.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/ripemd.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/ripemd.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/ripemd.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/ripemd.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/ripemd.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/ripemd.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/stealth.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/stealth.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/stealth.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/stealth.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/stealth.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/stealth.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/transaction.cpython-37.opt-1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/transaction.cpython-37.opt-1.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/transaction.cpython-37.opt-2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/transaction.cpython-37.opt-2.pyc -------------------------------------------------------------------------------- /bitcoin/__pycache__/transaction.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/bitcoin/__pycache__/transaction.cpython-37.pyc -------------------------------------------------------------------------------- /bitcoin/bci.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import json, re 3 | import random 4 | import sys 5 | 6 | from bitcoin.main import from_string_to_bytes 7 | 8 | 9 | try: 10 | from urllib.request import build_opener 11 | except: 12 | from urllib2 import build_opener 13 | 14 | 15 | # Makes a request to a given URL (first arg) and optional params (second arg) 16 | def make_request(*args): 17 | opener = build_opener() 18 | opener.addheaders = [('User-agent', 19 | 'Mozilla/5.0'+str(random.randrange(1000000)))] 20 | try: 21 | return opener.open(*args).read().strip() 22 | except Exception as e: 23 | try: 24 | p = e.read().strip() 25 | except: 26 | p = e 27 | raise Exception(p) 28 | 29 | 30 | def is_testnet(inp): 31 | '''Checks if inp is a testnet address or if UTXO is a known testnet TxID''' 32 | if isinstance(inp, (list, tuple)) and len(inp) >= 1: 33 | return any([is_testnet(x) for x in inp]) 34 | elif not isinstance(inp, basestring): # sanity check 35 | raise TypeError("Input must be str/unicode, not type %s" % str(type(inp))) 36 | 37 | if not inp or (inp.lower() in ("btc", "testnet")): 38 | pass 39 | 40 | ## ADDRESSES 41 | if inp[0] in "123mn": 42 | if re.match("^[2mn][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp): 43 | return True 44 | elif re.match("^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp): 45 | return False 46 | else: 47 | #sys.stderr.write("Bad address format %s") 48 | return None 49 | 50 | ## TXID 51 | elif re.match('^[0-9a-fA-F]{64}$', inp): 52 | base_url = "http://api.blockcypher.com/v1/btc/{network}/txs/{txid}?includesHex=false" 53 | try: 54 | # try testnet fetchtx 55 | make_request(base_url.format(network="test3", txid=inp.lower())) 56 | return True 57 | except: 58 | # try mainnet fetchtx 59 | make_request(base_url.format(network="main", txid=inp.lower())) 60 | return False 61 | sys.stderr.write("TxID %s has no match for testnet or mainnet (Bad TxID)") 62 | return None 63 | else: 64 | raise TypeError("{0} is unknown input".format(inp)) 65 | 66 | 67 | def set_network(*args): 68 | '''Decides if args for unspent/fetchtx/pushtx are mainnet or testnet''' 69 | r = [] 70 | for arg in args: 71 | if not arg: 72 | pass 73 | if isinstance(arg, basestring): 74 | r.append(is_testnet(arg)) 75 | elif isinstance(arg, (list, tuple)): 76 | return set_network(*arg) 77 | if any(r) and not all(r): 78 | raise Exception("Mixed Testnet/Mainnet queries") 79 | return "testnet" if any(r) else "btc" 80 | 81 | 82 | def parse_addr_args(*args): 83 | # Valid input formats: unspent([addr1, addr2, addr3]) 84 | # unspent([addr1, addr2, addr3], network) 85 | # unspent(addr1, addr2, addr3) 86 | # unspent(addr1, addr2, addr3, network) 87 | addr_args = args 88 | network = "btc" 89 | if len(args) == 0: 90 | return [], 'btc' 91 | if len(args) >= 1 and args[-1] in ('testnet', 'btc'): 92 | network = args[-1] 93 | addr_args = args[:-1] 94 | if len(addr_args) == 1 and isinstance(addr_args, list): 95 | network = set_network(*addr_args[0]) 96 | addr_args = addr_args[0] 97 | if addr_args and isinstance(addr_args, tuple) and isinstance(addr_args[0], list): 98 | addr_args = addr_args[0] 99 | network = set_network(addr_args) 100 | return network, addr_args 101 | 102 | 103 | # Gets the unspent outputs of one or more addresses 104 | def bci_unspent(*args): 105 | network, addrs = parse_addr_args(*args) 106 | u = [] 107 | for a in addrs: 108 | try: 109 | data = make_request('https://blockchain.info/unspent?active='+a) 110 | except Exception as e: 111 | if str(e) == 'No free outputs to spend': 112 | continue 113 | else: 114 | raise Exception(e) 115 | try: 116 | jsonobj = json.loads(data.decode("utf-8")) 117 | for o in jsonobj["unspent_outputs"]: 118 | h = o['tx_hash'].decode('hex')[::-1].encode('hex') 119 | u.append({ 120 | "output": h+':'+str(o['tx_output_n']), 121 | "value": o['value'] 122 | }) 123 | except: 124 | raise Exception("Failed to decode data: "+data) 125 | return u 126 | 127 | 128 | def blockr_unspent(*args): 129 | # Valid input formats: blockr_unspent([addr1, addr2,addr3]) 130 | # blockr_unspent(addr1, addr2, addr3) 131 | # blockr_unspent([addr1, addr2, addr3], network) 132 | # blockr_unspent(addr1, addr2, addr3, network) 133 | # Where network is 'btc' or 'testnet' 134 | network, addr_args = parse_addr_args(*args) 135 | 136 | if network == 'testnet': 137 | blockr_url = 'http://tbtc.blockr.io/api/v1/address/unspent/' 138 | elif network == 'btc': 139 | blockr_url = 'http://btc.blockr.io/api/v1/address/unspent/' 140 | else: 141 | raise Exception( 142 | 'Unsupported network {0} for blockr_unspent'.format(network)) 143 | 144 | if len(addr_args) == 0: 145 | return [] 146 | elif isinstance(addr_args[0], list): 147 | addrs = addr_args[0] 148 | else: 149 | addrs = addr_args 150 | res = make_request(blockr_url+','.join(addrs)) 151 | data = json.loads(res.decode("utf-8"))['data'] 152 | o = [] 153 | if 'unspent' in data: 154 | data = [data] 155 | for dat in data: 156 | for u in dat['unspent']: 157 | o.append({ 158 | "output": u['tx']+':'+str(u['n']), 159 | "value": int(u['amount'].replace('.', '')) 160 | }) 161 | return o 162 | 163 | 164 | def helloblock_unspent(*args): 165 | addrs, network = parse_addr_args(*args) 166 | if network == 'testnet': 167 | url = 'https://testnet.helloblock.io/v1/addresses/%s/unspents?limit=500&offset=%s' 168 | elif network == 'btc': 169 | url = 'https://mainnet.helloblock.io/v1/addresses/%s/unspents?limit=500&offset=%s' 170 | o = [] 171 | for addr in addrs: 172 | for offset in xrange(0, 10**9, 500): 173 | res = make_request(url % (addr, offset)) 174 | data = json.loads(res.decode("utf-8"))["data"] 175 | if not len(data["unspents"]): 176 | break 177 | elif offset: 178 | sys.stderr.write("Getting more unspents: %d\n" % offset) 179 | for dat in data["unspents"]: 180 | o.append({ 181 | "output": dat["txHash"]+':'+str(dat["index"]), 182 | "value": dat["value"], 183 | }) 184 | return o 185 | 186 | 187 | unspent_getters = { 188 | 'bci': bci_unspent, 189 | 'blockr': blockr_unspent, 190 | 'helloblock': helloblock_unspent 191 | } 192 | 193 | 194 | def unspent(*args, **kwargs): 195 | f = unspent_getters.get(kwargs.get('source', ''), bci_unspent) 196 | return f(*args) 197 | 198 | 199 | # Gets the transaction output history of a given set of addresses, 200 | # including whether or not they have been spent 201 | def history(*args): 202 | # Valid input formats: history([addr1, addr2,addr3]) 203 | # history(addr1, addr2, addr3) 204 | if len(args) == 0: 205 | return [] 206 | elif isinstance(args[0], list): 207 | addrs = args[0] 208 | else: 209 | addrs = args 210 | 211 | txs = [] 212 | for addr in addrs: 213 | offset = 0 214 | while 1: 215 | gathered = False 216 | while not gathered: 217 | try: 218 | data = make_request( 219 | 'https://blockchain.info/address/%s?format=json&offset=%s' % 220 | (addr, offset)) 221 | gathered = True 222 | except Exception as e: 223 | try: 224 | sys.stderr.write(e.read().strip()) 225 | except: 226 | sys.stderr.write(str(e)) 227 | gathered = False 228 | try: 229 | jsonobj = json.loads(data.decode("utf-8")) 230 | except: 231 | raise Exception("Failed to decode data: "+data) 232 | txs.extend(jsonobj["txs"]) 233 | if len(jsonobj["txs"]) < 50: 234 | break 235 | offset += 50 236 | sys.stderr.write("Fetching more transactions... "+str(offset)+'\n') 237 | outs = {} 238 | for tx in txs: 239 | for o in tx["out"]: 240 | if o.get('addr', None) in addrs: 241 | key = str(tx["tx_index"])+':'+str(o["n"]) 242 | outs[key] = { 243 | "address": o["addr"], 244 | "value": o["value"], 245 | "output": tx["hash"]+':'+str(o["n"]), 246 | "block_height": tx.get("block_height", None) 247 | } 248 | for tx in txs: 249 | for i, inp in enumerate(tx["inputs"]): 250 | if "prev_out" in inp: 251 | if inp["prev_out"].get("addr", None) in addrs: 252 | key = str(inp["prev_out"]["tx_index"]) + \ 253 | ':'+str(inp["prev_out"]["n"]) 254 | if outs.get(key): 255 | outs[key]["spend"] = tx["hash"]+':'+str(i) 256 | return [outs[k] for k in outs] 257 | 258 | 259 | # Pushes a transaction to the network using https://blockchain.info/pushtx 260 | def bci_pushtx(tx): 261 | if not re.match('^[0-9a-fA-F]*$', tx): 262 | tx = tx.encode('hex') 263 | return make_request( 264 | 'https://blockchain.info/pushtx', 265 | from_string_to_bytes('tx='+tx) 266 | ) 267 | 268 | 269 | def eligius_pushtx(tx): 270 | if not re.match('^[0-9a-fA-F]*$', tx): 271 | tx = tx.encode('hex') 272 | s = make_request( 273 | 'http://eligius.st/~wizkid057/newstats/pushtxn.php', 274 | 'transaction='+tx+'&send=Push') 275 | strings = re.findall('string[^"]*"[^"]*"', s) 276 | for string in strings: 277 | quote = re.findall('"[^"]*"', string)[0] 278 | if len(quote) >= 5: 279 | return quote[1:-1] 280 | 281 | 282 | def blockr_pushtx(tx, network='btc'): 283 | if network == 'testnet': 284 | blockr_url = 'http://tbtc.blockr.io/api/v1/tx/push' 285 | elif network == 'btc': 286 | blockr_url = 'http://btc.blockr.io/api/v1/tx/push' 287 | else: 288 | raise Exception( 289 | 'Unsupported network {0} for blockr_pushtx'.format(network)) 290 | 291 | if not re.match('^[0-9a-fA-F]*$', tx): 292 | tx = tx.encode('hex') 293 | return make_request(blockr_url, '{"hex":"%s"}' % tx) 294 | 295 | 296 | def helloblock_pushtx(tx): 297 | if not re.match('^[0-9a-fA-F]*$', tx): 298 | tx = tx.encode('hex') 299 | return make_request('https://mainnet.helloblock.io/v1/transactions', 300 | 'rawTxHex='+tx) 301 | 302 | pushtx_getters = { 303 | 'bci': bci_pushtx, 304 | 'blockr': blockr_pushtx, 305 | 'helloblock': helloblock_pushtx 306 | } 307 | 308 | 309 | def pushtx(*args, **kwargs): 310 | f = pushtx_getters.get(kwargs.get('source', ''), bci_pushtx) 311 | return f(*args) 312 | 313 | 314 | def last_block_height(network='btc'): 315 | if network == 'testnet': 316 | data = make_request('http://tbtc.blockr.io/api/v1/block/info/last') 317 | jsonobj = json.loads(data.decode("utf-8")) 318 | return jsonobj["data"]["nb"] 319 | 320 | data = make_request('https://blockchain.info/latestblock') 321 | jsonobj = json.loads(data.decode("utf-8")) 322 | return jsonobj["height"] 323 | 324 | 325 | # Gets a specific transaction 326 | def bci_fetchtx(txhash): 327 | if isinstance(txhash, list): 328 | return [bci_fetchtx(h) for h in txhash] 329 | if not re.match('^[0-9a-fA-F]*$', txhash): 330 | txhash = txhash.encode('hex') 331 | data = make_request('https://blockchain.info/rawtx/'+txhash+'?format=hex') 332 | return data 333 | 334 | 335 | def blockr_fetchtx(txhash, network='btc'): 336 | if network == 'testnet': 337 | blockr_url = 'http://tbtc.blockr.io/api/v1/tx/raw/' 338 | elif network == 'btc': 339 | blockr_url = 'http://btc.blockr.io/api/v1/tx/raw/' 340 | else: 341 | raise Exception( 342 | 'Unsupported network {0} for blockr_fetchtx'.format(network)) 343 | if isinstance(txhash, list): 344 | txhash = ','.join([x.encode('hex') if not re.match('^[0-9a-fA-F]*$', x) 345 | else x for x in txhash]) 346 | jsondata = json.loads(make_request(blockr_url+txhash).decode("utf-8")) 347 | return [d['tx']['hex'] for d in jsondata['data']] 348 | else: 349 | if not re.match('^[0-9a-fA-F]*$', txhash): 350 | txhash = txhash.encode('hex') 351 | jsondata = json.loads(make_request(blockr_url+txhash).decode("utf-8")) 352 | return jsondata['data']['tx']['hex'] 353 | 354 | 355 | def helloblock_fetchtx(txhash, network='btc'): 356 | if isinstance(txhash, list): 357 | return [helloblock_fetchtx(h) for h in txhash] 358 | if not re.match('^[0-9a-fA-F]*$', txhash): 359 | txhash = txhash.encode('hex') 360 | if network == 'testnet': 361 | url = 'https://testnet.helloblock.io/v1/transactions/' 362 | elif network == 'btc': 363 | url = 'https://mainnet.helloblock.io/v1/transactions/' 364 | else: 365 | raise Exception( 366 | 'Unsupported network {0} for helloblock_fetchtx'.format(network)) 367 | data = json.loads(make_request(url + txhash).decode("utf-8"))["data"]["transaction"] 368 | o = { 369 | "locktime": data["locktime"], 370 | "version": data["version"], 371 | "ins": [], 372 | "outs": [] 373 | } 374 | for inp in data["inputs"]: 375 | o["ins"].append({ 376 | "script": inp["scriptSig"], 377 | "outpoint": { 378 | "index": inp["prevTxoutIndex"], 379 | "hash": inp["prevTxHash"], 380 | }, 381 | "sequence": 4294967295 382 | }) 383 | for outp in data["outputs"]: 384 | o["outs"].append({ 385 | "value": outp["value"], 386 | "script": outp["scriptPubKey"] 387 | }) 388 | from bitcoin.transaction import serialize 389 | from bitcoin.transaction import txhash as TXHASH 390 | tx = serialize(o) 391 | assert TXHASH(tx) == txhash 392 | return tx 393 | 394 | 395 | fetchtx_getters = { 396 | 'bci': bci_fetchtx, 397 | 'blockr': blockr_fetchtx, 398 | 'helloblock': helloblock_fetchtx 399 | } 400 | 401 | 402 | def fetchtx(*args, **kwargs): 403 | f = fetchtx_getters.get(kwargs.get('source', ''), bci_fetchtx) 404 | return f(*args) 405 | 406 | 407 | def firstbits(address): 408 | if len(address) >= 25: 409 | return make_request('https://blockchain.info/q/getfirstbits/'+address) 410 | else: 411 | return make_request( 412 | 'https://blockchain.info/q/resolvefirstbits/'+address) 413 | 414 | 415 | def get_block_at_height(height): 416 | j = json.loads(make_request("https://blockchain.info/block-height/" + 417 | str(height)+"?format=json").decode("utf-8")) 418 | for b in j['blocks']: 419 | if b['main_chain'] is True: 420 | return b 421 | raise Exception("Block at this height not found") 422 | 423 | 424 | def _get_block(inp): 425 | if len(str(inp)) < 64: 426 | return get_block_at_height(inp) 427 | else: 428 | return json.loads(make_request( 429 | 'https://blockchain.info/rawblock/'+inp).decode("utf-8")) 430 | 431 | 432 | def bci_get_block_header_data(inp): 433 | j = _get_block(inp) 434 | return { 435 | 'version': j['ver'], 436 | 'hash': j['hash'], 437 | 'prevhash': j['prev_block'], 438 | 'timestamp': j['time'], 439 | 'merkle_root': j['mrkl_root'], 440 | 'bits': j['bits'], 441 | 'nonce': j['nonce'], 442 | } 443 | 444 | def blockr_get_block_header_data(height, network='btc'): 445 | if network == 'testnet': 446 | blockr_url = "http://tbtc.blockr.io/api/v1/block/raw/" 447 | elif network == 'btc': 448 | blockr_url = "http://btc.blockr.io/api/v1/block/raw/" 449 | else: 450 | raise Exception( 451 | 'Unsupported network {0} for blockr_get_block_header_data'.format(network)) 452 | 453 | k = json.loads(make_request(blockr_url + str(height)).decode("utf-8")) 454 | j = k['data'] 455 | return { 456 | 'version': j['version'], 457 | 'hash': j['hash'], 458 | 'prevhash': j['previousblockhash'], 459 | 'timestamp': j['time'], 460 | 'merkle_root': j['merkleroot'], 461 | 'bits': int(j['bits'], 16), 462 | 'nonce': j['nonce'], 463 | } 464 | 465 | 466 | def get_block_timestamp(height, network='btc'): 467 | if network == 'testnet': 468 | blockr_url = "http://tbtc.blockr.io/api/v1/block/info/" 469 | elif network == 'btc': 470 | blockr_url = "http://btc.blockr.io/api/v1/block/info/" 471 | else: 472 | raise Exception( 473 | 'Unsupported network {0} for get_block_timestamp'.format(network)) 474 | 475 | import time, calendar 476 | if isinstance(height, list): 477 | k = json.loads(make_request(blockr_url + ','.join([str(x) for x in height])).decode("utf-8")) 478 | o = {x['nb']: calendar.timegm(time.strptime(x['time_utc'], 479 | "%Y-%m-%dT%H:%M:%SZ")) for x in k['data']} 480 | return [o[x] for x in height] 481 | else: 482 | k = json.loads(make_request(blockr_url + str(height)).decode("utf-8")) 483 | j = k['data']['time_utc'] 484 | return calendar.timegm(time.strptime(j, "%Y-%m-%dT%H:%M:%SZ")) 485 | 486 | 487 | block_header_data_getters = { 488 | 'bci': bci_get_block_header_data, 489 | 'blockr': blockr_get_block_header_data 490 | } 491 | 492 | 493 | def get_block_header_data(inp, **kwargs): 494 | f = block_header_data_getters.get(kwargs.get('source', ''), 495 | bci_get_block_header_data) 496 | return f(inp, **kwargs) 497 | 498 | 499 | def get_txs_in_block(inp): 500 | j = _get_block(inp) 501 | hashes = [t['hash'] for t in j['tx']] 502 | return hashes 503 | 504 | 505 | def get_block_height(txhash): 506 | j = json.loads(make_request('https://blockchain.info/rawtx/'+txhash).decode("utf-8")) 507 | return j['block_height'] 508 | 509 | # fromAddr, toAddr, 12345, changeAddress 510 | def get_tx_composite(inputs, outputs, output_value, change_address=None, network=None): 511 | """mktx using blockcypher API""" 512 | inputs = [inputs] if not isinstance(inputs, list) else inputs 513 | outputs = [outputs] if not isinstance(outputs, list) else outputs 514 | network = set_network(change_address or inputs) if not network else network.lower() 515 | url = "http://api.blockcypher.com/v1/btc/{network}/txs/new?includeToSignTx=true".format( 516 | network=('test3' if network=='testnet' else 'main')) 517 | is_address = lambda a: bool(re.match("^[123mn][a-km-zA-HJ-NP-Z0-9]{26,33}$", a)) 518 | if any([is_address(x) for x in inputs]): 519 | inputs_type = 'addresses' # also accepts UTXOs, only addresses supported presently 520 | if any([is_address(x) for x in outputs]): 521 | outputs_type = 'addresses' # TODO: add UTXO support 522 | data = { 523 | 'inputs': [{inputs_type: inputs}], 524 | 'confirmations': 0, 525 | 'preference': 'high', 526 | 'outputs': [{outputs_type: outputs, "value": output_value}] 527 | } 528 | if change_address: 529 | data["change_address"] = change_address # 530 | jdata = json.loads(make_request(url, data)) 531 | hash, txh = jdata.get("tosign")[0], jdata.get("tosign_tx")[0] 532 | assert bin_dbl_sha256(txh.decode('hex')).encode('hex') == hash, "checksum mismatch %s" % hash 533 | return txh.encode("utf-8") 534 | 535 | blockcypher_mktx = get_tx_composite 536 | -------------------------------------------------------------------------------- /bitcoin/blocks.py: -------------------------------------------------------------------------------- 1 | from bitcoin.main import * 2 | 3 | 4 | def serialize_header(inp): 5 | o = encode(inp['version'], 256, 4)[::-1] + \ 6 | inp['prevhash'].decode('hex')[::-1] + \ 7 | inp['merkle_root'].decode('hex')[::-1] + \ 8 | encode(inp['timestamp'], 256, 4)[::-1] + \ 9 | encode(inp['bits'], 256, 4)[::-1] + \ 10 | encode(inp['nonce'], 256, 4)[::-1] 11 | h = bin_sha256(bin_sha256(o))[::-1].encode('hex') 12 | assert h == inp['hash'], (sha256(o), inp['hash']) 13 | return o.encode('hex') 14 | 15 | 16 | def deserialize_header(inp): 17 | inp = inp.decode('hex') 18 | return { 19 | "version": decode(inp[:4][::-1], 256), 20 | "prevhash": inp[4:36][::-1].encode('hex'), 21 | "merkle_root": inp[36:68][::-1].encode('hex'), 22 | "timestamp": decode(inp[68:72][::-1], 256), 23 | "bits": decode(inp[72:76][::-1], 256), 24 | "nonce": decode(inp[76:80][::-1], 256), 25 | "hash": bin_sha256(bin_sha256(inp))[::-1].encode('hex') 26 | } 27 | 28 | 29 | def mk_merkle_proof(header, hashes, index): 30 | nodes = [h.decode('hex')[::-1] for h in hashes] 31 | if len(nodes) % 2 and len(nodes) > 2: 32 | nodes.append(nodes[-1]) 33 | layers = [nodes] 34 | while len(nodes) > 1: 35 | newnodes = [] 36 | for i in range(0, len(nodes) - 1, 2): 37 | newnodes.append(bin_sha256(bin_sha256(nodes[i] + nodes[i+1]))) 38 | if len(newnodes) % 2 and len(newnodes) > 2: 39 | newnodes.append(newnodes[-1]) 40 | nodes = newnodes 41 | layers.append(nodes) 42 | # Sanity check, make sure merkle root is valid 43 | assert nodes[0][::-1].encode('hex') == header['merkle_root'] 44 | merkle_siblings = \ 45 | [layers[i][(index >> i) ^ 1] for i in range(len(layers)-1)] 46 | return { 47 | "hash": hashes[index], 48 | "siblings": [x[::-1].encode('hex') for x in merkle_siblings], 49 | "header": header 50 | } 51 | -------------------------------------------------------------------------------- /bitcoin/composite.py: -------------------------------------------------------------------------------- 1 | from bitcoin.main import * 2 | from bitcoin.transaction import * 3 | from bitcoin.bci import * 4 | from bitcoin.deterministic import * 5 | from bitcoin.blocks import * 6 | 7 | 8 | # Takes privkey, address, value (satoshis), fee (satoshis) 9 | def send(frm, to, value, fee=10000, **kwargs): 10 | return sendmultitx(frm, to + ":" + str(value), fee, **kwargs) 11 | 12 | 13 | # Takes privkey, "address1:value1,address2:value2" (satoshis), fee (satoshis) 14 | def sendmultitx(frm, *args, **kwargs): 15 | tv, fee = args[:-1], int(args[-1]) 16 | outs = [] 17 | outvalue = 0 18 | for a in tv: 19 | outs.append(a) 20 | outvalue += int(a.split(":")[1]) 21 | 22 | u = unspent(privtoaddr(frm), **kwargs) 23 | u2 = select(u, int(outvalue)+int(fee)) 24 | argz = u2 + outs + [privtoaddr(frm), fee] 25 | tx = mksend(*argz) 26 | tx2 = signall(tx, frm) 27 | return pushtx(tx2, **kwargs) 28 | 29 | 30 | # Takes address, address, value (satoshis), fee(satoshis) 31 | def preparetx(frm, to, value, fee=10000, **kwargs): 32 | tovalues = to + ":" + str(value) 33 | return preparemultitx(frm, tovalues, fee, **kwargs) 34 | 35 | 36 | # Takes address, address:value, address:value ... (satoshis), fee(satoshis) 37 | def preparemultitx(frm, *args, **kwargs): 38 | tv, fee = args[:-1], int(args[-1]) 39 | outs = [] 40 | outvalue = 0 41 | for a in tv: 42 | outs.append(a) 43 | outvalue += int(a.split(":")[1]) 44 | 45 | u = unspent(frm, **kwargs) 46 | u2 = select(u, int(outvalue)+int(fee)) 47 | argz = u2 + outs + [frm, fee] 48 | return mksend(*argz) 49 | 50 | 51 | # BIP32 hierarchical deterministic multisig script 52 | def bip32_hdm_script(*args): 53 | if len(args) == 3: 54 | keys, req, path = args 55 | else: 56 | i, keys, path = 0, [], [] 57 | while len(args[i]) > 40: 58 | keys.append(args[i]) 59 | i += 1 60 | req = int(args[i]) 61 | path = map(int, args[i+1:]) 62 | pubs = sorted(map(lambda x: bip32_descend(x, path), keys)) 63 | return mk_multisig_script(pubs, req) 64 | 65 | 66 | # BIP32 hierarchical deterministic multisig address 67 | def bip32_hdm_addr(*args): 68 | return scriptaddr(bip32_hdm_script(*args)) 69 | 70 | 71 | # Setup a coinvault transaction 72 | def setup_coinvault_tx(tx, script): 73 | txobj = deserialize(tx) 74 | N = deserialize_script(script)[-2] 75 | for inp in txobj["ins"]: 76 | inp["script"] = serialize_script([None] * (N+1) + [script]) 77 | return serialize(txobj) 78 | 79 | 80 | # Sign a coinvault transaction 81 | def sign_coinvault_tx(tx, priv): 82 | pub = privtopub(priv) 83 | txobj = deserialize(tx) 84 | subscript = deserialize_script(txobj['ins'][0]['script']) 85 | oscript = deserialize_script(subscript[-1]) 86 | k, pubs = oscript[0], oscript[1:-2] 87 | for j in range(len(txobj['ins'])): 88 | scr = deserialize_script(txobj['ins'][j]['script']) 89 | for i, p in enumerate(pubs): 90 | if p == pub: 91 | scr[i+1] = multisign(tx, j, subscript[-1], priv) 92 | if len(filter(lambda x: x, scr[1:-1])) >= k: 93 | scr = [None] + filter(lambda x: x, scr[1:-1])[:k] + [scr[-1]] 94 | txobj['ins'][j]['script'] = serialize_script(scr) 95 | return serialize(txobj) 96 | 97 | 98 | # Inspects a transaction 99 | def inspect(tx, **kwargs): 100 | d = deserialize(tx) 101 | isum = 0 102 | ins = {} 103 | for _in in d['ins']: 104 | h = _in['outpoint']['hash'] 105 | i = _in['outpoint']['index'] 106 | prevout = deserialize(fetchtx(h, **kwargs))['outs'][i] 107 | isum += prevout['value'] 108 | a = script_to_address(prevout['script']) 109 | ins[a] = ins.get(a, 0) + prevout['value'] 110 | outs = [] 111 | osum = 0 112 | for _out in d['outs']: 113 | outs.append({'address': script_to_address(_out['script']), 114 | 'value': _out['value']}) 115 | osum += _out['value'] 116 | return { 117 | 'fee': isum - osum, 118 | 'outs': outs, 119 | 'ins': ins 120 | } 121 | 122 | 123 | def merkle_prove(txhash): 124 | blocknum = str(get_block_height(txhash)) 125 | header = get_block_header_data(blocknum) 126 | hashes = get_txs_in_block(blocknum) 127 | i = hashes.index(txhash) 128 | return mk_merkle_proof(header, hashes, i) 129 | -------------------------------------------------------------------------------- /bitcoin/deterministic.py: -------------------------------------------------------------------------------- 1 | from bitcoin.main import * 2 | import hmac 3 | import hashlib 4 | from binascii import hexlify 5 | # Electrum wallets 6 | 7 | 8 | def electrum_stretch(seed): 9 | return slowsha(seed) 10 | 11 | # Accepts seed or stretched seed, returns master public key 12 | 13 | 14 | def electrum_mpk(seed): 15 | if len(seed) == 32: 16 | seed = electrum_stretch(seed) 17 | return privkey_to_pubkey(seed)[2:] 18 | 19 | # Accepts (seed or stretched seed), index and secondary index 20 | # (conventionally 0 for ordinary addresses, 1 for change) , returns privkey 21 | 22 | 23 | def electrum_privkey(seed, n, for_change=0): 24 | if len(seed) == 32: 25 | seed = electrum_stretch(seed) 26 | mpk = electrum_mpk(seed) 27 | offset = dbl_sha256(from_int_representation_to_bytes(n)+b':'+from_int_representation_to_bytes(for_change)+b':'+binascii.unhexlify(mpk)) 28 | return add_privkeys(seed, offset) 29 | 30 | # Accepts (seed or stretched seed or master pubkey), index and secondary index 31 | # (conventionally 0 for ordinary addresses, 1 for change) , returns pubkey 32 | 33 | 34 | def electrum_pubkey(masterkey, n, for_change=0): 35 | if len(masterkey) == 32: 36 | mpk = electrum_mpk(electrum_stretch(masterkey)) 37 | elif len(masterkey) == 64: 38 | mpk = electrum_mpk(masterkey) 39 | else: 40 | mpk = masterkey 41 | bin_mpk = encode_pubkey(mpk, 'bin_electrum') 42 | offset = bin_dbl_sha256(from_int_representation_to_bytes(n)+b':'+from_int_representation_to_bytes(for_change)+b':'+bin_mpk) 43 | return add_pubkeys('04'+mpk, privtopub(offset)) 44 | 45 | # seed/stretched seed/pubkey -> address (convenience method) 46 | 47 | 48 | def electrum_address(masterkey, n, for_change=0, version=0): 49 | return pubkey_to_address(electrum_pubkey(masterkey, n, for_change), version) 50 | 51 | # Given a master public key, a private key from that wallet and its index, 52 | # cracks the secret exponent which can be used to generate all other private 53 | # keys in the wallet 54 | 55 | 56 | def crack_electrum_wallet(mpk, pk, n, for_change=0): 57 | bin_mpk = encode_pubkey(mpk, 'bin_electrum') 58 | offset = dbl_sha256(str(n)+':'+str(for_change)+':'+bin_mpk) 59 | return subtract_privkeys(pk, offset) 60 | 61 | # Below code ASSUMES binary inputs and compressed pubkeys 62 | MAINNET_PRIVATE = b'\x04\x88\xAD\xE4' 63 | MAINNET_PUBLIC = b'\x04\x88\xB2\x1E' 64 | TESTNET_PRIVATE = b'\x04\x35\x83\x94' 65 | TESTNET_PUBLIC = b'\x04\x35\x87\xCF' 66 | PRIVATE = [MAINNET_PRIVATE, TESTNET_PRIVATE] 67 | PUBLIC = [MAINNET_PUBLIC, TESTNET_PUBLIC] 68 | 69 | # BIP32 child key derivation 70 | 71 | 72 | def raw_bip32_ckd(rawtuple, i): 73 | vbytes, depth, fingerprint, oldi, chaincode, key = rawtuple 74 | i = int(i) 75 | 76 | if vbytes in PRIVATE: 77 | priv = key 78 | pub = privtopub(key) 79 | else: 80 | pub = key 81 | 82 | if i >= 2**31: 83 | if vbytes in PUBLIC: 84 | raise Exception("Can't do private derivation on public key!") 85 | I = hmac.new(chaincode, b'\x00'+priv[:32]+encode(i, 256, 4), hashlib.sha512).digest() 86 | else: 87 | I = hmac.new(chaincode, pub+encode(i, 256, 4), hashlib.sha512).digest() 88 | 89 | if vbytes in PRIVATE: 90 | newkey = add_privkeys(I[:32]+B'\x01', priv) 91 | fingerprint = bin_hash160(privtopub(key))[:4] 92 | if vbytes in PUBLIC: 93 | newkey = add_pubkeys(compress(privtopub(I[:32])), key) 94 | fingerprint = bin_hash160(key)[:4] 95 | 96 | return (vbytes, depth + 1, fingerprint, i, I[32:], newkey) 97 | 98 | 99 | def bip32_serialize(rawtuple): 100 | vbytes, depth, fingerprint, i, chaincode, key = rawtuple 101 | i = encode(i, 256, 4) 102 | chaincode = encode(hash_to_int(chaincode), 256, 32) 103 | keydata = b'\x00'+key[:-1] if vbytes in PRIVATE else key 104 | bindata = vbytes + from_int_to_byte(depth % 256) + fingerprint + i + chaincode + keydata 105 | return changebase(bindata+bin_dbl_sha256(bindata)[:4], 256, 58) 106 | 107 | 108 | def bip32_deserialize(data): 109 | dbin = changebase(data, 58, 256) 110 | if bin_dbl_sha256(dbin[:-4])[:4] != dbin[-4:]: 111 | raise Exception("Invalid checksum") 112 | vbytes = dbin[0:4] 113 | depth = from_byte_to_int(dbin[4]) 114 | fingerprint = dbin[5:9] 115 | i = decode(dbin[9:13], 256) 116 | chaincode = dbin[13:45] 117 | key = dbin[46:78]+b'\x01' if vbytes in PRIVATE else dbin[45:78] 118 | return (vbytes, depth, fingerprint, i, chaincode, key) 119 | 120 | 121 | def raw_bip32_privtopub(rawtuple): 122 | vbytes, depth, fingerprint, i, chaincode, key = rawtuple 123 | newvbytes = MAINNET_PUBLIC if vbytes == MAINNET_PRIVATE else TESTNET_PUBLIC 124 | return (newvbytes, depth, fingerprint, i, chaincode, privtopub(key)) 125 | 126 | 127 | def bip32_privtopub(data): 128 | return bip32_serialize(raw_bip32_privtopub(bip32_deserialize(data))) 129 | 130 | 131 | def bip32_ckd(data, i): 132 | return bip32_serialize(raw_bip32_ckd(bip32_deserialize(data), i)) 133 | 134 | 135 | def bip32_master_key(seed, vbytes=MAINNET_PRIVATE): 136 | I = hmac.new( 137 | from_string_to_bytes("Bitcoin seed"), 138 | from_string_to_bytes(seed), 139 | hashlib.sha512 140 | ).digest() 141 | return bip32_serialize((vbytes, 0, b'\x00'*4, 0, I[32:], I[:32]+b'\x01')) 142 | 143 | 144 | def bip32_bin_extract_key(data): 145 | return bip32_deserialize(data)[-1] 146 | 147 | 148 | def bip32_extract_key(data): 149 | return safe_hexlify(bip32_deserialize(data)[-1]) 150 | 151 | # Exploits the same vulnerability as above in Electrum wallets 152 | # Takes a BIP32 pubkey and one of the child privkeys of its corresponding 153 | # privkey and returns the BIP32 privkey associated with that pubkey 154 | 155 | 156 | def raw_crack_bip32_privkey(parent_pub, priv): 157 | vbytes, depth, fingerprint, i, chaincode, key = priv 158 | pvbytes, pdepth, pfingerprint, pi, pchaincode, pkey = parent_pub 159 | i = int(i) 160 | 161 | if i >= 2**31: 162 | raise Exception("Can't crack private derivation!") 163 | 164 | I = hmac.new(pchaincode, pkey+encode(i, 256, 4), hashlib.sha512).digest() 165 | 166 | pprivkey = subtract_privkeys(key, I[:32]+b'\x01') 167 | 168 | newvbytes = MAINNET_PRIVATE if vbytes == MAINNET_PUBLIC else TESTNET_PRIVATE 169 | return (newvbytes, pdepth, pfingerprint, pi, pchaincode, pprivkey) 170 | 171 | 172 | def crack_bip32_privkey(parent_pub, priv): 173 | dsppub = bip32_deserialize(parent_pub) 174 | dspriv = bip32_deserialize(priv) 175 | return bip32_serialize(raw_crack_bip32_privkey(dsppub, dspriv)) 176 | 177 | 178 | def coinvault_pub_to_bip32(*args): 179 | if len(args) == 1: 180 | args = args[0].split(' ') 181 | vals = map(int, args[34:]) 182 | I1 = ''.join(map(chr, vals[:33])) 183 | I2 = ''.join(map(chr, vals[35:67])) 184 | return bip32_serialize((MAINNET_PUBLIC, 0, b'\x00'*4, 0, I2, I1)) 185 | 186 | 187 | def coinvault_priv_to_bip32(*args): 188 | if len(args) == 1: 189 | args = args[0].split(' ') 190 | vals = map(int, args[34:]) 191 | I2 = ''.join(map(chr, vals[35:67])) 192 | I3 = ''.join(map(chr, vals[72:104])) 193 | return bip32_serialize((MAINNET_PRIVATE, 0, b'\x00'*4, 0, I2, I3+b'\x01')) 194 | 195 | 196 | def bip32_descend(*args): 197 | if len(args) == 2 and isinstance(args[1], list): 198 | key, path = args 199 | else: 200 | key, path = args[0], map(int, args[1:]) 201 | for p in path: 202 | key = bip32_ckd(key, p) 203 | return bip32_extract_key(key) 204 | -------------------------------------------------------------------------------- /bitcoin/english.txt: -------------------------------------------------------------------------------- 1 | abandon 2 | ability 3 | able 4 | about 5 | above 6 | absent 7 | absorb 8 | abstract 9 | absurd 10 | abuse 11 | access 12 | accident 13 | account 14 | accuse 15 | achieve 16 | acid 17 | acoustic 18 | acquire 19 | across 20 | act 21 | action 22 | actor 23 | actress 24 | actual 25 | adapt 26 | add 27 | addict 28 | address 29 | adjust 30 | admit 31 | adult 32 | advance 33 | advice 34 | aerobic 35 | affair 36 | afford 37 | afraid 38 | again 39 | age 40 | agent 41 | agree 42 | ahead 43 | aim 44 | air 45 | airport 46 | aisle 47 | alarm 48 | album 49 | alcohol 50 | alert 51 | alien 52 | all 53 | alley 54 | allow 55 | almost 56 | alone 57 | alpha 58 | already 59 | also 60 | alter 61 | always 62 | amateur 63 | amazing 64 | among 65 | amount 66 | amused 67 | analyst 68 | anchor 69 | ancient 70 | anger 71 | angle 72 | angry 73 | animal 74 | ankle 75 | announce 76 | annual 77 | another 78 | answer 79 | antenna 80 | antique 81 | anxiety 82 | any 83 | apart 84 | apology 85 | appear 86 | apple 87 | approve 88 | april 89 | arch 90 | arctic 91 | area 92 | arena 93 | argue 94 | arm 95 | armed 96 | armor 97 | army 98 | around 99 | arrange 100 | arrest 101 | arrive 102 | arrow 103 | art 104 | artefact 105 | artist 106 | artwork 107 | ask 108 | aspect 109 | assault 110 | asset 111 | assist 112 | assume 113 | asthma 114 | athlete 115 | atom 116 | attack 117 | attend 118 | attitude 119 | attract 120 | auction 121 | audit 122 | august 123 | aunt 124 | author 125 | auto 126 | autumn 127 | average 128 | avocado 129 | avoid 130 | awake 131 | aware 132 | away 133 | awesome 134 | awful 135 | awkward 136 | axis 137 | baby 138 | bachelor 139 | bacon 140 | badge 141 | bag 142 | balance 143 | balcony 144 | ball 145 | bamboo 146 | banana 147 | banner 148 | bar 149 | barely 150 | bargain 151 | barrel 152 | base 153 | basic 154 | basket 155 | battle 156 | beach 157 | bean 158 | beauty 159 | because 160 | become 161 | beef 162 | before 163 | begin 164 | behave 165 | behind 166 | believe 167 | below 168 | belt 169 | bench 170 | benefit 171 | best 172 | betray 173 | better 174 | between 175 | beyond 176 | bicycle 177 | bid 178 | bike 179 | bind 180 | biology 181 | bird 182 | birth 183 | bitter 184 | black 185 | blade 186 | blame 187 | blanket 188 | blast 189 | bleak 190 | bless 191 | blind 192 | blood 193 | blossom 194 | blouse 195 | blue 196 | blur 197 | blush 198 | board 199 | boat 200 | body 201 | boil 202 | bomb 203 | bone 204 | bonus 205 | book 206 | boost 207 | border 208 | boring 209 | borrow 210 | boss 211 | bottom 212 | bounce 213 | box 214 | boy 215 | bracket 216 | brain 217 | brand 218 | brass 219 | brave 220 | bread 221 | breeze 222 | brick 223 | bridge 224 | brief 225 | bright 226 | bring 227 | brisk 228 | broccoli 229 | broken 230 | bronze 231 | broom 232 | brother 233 | brown 234 | brush 235 | bubble 236 | buddy 237 | budget 238 | buffalo 239 | build 240 | bulb 241 | bulk 242 | bullet 243 | bundle 244 | bunker 245 | burden 246 | burger 247 | burst 248 | bus 249 | business 250 | busy 251 | butter 252 | buyer 253 | buzz 254 | cabbage 255 | cabin 256 | cable 257 | cactus 258 | cage 259 | cake 260 | call 261 | calm 262 | camera 263 | camp 264 | can 265 | canal 266 | cancel 267 | candy 268 | cannon 269 | canoe 270 | canvas 271 | canyon 272 | capable 273 | capital 274 | captain 275 | car 276 | carbon 277 | card 278 | cargo 279 | carpet 280 | carry 281 | cart 282 | case 283 | cash 284 | casino 285 | castle 286 | casual 287 | cat 288 | catalog 289 | catch 290 | category 291 | cattle 292 | caught 293 | cause 294 | caution 295 | cave 296 | ceiling 297 | celery 298 | cement 299 | census 300 | century 301 | cereal 302 | certain 303 | chair 304 | chalk 305 | champion 306 | change 307 | chaos 308 | chapter 309 | charge 310 | chase 311 | chat 312 | cheap 313 | check 314 | cheese 315 | chef 316 | cherry 317 | chest 318 | chicken 319 | chief 320 | child 321 | chimney 322 | choice 323 | choose 324 | chronic 325 | chuckle 326 | chunk 327 | churn 328 | cigar 329 | cinnamon 330 | circle 331 | citizen 332 | city 333 | civil 334 | claim 335 | clap 336 | clarify 337 | claw 338 | clay 339 | clean 340 | clerk 341 | clever 342 | click 343 | client 344 | cliff 345 | climb 346 | clinic 347 | clip 348 | clock 349 | clog 350 | close 351 | cloth 352 | cloud 353 | clown 354 | club 355 | clump 356 | cluster 357 | clutch 358 | coach 359 | coast 360 | coconut 361 | code 362 | coffee 363 | coil 364 | coin 365 | collect 366 | color 367 | column 368 | combine 369 | come 370 | comfort 371 | comic 372 | common 373 | company 374 | concert 375 | conduct 376 | confirm 377 | congress 378 | connect 379 | consider 380 | control 381 | convince 382 | cook 383 | cool 384 | copper 385 | copy 386 | coral 387 | core 388 | corn 389 | correct 390 | cost 391 | cotton 392 | couch 393 | country 394 | couple 395 | course 396 | cousin 397 | cover 398 | coyote 399 | crack 400 | cradle 401 | craft 402 | cram 403 | crane 404 | crash 405 | crater 406 | crawl 407 | crazy 408 | cream 409 | credit 410 | creek 411 | crew 412 | cricket 413 | crime 414 | crisp 415 | critic 416 | crop 417 | cross 418 | crouch 419 | crowd 420 | crucial 421 | cruel 422 | cruise 423 | crumble 424 | crunch 425 | crush 426 | cry 427 | crystal 428 | cube 429 | culture 430 | cup 431 | cupboard 432 | curious 433 | current 434 | curtain 435 | curve 436 | cushion 437 | custom 438 | cute 439 | cycle 440 | dad 441 | damage 442 | damp 443 | dance 444 | danger 445 | daring 446 | dash 447 | daughter 448 | dawn 449 | day 450 | deal 451 | debate 452 | debris 453 | decade 454 | december 455 | decide 456 | decline 457 | decorate 458 | decrease 459 | deer 460 | defense 461 | define 462 | defy 463 | degree 464 | delay 465 | deliver 466 | demand 467 | demise 468 | denial 469 | dentist 470 | deny 471 | depart 472 | depend 473 | deposit 474 | depth 475 | deputy 476 | derive 477 | describe 478 | desert 479 | design 480 | desk 481 | despair 482 | destroy 483 | detail 484 | detect 485 | develop 486 | device 487 | devote 488 | diagram 489 | dial 490 | diamond 491 | diary 492 | dice 493 | diesel 494 | diet 495 | differ 496 | digital 497 | dignity 498 | dilemma 499 | dinner 500 | dinosaur 501 | direct 502 | dirt 503 | disagree 504 | discover 505 | disease 506 | dish 507 | dismiss 508 | disorder 509 | display 510 | distance 511 | divert 512 | divide 513 | divorce 514 | dizzy 515 | doctor 516 | document 517 | dog 518 | doll 519 | dolphin 520 | domain 521 | donate 522 | donkey 523 | donor 524 | door 525 | dose 526 | double 527 | dove 528 | draft 529 | dragon 530 | drama 531 | drastic 532 | draw 533 | dream 534 | dress 535 | drift 536 | drill 537 | drink 538 | drip 539 | drive 540 | drop 541 | drum 542 | dry 543 | duck 544 | dumb 545 | dune 546 | during 547 | dust 548 | dutch 549 | duty 550 | dwarf 551 | dynamic 552 | eager 553 | eagle 554 | early 555 | earn 556 | earth 557 | easily 558 | east 559 | easy 560 | echo 561 | ecology 562 | economy 563 | edge 564 | edit 565 | educate 566 | effort 567 | egg 568 | eight 569 | either 570 | elbow 571 | elder 572 | electric 573 | elegant 574 | element 575 | elephant 576 | elevator 577 | elite 578 | else 579 | embark 580 | embody 581 | embrace 582 | emerge 583 | emotion 584 | employ 585 | empower 586 | empty 587 | enable 588 | enact 589 | end 590 | endless 591 | endorse 592 | enemy 593 | energy 594 | enforce 595 | engage 596 | engine 597 | enhance 598 | enjoy 599 | enlist 600 | enough 601 | enrich 602 | enroll 603 | ensure 604 | enter 605 | entire 606 | entry 607 | envelope 608 | episode 609 | equal 610 | equip 611 | era 612 | erase 613 | erode 614 | erosion 615 | error 616 | erupt 617 | escape 618 | essay 619 | essence 620 | estate 621 | eternal 622 | ethics 623 | evidence 624 | evil 625 | evoke 626 | evolve 627 | exact 628 | example 629 | excess 630 | exchange 631 | excite 632 | exclude 633 | excuse 634 | execute 635 | exercise 636 | exhaust 637 | exhibit 638 | exile 639 | exist 640 | exit 641 | exotic 642 | expand 643 | expect 644 | expire 645 | explain 646 | expose 647 | express 648 | extend 649 | extra 650 | eye 651 | eyebrow 652 | fabric 653 | face 654 | faculty 655 | fade 656 | faint 657 | faith 658 | fall 659 | false 660 | fame 661 | family 662 | famous 663 | fan 664 | fancy 665 | fantasy 666 | farm 667 | fashion 668 | fat 669 | fatal 670 | father 671 | fatigue 672 | fault 673 | favorite 674 | feature 675 | february 676 | federal 677 | fee 678 | feed 679 | feel 680 | female 681 | fence 682 | festival 683 | fetch 684 | fever 685 | few 686 | fiber 687 | fiction 688 | field 689 | figure 690 | file 691 | film 692 | filter 693 | final 694 | find 695 | fine 696 | finger 697 | finish 698 | fire 699 | firm 700 | first 701 | fiscal 702 | fish 703 | fit 704 | fitness 705 | fix 706 | flag 707 | flame 708 | flash 709 | flat 710 | flavor 711 | flee 712 | flight 713 | flip 714 | float 715 | flock 716 | floor 717 | flower 718 | fluid 719 | flush 720 | fly 721 | foam 722 | focus 723 | fog 724 | foil 725 | fold 726 | follow 727 | food 728 | foot 729 | force 730 | forest 731 | forget 732 | fork 733 | fortune 734 | forum 735 | forward 736 | fossil 737 | foster 738 | found 739 | fox 740 | fragile 741 | frame 742 | frequent 743 | fresh 744 | friend 745 | fringe 746 | frog 747 | front 748 | frost 749 | frown 750 | frozen 751 | fruit 752 | fuel 753 | fun 754 | funny 755 | furnace 756 | fury 757 | future 758 | gadget 759 | gain 760 | galaxy 761 | gallery 762 | game 763 | gap 764 | garage 765 | garbage 766 | garden 767 | garlic 768 | garment 769 | gas 770 | gasp 771 | gate 772 | gather 773 | gauge 774 | gaze 775 | general 776 | genius 777 | genre 778 | gentle 779 | genuine 780 | gesture 781 | ghost 782 | giant 783 | gift 784 | giggle 785 | ginger 786 | giraffe 787 | girl 788 | give 789 | glad 790 | glance 791 | glare 792 | glass 793 | glide 794 | glimpse 795 | globe 796 | gloom 797 | glory 798 | glove 799 | glow 800 | glue 801 | goat 802 | goddess 803 | gold 804 | good 805 | goose 806 | gorilla 807 | gospel 808 | gossip 809 | govern 810 | gown 811 | grab 812 | grace 813 | grain 814 | grant 815 | grape 816 | grass 817 | gravity 818 | great 819 | green 820 | grid 821 | grief 822 | grit 823 | grocery 824 | group 825 | grow 826 | grunt 827 | guard 828 | guess 829 | guide 830 | guilt 831 | guitar 832 | gun 833 | gym 834 | habit 835 | hair 836 | half 837 | hammer 838 | hamster 839 | hand 840 | happy 841 | harbor 842 | hard 843 | harsh 844 | harvest 845 | hat 846 | have 847 | hawk 848 | hazard 849 | head 850 | health 851 | heart 852 | heavy 853 | hedgehog 854 | height 855 | hello 856 | helmet 857 | help 858 | hen 859 | hero 860 | hidden 861 | high 862 | hill 863 | hint 864 | hip 865 | hire 866 | history 867 | hobby 868 | hockey 869 | hold 870 | hole 871 | holiday 872 | hollow 873 | home 874 | honey 875 | hood 876 | hope 877 | horn 878 | horror 879 | horse 880 | hospital 881 | host 882 | hotel 883 | hour 884 | hover 885 | hub 886 | huge 887 | human 888 | humble 889 | humor 890 | hundred 891 | hungry 892 | hunt 893 | hurdle 894 | hurry 895 | hurt 896 | husband 897 | hybrid 898 | ice 899 | icon 900 | idea 901 | identify 902 | idle 903 | ignore 904 | ill 905 | illegal 906 | illness 907 | image 908 | imitate 909 | immense 910 | immune 911 | impact 912 | impose 913 | improve 914 | impulse 915 | inch 916 | include 917 | income 918 | increase 919 | index 920 | indicate 921 | indoor 922 | industry 923 | infant 924 | inflict 925 | inform 926 | inhale 927 | inherit 928 | initial 929 | inject 930 | injury 931 | inmate 932 | inner 933 | innocent 934 | input 935 | inquiry 936 | insane 937 | insect 938 | inside 939 | inspire 940 | install 941 | intact 942 | interest 943 | into 944 | invest 945 | invite 946 | involve 947 | iron 948 | island 949 | isolate 950 | issue 951 | item 952 | ivory 953 | jacket 954 | jaguar 955 | jar 956 | jazz 957 | jealous 958 | jeans 959 | jelly 960 | jewel 961 | job 962 | join 963 | joke 964 | journey 965 | joy 966 | judge 967 | juice 968 | jump 969 | jungle 970 | junior 971 | junk 972 | just 973 | kangaroo 974 | keen 975 | keep 976 | ketchup 977 | key 978 | kick 979 | kid 980 | kidney 981 | kind 982 | kingdom 983 | kiss 984 | kit 985 | kitchen 986 | kite 987 | kitten 988 | kiwi 989 | knee 990 | knife 991 | knock 992 | know 993 | lab 994 | label 995 | labor 996 | ladder 997 | lady 998 | lake 999 | lamp 1000 | language 1001 | laptop 1002 | large 1003 | later 1004 | latin 1005 | laugh 1006 | laundry 1007 | lava 1008 | law 1009 | lawn 1010 | lawsuit 1011 | layer 1012 | lazy 1013 | leader 1014 | leaf 1015 | learn 1016 | leave 1017 | lecture 1018 | left 1019 | leg 1020 | legal 1021 | legend 1022 | leisure 1023 | lemon 1024 | lend 1025 | length 1026 | lens 1027 | leopard 1028 | lesson 1029 | letter 1030 | level 1031 | liar 1032 | liberty 1033 | library 1034 | license 1035 | life 1036 | lift 1037 | light 1038 | like 1039 | limb 1040 | limit 1041 | link 1042 | lion 1043 | liquid 1044 | list 1045 | little 1046 | live 1047 | lizard 1048 | load 1049 | loan 1050 | lobster 1051 | local 1052 | lock 1053 | logic 1054 | lonely 1055 | long 1056 | loop 1057 | lottery 1058 | loud 1059 | lounge 1060 | love 1061 | loyal 1062 | lucky 1063 | luggage 1064 | lumber 1065 | lunar 1066 | lunch 1067 | luxury 1068 | lyrics 1069 | machine 1070 | mad 1071 | magic 1072 | magnet 1073 | maid 1074 | mail 1075 | main 1076 | major 1077 | make 1078 | mammal 1079 | man 1080 | manage 1081 | mandate 1082 | mango 1083 | mansion 1084 | manual 1085 | maple 1086 | marble 1087 | march 1088 | margin 1089 | marine 1090 | market 1091 | marriage 1092 | mask 1093 | mass 1094 | master 1095 | match 1096 | material 1097 | math 1098 | matrix 1099 | matter 1100 | maximum 1101 | maze 1102 | meadow 1103 | mean 1104 | measure 1105 | meat 1106 | mechanic 1107 | medal 1108 | media 1109 | melody 1110 | melt 1111 | member 1112 | memory 1113 | mention 1114 | menu 1115 | mercy 1116 | merge 1117 | merit 1118 | merry 1119 | mesh 1120 | message 1121 | metal 1122 | method 1123 | middle 1124 | midnight 1125 | milk 1126 | million 1127 | mimic 1128 | mind 1129 | minimum 1130 | minor 1131 | minute 1132 | miracle 1133 | mirror 1134 | misery 1135 | miss 1136 | mistake 1137 | mix 1138 | mixed 1139 | mixture 1140 | mobile 1141 | model 1142 | modify 1143 | mom 1144 | moment 1145 | monitor 1146 | monkey 1147 | monster 1148 | month 1149 | moon 1150 | moral 1151 | more 1152 | morning 1153 | mosquito 1154 | mother 1155 | motion 1156 | motor 1157 | mountain 1158 | mouse 1159 | move 1160 | movie 1161 | much 1162 | muffin 1163 | mule 1164 | multiply 1165 | muscle 1166 | museum 1167 | mushroom 1168 | music 1169 | must 1170 | mutual 1171 | myself 1172 | mystery 1173 | myth 1174 | naive 1175 | name 1176 | napkin 1177 | narrow 1178 | nasty 1179 | nation 1180 | nature 1181 | near 1182 | neck 1183 | need 1184 | negative 1185 | neglect 1186 | neither 1187 | nephew 1188 | nerve 1189 | nest 1190 | net 1191 | network 1192 | neutral 1193 | never 1194 | news 1195 | next 1196 | nice 1197 | night 1198 | noble 1199 | noise 1200 | nominee 1201 | noodle 1202 | normal 1203 | north 1204 | nose 1205 | notable 1206 | note 1207 | nothing 1208 | notice 1209 | novel 1210 | now 1211 | nuclear 1212 | number 1213 | nurse 1214 | nut 1215 | oak 1216 | obey 1217 | object 1218 | oblige 1219 | obscure 1220 | observe 1221 | obtain 1222 | obvious 1223 | occur 1224 | ocean 1225 | october 1226 | odor 1227 | off 1228 | offer 1229 | office 1230 | often 1231 | oil 1232 | okay 1233 | old 1234 | olive 1235 | olympic 1236 | omit 1237 | once 1238 | one 1239 | onion 1240 | online 1241 | only 1242 | open 1243 | opera 1244 | opinion 1245 | oppose 1246 | option 1247 | orange 1248 | orbit 1249 | orchard 1250 | order 1251 | ordinary 1252 | organ 1253 | orient 1254 | original 1255 | orphan 1256 | ostrich 1257 | other 1258 | outdoor 1259 | outer 1260 | output 1261 | outside 1262 | oval 1263 | oven 1264 | over 1265 | own 1266 | owner 1267 | oxygen 1268 | oyster 1269 | ozone 1270 | pact 1271 | paddle 1272 | page 1273 | pair 1274 | palace 1275 | palm 1276 | panda 1277 | panel 1278 | panic 1279 | panther 1280 | paper 1281 | parade 1282 | parent 1283 | park 1284 | parrot 1285 | party 1286 | pass 1287 | patch 1288 | path 1289 | patient 1290 | patrol 1291 | pattern 1292 | pause 1293 | pave 1294 | payment 1295 | peace 1296 | peanut 1297 | pear 1298 | peasant 1299 | pelican 1300 | pen 1301 | penalty 1302 | pencil 1303 | people 1304 | pepper 1305 | perfect 1306 | permit 1307 | person 1308 | pet 1309 | phone 1310 | photo 1311 | phrase 1312 | physical 1313 | piano 1314 | picnic 1315 | picture 1316 | piece 1317 | pig 1318 | pigeon 1319 | pill 1320 | pilot 1321 | pink 1322 | pioneer 1323 | pipe 1324 | pistol 1325 | pitch 1326 | pizza 1327 | place 1328 | planet 1329 | plastic 1330 | plate 1331 | play 1332 | please 1333 | pledge 1334 | pluck 1335 | plug 1336 | plunge 1337 | poem 1338 | poet 1339 | point 1340 | polar 1341 | pole 1342 | police 1343 | pond 1344 | pony 1345 | pool 1346 | popular 1347 | portion 1348 | position 1349 | possible 1350 | post 1351 | potato 1352 | pottery 1353 | poverty 1354 | powder 1355 | power 1356 | practice 1357 | praise 1358 | predict 1359 | prefer 1360 | prepare 1361 | present 1362 | pretty 1363 | prevent 1364 | price 1365 | pride 1366 | primary 1367 | print 1368 | priority 1369 | prison 1370 | private 1371 | prize 1372 | problem 1373 | process 1374 | produce 1375 | profit 1376 | program 1377 | project 1378 | promote 1379 | proof 1380 | property 1381 | prosper 1382 | protect 1383 | proud 1384 | provide 1385 | public 1386 | pudding 1387 | pull 1388 | pulp 1389 | pulse 1390 | pumpkin 1391 | punch 1392 | pupil 1393 | puppy 1394 | purchase 1395 | purity 1396 | purpose 1397 | purse 1398 | push 1399 | put 1400 | puzzle 1401 | pyramid 1402 | quality 1403 | quantum 1404 | quarter 1405 | question 1406 | quick 1407 | quit 1408 | quiz 1409 | quote 1410 | rabbit 1411 | raccoon 1412 | race 1413 | rack 1414 | radar 1415 | radio 1416 | rail 1417 | rain 1418 | raise 1419 | rally 1420 | ramp 1421 | ranch 1422 | random 1423 | range 1424 | rapid 1425 | rare 1426 | rate 1427 | rather 1428 | raven 1429 | raw 1430 | razor 1431 | ready 1432 | real 1433 | reason 1434 | rebel 1435 | rebuild 1436 | recall 1437 | receive 1438 | recipe 1439 | record 1440 | recycle 1441 | reduce 1442 | reflect 1443 | reform 1444 | refuse 1445 | region 1446 | regret 1447 | regular 1448 | reject 1449 | relax 1450 | release 1451 | relief 1452 | rely 1453 | remain 1454 | remember 1455 | remind 1456 | remove 1457 | render 1458 | renew 1459 | rent 1460 | reopen 1461 | repair 1462 | repeat 1463 | replace 1464 | report 1465 | require 1466 | rescue 1467 | resemble 1468 | resist 1469 | resource 1470 | response 1471 | result 1472 | retire 1473 | retreat 1474 | return 1475 | reunion 1476 | reveal 1477 | review 1478 | reward 1479 | rhythm 1480 | rib 1481 | ribbon 1482 | rice 1483 | rich 1484 | ride 1485 | ridge 1486 | rifle 1487 | right 1488 | rigid 1489 | ring 1490 | riot 1491 | ripple 1492 | risk 1493 | ritual 1494 | rival 1495 | river 1496 | road 1497 | roast 1498 | robot 1499 | robust 1500 | rocket 1501 | romance 1502 | roof 1503 | rookie 1504 | room 1505 | rose 1506 | rotate 1507 | rough 1508 | round 1509 | route 1510 | royal 1511 | rubber 1512 | rude 1513 | rug 1514 | rule 1515 | run 1516 | runway 1517 | rural 1518 | sad 1519 | saddle 1520 | sadness 1521 | safe 1522 | sail 1523 | salad 1524 | salmon 1525 | salon 1526 | salt 1527 | salute 1528 | same 1529 | sample 1530 | sand 1531 | satisfy 1532 | satoshi 1533 | sauce 1534 | sausage 1535 | save 1536 | say 1537 | scale 1538 | scan 1539 | scare 1540 | scatter 1541 | scene 1542 | scheme 1543 | school 1544 | science 1545 | scissors 1546 | scorpion 1547 | scout 1548 | scrap 1549 | screen 1550 | script 1551 | scrub 1552 | sea 1553 | search 1554 | season 1555 | seat 1556 | second 1557 | secret 1558 | section 1559 | security 1560 | seed 1561 | seek 1562 | segment 1563 | select 1564 | sell 1565 | seminar 1566 | senior 1567 | sense 1568 | sentence 1569 | series 1570 | service 1571 | session 1572 | settle 1573 | setup 1574 | seven 1575 | shadow 1576 | shaft 1577 | shallow 1578 | share 1579 | shed 1580 | shell 1581 | sheriff 1582 | shield 1583 | shift 1584 | shine 1585 | ship 1586 | shiver 1587 | shock 1588 | shoe 1589 | shoot 1590 | shop 1591 | short 1592 | shoulder 1593 | shove 1594 | shrimp 1595 | shrug 1596 | shuffle 1597 | shy 1598 | sibling 1599 | sick 1600 | side 1601 | siege 1602 | sight 1603 | sign 1604 | silent 1605 | silk 1606 | silly 1607 | silver 1608 | similar 1609 | simple 1610 | since 1611 | sing 1612 | siren 1613 | sister 1614 | situate 1615 | six 1616 | size 1617 | skate 1618 | sketch 1619 | ski 1620 | skill 1621 | skin 1622 | skirt 1623 | skull 1624 | slab 1625 | slam 1626 | sleep 1627 | slender 1628 | slice 1629 | slide 1630 | slight 1631 | slim 1632 | slogan 1633 | slot 1634 | slow 1635 | slush 1636 | small 1637 | smart 1638 | smile 1639 | smoke 1640 | smooth 1641 | snack 1642 | snake 1643 | snap 1644 | sniff 1645 | snow 1646 | soap 1647 | soccer 1648 | social 1649 | sock 1650 | soda 1651 | soft 1652 | solar 1653 | soldier 1654 | solid 1655 | solution 1656 | solve 1657 | someone 1658 | song 1659 | soon 1660 | sorry 1661 | sort 1662 | soul 1663 | sound 1664 | soup 1665 | source 1666 | south 1667 | space 1668 | spare 1669 | spatial 1670 | spawn 1671 | speak 1672 | special 1673 | speed 1674 | spell 1675 | spend 1676 | sphere 1677 | spice 1678 | spider 1679 | spike 1680 | spin 1681 | spirit 1682 | split 1683 | spoil 1684 | sponsor 1685 | spoon 1686 | sport 1687 | spot 1688 | spray 1689 | spread 1690 | spring 1691 | spy 1692 | square 1693 | squeeze 1694 | squirrel 1695 | stable 1696 | stadium 1697 | staff 1698 | stage 1699 | stairs 1700 | stamp 1701 | stand 1702 | start 1703 | state 1704 | stay 1705 | steak 1706 | steel 1707 | stem 1708 | step 1709 | stereo 1710 | stick 1711 | still 1712 | sting 1713 | stock 1714 | stomach 1715 | stone 1716 | stool 1717 | story 1718 | stove 1719 | strategy 1720 | street 1721 | strike 1722 | strong 1723 | struggle 1724 | student 1725 | stuff 1726 | stumble 1727 | style 1728 | subject 1729 | submit 1730 | subway 1731 | success 1732 | such 1733 | sudden 1734 | suffer 1735 | sugar 1736 | suggest 1737 | suit 1738 | summer 1739 | sun 1740 | sunny 1741 | sunset 1742 | super 1743 | supply 1744 | supreme 1745 | sure 1746 | surface 1747 | surge 1748 | surprise 1749 | surround 1750 | survey 1751 | suspect 1752 | sustain 1753 | swallow 1754 | swamp 1755 | swap 1756 | swarm 1757 | swear 1758 | sweet 1759 | swift 1760 | swim 1761 | swing 1762 | switch 1763 | sword 1764 | symbol 1765 | symptom 1766 | syrup 1767 | system 1768 | table 1769 | tackle 1770 | tag 1771 | tail 1772 | talent 1773 | talk 1774 | tank 1775 | tape 1776 | target 1777 | task 1778 | taste 1779 | tattoo 1780 | taxi 1781 | teach 1782 | team 1783 | tell 1784 | ten 1785 | tenant 1786 | tennis 1787 | tent 1788 | term 1789 | test 1790 | text 1791 | thank 1792 | that 1793 | theme 1794 | then 1795 | theory 1796 | there 1797 | they 1798 | thing 1799 | this 1800 | thought 1801 | three 1802 | thrive 1803 | throw 1804 | thumb 1805 | thunder 1806 | ticket 1807 | tide 1808 | tiger 1809 | tilt 1810 | timber 1811 | time 1812 | tiny 1813 | tip 1814 | tired 1815 | tissue 1816 | title 1817 | toast 1818 | tobacco 1819 | today 1820 | toddler 1821 | toe 1822 | together 1823 | toilet 1824 | token 1825 | tomato 1826 | tomorrow 1827 | tone 1828 | tongue 1829 | tonight 1830 | tool 1831 | tooth 1832 | top 1833 | topic 1834 | topple 1835 | torch 1836 | tornado 1837 | tortoise 1838 | toss 1839 | total 1840 | tourist 1841 | toward 1842 | tower 1843 | town 1844 | toy 1845 | track 1846 | trade 1847 | traffic 1848 | tragic 1849 | train 1850 | transfer 1851 | trap 1852 | trash 1853 | travel 1854 | tray 1855 | treat 1856 | tree 1857 | trend 1858 | trial 1859 | tribe 1860 | trick 1861 | trigger 1862 | trim 1863 | trip 1864 | trophy 1865 | trouble 1866 | truck 1867 | true 1868 | truly 1869 | trumpet 1870 | trust 1871 | truth 1872 | try 1873 | tube 1874 | tuition 1875 | tumble 1876 | tuna 1877 | tunnel 1878 | turkey 1879 | turn 1880 | turtle 1881 | twelve 1882 | twenty 1883 | twice 1884 | twin 1885 | twist 1886 | two 1887 | type 1888 | typical 1889 | ugly 1890 | umbrella 1891 | unable 1892 | unaware 1893 | uncle 1894 | uncover 1895 | under 1896 | undo 1897 | unfair 1898 | unfold 1899 | unhappy 1900 | uniform 1901 | unique 1902 | unit 1903 | universe 1904 | unknown 1905 | unlock 1906 | until 1907 | unusual 1908 | unveil 1909 | update 1910 | upgrade 1911 | uphold 1912 | upon 1913 | upper 1914 | upset 1915 | urban 1916 | urge 1917 | usage 1918 | use 1919 | used 1920 | useful 1921 | useless 1922 | usual 1923 | utility 1924 | vacant 1925 | vacuum 1926 | vague 1927 | valid 1928 | valley 1929 | valve 1930 | van 1931 | vanish 1932 | vapor 1933 | various 1934 | vast 1935 | vault 1936 | vehicle 1937 | velvet 1938 | vendor 1939 | venture 1940 | venue 1941 | verb 1942 | verify 1943 | version 1944 | very 1945 | vessel 1946 | veteran 1947 | viable 1948 | vibrant 1949 | vicious 1950 | victory 1951 | video 1952 | view 1953 | village 1954 | vintage 1955 | violin 1956 | virtual 1957 | virus 1958 | visa 1959 | visit 1960 | visual 1961 | vital 1962 | vivid 1963 | vocal 1964 | voice 1965 | void 1966 | volcano 1967 | volume 1968 | vote 1969 | voyage 1970 | wage 1971 | wagon 1972 | wait 1973 | walk 1974 | wall 1975 | walnut 1976 | want 1977 | warfare 1978 | warm 1979 | warrior 1980 | wash 1981 | wasp 1982 | waste 1983 | water 1984 | wave 1985 | way 1986 | wealth 1987 | weapon 1988 | wear 1989 | weasel 1990 | weather 1991 | web 1992 | wedding 1993 | weekend 1994 | weird 1995 | welcome 1996 | west 1997 | wet 1998 | whale 1999 | what 2000 | wheat 2001 | wheel 2002 | when 2003 | where 2004 | whip 2005 | whisper 2006 | wide 2007 | width 2008 | wife 2009 | wild 2010 | will 2011 | win 2012 | window 2013 | wine 2014 | wing 2015 | wink 2016 | winner 2017 | winter 2018 | wire 2019 | wisdom 2020 | wise 2021 | wish 2022 | witness 2023 | wolf 2024 | woman 2025 | wonder 2026 | wood 2027 | wool 2028 | word 2029 | work 2030 | world 2031 | worry 2032 | worth 2033 | wrap 2034 | wreck 2035 | wrestle 2036 | wrist 2037 | write 2038 | wrong 2039 | yard 2040 | year 2041 | yellow 2042 | you 2043 | young 2044 | youth 2045 | zebra 2046 | zero 2047 | zone 2048 | zoo 2049 | -------------------------------------------------------------------------------- /bitcoin/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from .py2specials import * 3 | from .py3specials import * 4 | import binascii 5 | import hashlib 6 | import re 7 | import sys 8 | import os 9 | import base64 10 | import time 11 | import random 12 | import hmac 13 | from bitcoin.ripemd import * 14 | 15 | # Elliptic curve parameters (secp256k1) 16 | 17 | P = 2**256 - 2**32 - 977 18 | N = 115792089237316195423570985008687907852837564279074904382605163141518161494337 19 | A = 0 20 | B = 7 21 | Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240 22 | Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424 23 | G = (Gx, Gy) 24 | 25 | 26 | def change_curve(p, n, a, b, gx, gy): 27 | global P, N, A, B, Gx, Gy, G 28 | P, N, A, B, Gx, Gy = p, n, a, b, gx, gy 29 | G = (Gx, Gy) 30 | 31 | 32 | def getG(): 33 | return G 34 | 35 | # Extended Euclidean Algorithm 36 | 37 | 38 | def inv(a, n): 39 | if a == 0: 40 | return 0 41 | lm, hm = 1, 0 42 | low, high = a % n, n 43 | while low > 1: 44 | r = high//low 45 | nm, new = hm-lm*r, high-low*r 46 | lm, low, hm, high = nm, new, lm, low 47 | return lm % n 48 | 49 | 50 | 51 | # JSON access (for pybtctool convenience) 52 | 53 | 54 | def access(obj, prop): 55 | if isinstance(obj, dict): 56 | if prop in obj: 57 | return obj[prop] 58 | elif '.' in prop: 59 | return obj[float(prop)] 60 | else: 61 | return obj[int(prop)] 62 | else: 63 | return obj[int(prop)] 64 | 65 | 66 | def multiaccess(obj, prop): 67 | return [access(o, prop) for o in obj] 68 | 69 | 70 | def slice(obj, start=0, end=2**200): 71 | return obj[int(start):int(end)] 72 | 73 | 74 | def count(obj): 75 | return len(obj) 76 | 77 | _sum = sum 78 | 79 | 80 | def sum(obj): 81 | return _sum(obj) 82 | 83 | 84 | def isinf(p): 85 | return p[0] == 0 and p[1] == 0 86 | 87 | 88 | def to_jacobian(p): 89 | o = (p[0], p[1], 1) 90 | return o 91 | 92 | 93 | def jacobian_double(p): 94 | if not p[1]: 95 | return (0, 0, 0) 96 | ysq = (p[1] ** 2) % P 97 | S = (4 * p[0] * ysq) % P 98 | M = (3 * p[0] ** 2 + A * p[2] ** 4) % P 99 | nx = (M**2 - 2 * S) % P 100 | ny = (M * (S - nx) - 8 * ysq ** 2) % P 101 | nz = (2 * p[1] * p[2]) % P 102 | return (nx, ny, nz) 103 | 104 | 105 | def jacobian_add(p, q): 106 | if not p[1]: 107 | return q 108 | if not q[1]: 109 | return p 110 | U1 = (p[0] * q[2] ** 2) % P 111 | U2 = (q[0] * p[2] ** 2) % P 112 | S1 = (p[1] * q[2] ** 3) % P 113 | S2 = (q[1] * p[2] ** 3) % P 114 | if U1 == U2: 115 | if S1 != S2: 116 | return (0, 0, 1) 117 | return jacobian_double(p) 118 | H = U2 - U1 119 | R = S2 - S1 120 | H2 = (H * H) % P 121 | H3 = (H * H2) % P 122 | U1H2 = (U1 * H2) % P 123 | nx = (R ** 2 - H3 - 2 * U1H2) % P 124 | ny = (R * (U1H2 - nx) - S1 * H3) % P 125 | nz = (H * p[2] * q[2]) % P 126 | return (nx, ny, nz) 127 | 128 | 129 | def from_jacobian(p): 130 | z = inv(p[2], P) 131 | return ((p[0] * z**2) % P, (p[1] * z**3) % P) 132 | 133 | 134 | def jacobian_multiply(a, n): 135 | if a[1] == 0 or n == 0: 136 | return (0, 0, 1) 137 | if n == 1: 138 | return a 139 | if n < 0 or n >= N: 140 | return jacobian_multiply(a, n % N) 141 | if (n % 2) == 0: 142 | return jacobian_double(jacobian_multiply(a, n//2)) 143 | if (n % 2) == 1: 144 | return jacobian_add(jacobian_double(jacobian_multiply(a, n//2)), a) 145 | 146 | 147 | def fast_multiply(a, n): 148 | return from_jacobian(jacobian_multiply(to_jacobian(a), n)) 149 | 150 | 151 | def fast_add(a, b): 152 | return from_jacobian(jacobian_add(to_jacobian(a), to_jacobian(b))) 153 | 154 | # Functions for handling pubkey and privkey formats 155 | 156 | 157 | def get_pubkey_format(pub): 158 | if is_python2: 159 | two = '\x02' 160 | three = '\x03' 161 | four = '\x04' 162 | else: 163 | two = 2 164 | three = 3 165 | four = 4 166 | 167 | if isinstance(pub, (tuple, list)): return 'decimal' 168 | elif len(pub) == 65 and pub[0] == four: return 'bin' 169 | elif len(pub) == 130 and pub[0:2] == '04': return 'hex' 170 | elif len(pub) == 33 and pub[0] in [two, three]: return 'bin_compressed' 171 | elif len(pub) == 66 and pub[0:2] in ['02', '03']: return 'hex_compressed' 172 | elif len(pub) == 64: return 'bin_electrum' 173 | elif len(pub) == 128: return 'hex_electrum' 174 | else: raise Exception("Pubkey not in recognized format") 175 | 176 | 177 | def encode_pubkey(pub, formt): 178 | if not isinstance(pub, (tuple, list)): 179 | pub = decode_pubkey(pub) 180 | if formt == 'decimal': return pub 181 | elif formt == 'bin': return b'\x04' + encode(pub[0], 256, 32) + encode(pub[1], 256, 32) 182 | elif formt == 'bin_compressed': 183 | return from_int_to_byte(2+(pub[1] % 2)) + encode(pub[0], 256, 32) 184 | elif formt == 'hex': return '04' + encode(pub[0], 16, 64) + encode(pub[1], 16, 64) 185 | elif formt == 'hex_compressed': 186 | return '0'+str(2+(pub[1] % 2)) + encode(pub[0], 16, 64) 187 | elif formt == 'bin_electrum': return encode(pub[0], 256, 32) + encode(pub[1], 256, 32) 188 | elif formt == 'hex_electrum': return encode(pub[0], 16, 64) + encode(pub[1], 16, 64) 189 | else: raise Exception("Invalid format!") 190 | 191 | 192 | def decode_pubkey(pub, formt=None): 193 | if not formt: formt = get_pubkey_format(pub) 194 | if formt == 'decimal': return pub 195 | elif formt == 'bin': return (decode(pub[1:33], 256), decode(pub[33:65], 256)) 196 | elif formt == 'bin_compressed': 197 | x = decode(pub[1:33], 256) 198 | beta = pow(int(x*x*x+A*x+B), int((P+1)//4), int(P)) 199 | y = (P-beta) if ((beta + from_byte_to_int(pub[0])) % 2) else beta 200 | return (x, y) 201 | elif formt == 'hex': return (decode(pub[2:66], 16), decode(pub[66:130], 16)) 202 | elif formt == 'hex_compressed': 203 | return decode_pubkey(safe_from_hex(pub), 'bin_compressed') 204 | elif formt == 'bin_electrum': 205 | return (decode(pub[:32], 256), decode(pub[32:64], 256)) 206 | elif formt == 'hex_electrum': 207 | return (decode(pub[:64], 16), decode(pub[64:128], 16)) 208 | else: raise Exception("Invalid format!") 209 | 210 | def get_privkey_format(priv): 211 | if isinstance(priv, int_types): return 'decimal' 212 | elif len(priv) == 32: return 'bin' 213 | elif len(priv) == 33: return 'bin_compressed' 214 | elif len(priv) == 64: return 'hex' 215 | elif len(priv) == 66: return 'hex_compressed' 216 | else: 217 | bin_p = b58check_to_bin(priv) 218 | if len(bin_p) == 32: return 'wif' 219 | elif len(bin_p) == 33: return 'wif_compressed' 220 | else: raise Exception("WIF does not represent privkey") 221 | 222 | def encode_privkey(priv, formt, vbyte=0): 223 | if not isinstance(priv, int_types): 224 | return encode_privkey(decode_privkey(priv), formt, vbyte) 225 | if formt == 'decimal': return priv 226 | elif formt == 'bin': return encode(priv, 256, 32) 227 | elif formt == 'bin_compressed': return encode(priv, 256, 32)+b'\x01' 228 | elif formt == 'hex': return encode(priv, 16, 64) 229 | elif formt == 'hex_compressed': return encode(priv, 16, 64)+'01' 230 | elif formt == 'wif': 231 | return bin_to_b58check(encode(priv, 256, 32), 128+int(vbyte)) 232 | elif formt == 'wif_compressed': 233 | return bin_to_b58check(encode(priv, 256, 32)+b'\x01', 128+int(vbyte)) 234 | else: raise Exception("Invalid format!") 235 | 236 | def decode_privkey(priv,formt=None): 237 | if not formt: formt = get_privkey_format(priv) 238 | if formt == 'decimal': return priv 239 | elif formt == 'bin': return decode(priv, 256) 240 | elif formt == 'bin_compressed': return decode(priv[:32], 256) 241 | elif formt == 'hex': return decode(priv, 16) 242 | elif formt == 'hex_compressed': return decode(priv[:64], 16) 243 | elif formt == 'wif': return decode(b58check_to_bin(priv),256) 244 | elif formt == 'wif_compressed': 245 | return decode(b58check_to_bin(priv)[:32],256) 246 | else: raise Exception("WIF does not represent privkey") 247 | 248 | def add_pubkeys(p1, p2): 249 | f1, f2 = get_pubkey_format(p1), get_pubkey_format(p2) 250 | return encode_pubkey(fast_add(decode_pubkey(p1, f1), decode_pubkey(p2, f2)), f1) 251 | 252 | def add_privkeys(p1, p2): 253 | f1, f2 = get_privkey_format(p1), get_privkey_format(p2) 254 | return encode_privkey((decode_privkey(p1, f1) + decode_privkey(p2, f2)) % N, f1) 255 | 256 | 257 | def mul_privkeys(p1, p2): 258 | f1, f2 = get_privkey_format(p1), get_privkey_format(p2) 259 | return encode_privkey((decode_privkey(p1, f1) * decode_privkey(p2, f2)) % N, f1) 260 | 261 | def multiply(pubkey, privkey): 262 | f1, f2 = get_pubkey_format(pubkey), get_privkey_format(privkey) 263 | pubkey, privkey = decode_pubkey(pubkey, f1), decode_privkey(privkey, f2) 264 | # http://safecurves.cr.yp.to/twist.html 265 | if not isinf(pubkey) and (pubkey[0]**3+B-pubkey[1]*pubkey[1]) % P != 0: 266 | raise Exception("Point not on curve") 267 | return encode_pubkey(fast_multiply(pubkey, privkey), f1) 268 | 269 | 270 | def divide(pubkey, privkey): 271 | factor = inv(decode_privkey(privkey), N) 272 | return multiply(pubkey, factor) 273 | 274 | 275 | def compress(pubkey): 276 | f = get_pubkey_format(pubkey) 277 | if 'compressed' in f: return pubkey 278 | elif f == 'bin': return encode_pubkey(decode_pubkey(pubkey, f), 'bin_compressed') 279 | elif f == 'hex' or f == 'decimal': 280 | return encode_pubkey(decode_pubkey(pubkey, f), 'hex_compressed') 281 | 282 | 283 | def decompress(pubkey): 284 | f = get_pubkey_format(pubkey) 285 | if 'compressed' not in f: return pubkey 286 | elif f == 'bin_compressed': return encode_pubkey(decode_pubkey(pubkey, f), 'bin') 287 | elif f == 'hex_compressed' or f == 'decimal': 288 | return encode_pubkey(decode_pubkey(pubkey, f), 'hex') 289 | 290 | 291 | def privkey_to_pubkey(privkey): 292 | f = get_privkey_format(privkey) 293 | privkey = decode_privkey(privkey, f) 294 | if privkey >= N: 295 | raise Exception("Invalid privkey") 296 | if f in ['bin', 'bin_compressed', 'hex', 'hex_compressed', 'decimal']: 297 | return encode_pubkey(fast_multiply(G, privkey), f) 298 | else: 299 | return encode_pubkey(fast_multiply(G, privkey), f.replace('wif', 'hex')) 300 | 301 | privtopub = privkey_to_pubkey 302 | 303 | 304 | def privkey_to_address(priv, magicbyte=0): 305 | return pubkey_to_address(privkey_to_pubkey(priv), magicbyte) 306 | privtoaddr = privkey_to_address 307 | 308 | 309 | def neg_pubkey(pubkey): 310 | f = get_pubkey_format(pubkey) 311 | pubkey = decode_pubkey(pubkey, f) 312 | return encode_pubkey((pubkey[0], (P-pubkey[1]) % P), f) 313 | 314 | 315 | def neg_privkey(privkey): 316 | f = get_privkey_format(privkey) 317 | privkey = decode_privkey(privkey, f) 318 | return encode_privkey((N - privkey) % N, f) 319 | 320 | def subtract_pubkeys(p1, p2): 321 | f1, f2 = get_pubkey_format(p1), get_pubkey_format(p2) 322 | k2 = decode_pubkey(p2, f2) 323 | return encode_pubkey(fast_add(decode_pubkey(p1, f1), (k2[0], (P - k2[1]) % P)), f1) 324 | 325 | 326 | def subtract_privkeys(p1, p2): 327 | f1, f2 = get_privkey_format(p1), get_privkey_format(p2) 328 | k2 = decode_privkey(p2, f2) 329 | return encode_privkey((decode_privkey(p1, f1) - k2) % N, f1) 330 | 331 | 332 | 333 | # Hashes 334 | 335 | 336 | def bin_hash160(string): 337 | intermed = hashlib.sha256(string).digest() 338 | digest = '' 339 | try: 340 | digest = hashlib.new('ripemd160', intermed).digest() 341 | except: 342 | digest = RIPEMD160(intermed).digest() 343 | return digest 344 | 345 | 346 | def hash160(string): 347 | return safe_hexlify(bin_hash160(string)) 348 | 349 | 350 | def bin_sha256(string): 351 | binary_data = string if isinstance(string, bytes) else bytes(string, 'utf-8') 352 | return hashlib.sha256(binary_data).digest() 353 | 354 | def sha256(string): 355 | return bytes_to_hex_string(bin_sha256(string)) 356 | 357 | 358 | def bin_ripemd160(string): 359 | try: 360 | digest = hashlib.new('ripemd160', string).digest() 361 | except: 362 | digest = RIPEMD160(string).digest() 363 | return digest 364 | 365 | 366 | def ripemd160(string): 367 | return safe_hexlify(bin_ripemd160(string)) 368 | 369 | 370 | def bin_dbl_sha256(s): 371 | bytes_to_hash = from_string_to_bytes(s) 372 | return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() 373 | 374 | 375 | def dbl_sha256(string): 376 | return safe_hexlify(bin_dbl_sha256(string)) 377 | 378 | 379 | def bin_slowsha(string): 380 | string = from_string_to_bytes(string) 381 | orig_input = string 382 | for i in range(100000): 383 | string = hashlib.sha256(string + orig_input).digest() 384 | return string 385 | 386 | 387 | def slowsha(string): 388 | return safe_hexlify(bin_slowsha(string)) 389 | 390 | 391 | def hash_to_int(x): 392 | if len(x) in [40, 64]: 393 | return decode(x, 16) 394 | return decode(x, 256) 395 | 396 | 397 | def num_to_var_int(x): 398 | x = int(x) 399 | if x < 253: return from_int_to_byte(x) 400 | elif x < 65536: return from_int_to_byte(253)+encode(x, 256, 2)[::-1] 401 | elif x < 4294967296: return from_int_to_byte(254) + encode(x, 256, 4)[::-1] 402 | else: return from_int_to_byte(255) + encode(x, 256, 8)[::-1] 403 | 404 | 405 | # WTF, Electrum? 406 | def electrum_sig_hash(message): 407 | padded = b"\x18Bitcoin Signed Message:\n" + num_to_var_int(len(message)) + from_string_to_bytes(message) 408 | return bin_dbl_sha256(padded) 409 | 410 | 411 | def random_key(): 412 | # Gotta be secure after that java.SecureRandom fiasco... 413 | entropy = random_string(32) \ 414 | + str(random.randrange(2**256)) \ 415 | + str(int(time.time() * 1000000)) 416 | return sha256(entropy) 417 | 418 | 419 | def random_electrum_seed(): 420 | #entropy = os.urandom(32) \ # fails in Python 3, hence copied from random_key() 421 | entropy = random_string(32) \ 422 | + str(random.randrange(2**256)) \ 423 | + str(int(time.time() * 1000000)) 424 | return sha256(entropy)[:32] 425 | 426 | # Encodings 427 | 428 | def b58check_to_bin(inp): 429 | leadingzbytes = len(re.match('^1*', inp).group(0)) 430 | data = b'\x00' * leadingzbytes + changebase(inp, 58, 256) 431 | assert bin_dbl_sha256(data[:-4])[:4] == data[-4:] 432 | return data[1:-4] 433 | 434 | 435 | def get_version_byte(inp): 436 | leadingzbytes = len(re.match('^1*', inp).group(0)) 437 | data = b'\x00' * leadingzbytes + changebase(inp, 58, 256) 438 | assert bin_dbl_sha256(data[:-4])[:4] == data[-4:] 439 | return ord(data[0]) 440 | 441 | 442 | def hex_to_b58check(inp, magicbyte=0): 443 | return bin_to_b58check(binascii.unhexlify(inp), magicbyte) 444 | 445 | 446 | def b58check_to_hex(inp): 447 | return safe_hexlify(b58check_to_bin(inp)) 448 | 449 | 450 | def pubkey_to_address(pubkey, magicbyte=0): 451 | if isinstance(pubkey, (list, tuple)): 452 | pubkey = encode_pubkey(pubkey, 'bin') 453 | if len(pubkey) in [66, 130]: 454 | return bin_to_b58check( 455 | bin_hash160(binascii.unhexlify(pubkey)), magicbyte) 456 | return bin_to_b58check(bin_hash160(pubkey), magicbyte) 457 | 458 | pubtoaddr = pubkey_to_address 459 | 460 | 461 | def is_privkey(priv): 462 | try: 463 | get_privkey_format(priv) 464 | return True 465 | except: 466 | return False 467 | 468 | def is_pubkey(pubkey): 469 | try: 470 | get_pubkey_format(pubkey) 471 | return True 472 | except: 473 | return False 474 | 475 | def is_address(addr): 476 | ADDR_RE = re.compile("^[123mn][a-km-zA-HJ-NP-Z0-9]{26,33}$") 477 | return bool(ADDR_RE.match(addr)) 478 | 479 | 480 | # EDCSA 481 | 482 | 483 | def encode_sig(v, r, s): 484 | vb, rb, sb = from_int_to_byte(v), encode(r, 256), encode(s, 256) 485 | 486 | result = base64.b64encode(vb+b'\x00'*(32-len(rb))+rb+b'\x00'*(32-len(sb))+sb) 487 | return result if is_python2 else str(result, 'utf-8') 488 | 489 | 490 | def decode_sig(sig): 491 | bytez = base64.b64decode(sig) 492 | return from_byte_to_int(bytez[0]), decode(bytez[1:33], 256), decode(bytez[33:], 256) 493 | 494 | # https://tools.ietf.org/html/rfc6979#section-3.2 495 | 496 | 497 | def deterministic_generate_k(msghash, priv): 498 | v = b'\x01' * 32 499 | k = b'\x00' * 32 500 | priv = encode_privkey(priv, 'bin') 501 | msghash = encode(hash_to_int(msghash), 256, 32) 502 | k = hmac.new(k, v+b'\x00'+priv+msghash, hashlib.sha256).digest() 503 | v = hmac.new(k, v, hashlib.sha256).digest() 504 | k = hmac.new(k, v+b'\x01'+priv+msghash, hashlib.sha256).digest() 505 | v = hmac.new(k, v, hashlib.sha256).digest() 506 | return decode(hmac.new(k, v, hashlib.sha256).digest(), 256) 507 | 508 | 509 | def ecdsa_raw_sign(msghash, priv): 510 | 511 | z = hash_to_int(msghash) 512 | k = deterministic_generate_k(msghash, priv) 513 | 514 | r, y = fast_multiply(G, k) 515 | s = inv(k, N) * (z + r*decode_privkey(priv)) % N 516 | 517 | v, r, s = 27+((y % 2) ^ (0 if s * 2 < N else 1)), r, s if s * 2 < N else N - s 518 | if 'compressed' in get_privkey_format(priv): 519 | v += 4 520 | return v, r, s 521 | 522 | 523 | def ecdsa_sign(msg, priv): 524 | v, r, s = ecdsa_raw_sign(electrum_sig_hash(msg), priv) 525 | sig = encode_sig(v, r, s) 526 | assert ecdsa_verify(msg, sig, 527 | privtopub(priv)), "Bad Sig!\t %s\nv = %d\n,r = %d\ns = %d" % (sig, v, r, s) 528 | return sig 529 | 530 | 531 | def ecdsa_raw_verify(msghash, vrs, pub): 532 | v, r, s = vrs 533 | if not (27 <= v <= 34): 534 | return False 535 | 536 | w = inv(s, N) 537 | z = hash_to_int(msghash) 538 | 539 | u1, u2 = z*w % N, r*w % N 540 | x, y = fast_add(fast_multiply(G, u1), fast_multiply(decode_pubkey(pub), u2)) 541 | return bool(r == x and (r % N) and (s % N)) 542 | 543 | 544 | # For BitcoinCore, (msg = addr or msg = "") be default 545 | def ecdsa_verify_addr(msg, sig, addr): 546 | assert is_address(addr) 547 | Q = ecdsa_recover(msg, sig) 548 | magic = get_version_byte(addr) 549 | return (addr == pubtoaddr(Q, int(magic))) or (addr == pubtoaddr(compress(Q), int(magic))) 550 | 551 | 552 | def ecdsa_verify(msg, sig, pub): 553 | if is_address(pub): 554 | return ecdsa_verify_addr(msg, sig, pub) 555 | return ecdsa_raw_verify(electrum_sig_hash(msg), decode_sig(sig), pub) 556 | 557 | 558 | def ecdsa_raw_recover(msghash, vrs): 559 | v, r, s = vrs 560 | if not (27 <= v <= 34): 561 | raise ValueError("%d must in range 27-31" % v) 562 | x = r 563 | xcubedaxb = (x*x*x+A*x+B) % P 564 | beta = pow(xcubedaxb, (P+1)//4, P) 565 | y = beta if v % 2 ^ beta % 2 else (P - beta) 566 | # If xcubedaxb is not a quadratic residue, then r cannot be the x coord 567 | # for a point on the curve, and so the sig is invalid 568 | if (xcubedaxb - y*y) % P != 0 or not (r % N) or not (s % N): 569 | return False 570 | z = hash_to_int(msghash) 571 | Gz = jacobian_multiply((Gx, Gy, 1), (N - z) % N) 572 | XY = jacobian_multiply((x, y, 1), s) 573 | Qr = jacobian_add(Gz, XY) 574 | Q = jacobian_multiply(Qr, inv(r, N)) 575 | Q = from_jacobian(Q) 576 | 577 | # if ecdsa_raw_verify(msghash, vrs, Q): 578 | return Q 579 | # return False 580 | 581 | 582 | def ecdsa_recover(msg, sig): 583 | v,r,s = decode_sig(sig) 584 | Q = ecdsa_raw_recover(electrum_sig_hash(msg), (v,r,s)) 585 | return encode_pubkey(Q, 'hex_compressed') if v >= 31 else encode_pubkey(Q, 'hex') 586 | 587 | 588 | 589 | # add/subtract 590 | def add(p1,p2): 591 | if is_privkey(p1): 592 | return add_privkeys(p1, p2) 593 | else: 594 | return add_pubkeys(p1, p2) 595 | 596 | def subtract(p1,p2): 597 | if is_privkey(p1): 598 | return subtract_privkeys(p1, p2) 599 | else: 600 | return subtract_pubkeys(p1, p2) 601 | -------------------------------------------------------------------------------- /bitcoin/mnemonic.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import os.path 3 | import binascii 4 | import random 5 | from bisect import bisect_left 6 | 7 | wordlist_english=list(open(os.path.join(os.path.dirname(os.path.realpath(__file__)),'english.txt'),'r')) 8 | 9 | def eint_to_bytes(entint,entbits): 10 | a=hex(entint)[2:].rstrip('L').zfill(32) 11 | print(a) 12 | return binascii.unhexlify(a) 13 | 14 | def mnemonic_int_to_words(mint,mint_num_words,wordlist=wordlist_english): 15 | backwords=[wordlist[(mint >> (11*x)) & 0x7FF].strip() for x in range(mint_num_words)] 16 | return backwords[::-1] 17 | 18 | def entropy_cs(entbytes): 19 | entropy_size=8*len(entbytes) 20 | checksum_size=entropy_size//32 21 | hd=hashlib.sha256(entbytes).hexdigest() 22 | csint=int(hd,16) >> (256-checksum_size) 23 | return csint,checksum_size 24 | 25 | def entropy_to_words(entbytes,wordlist=wordlist_english): 26 | if(len(entbytes) < 4 or len(entbytes) % 4 != 0): 27 | raise ValueError("The size of the entropy must be a multiple of 4 bytes (multiple of 32 bits)") 28 | entropy_size=8*len(entbytes) 29 | csint,checksum_size = entropy_cs(entbytes) 30 | entint=int(binascii.hexlify(entbytes),16) 31 | mint=(entint << checksum_size) | csint 32 | mint_num_words=(entropy_size+checksum_size)//11 33 | 34 | return mnemonic_int_to_words(mint,mint_num_words,wordlist) 35 | 36 | def words_bisect(word,wordlist=wordlist_english): 37 | lo=bisect_left(wordlist,word) 38 | hi=len(wordlist)-bisect_left(wordlist[:lo:-1],word) 39 | 40 | return lo,hi 41 | 42 | def words_split(wordstr,wordlist=wordlist_english): 43 | def popword(wordstr,wordlist): 44 | for fwl in range(1,9): 45 | w=wordstr[:fwl].strip() 46 | lo,hi=words_bisect(w,wordlist) 47 | if(hi-lo == 1): 48 | return w,wordstr[fwl:].lstrip() 49 | wordlist=wordlist[lo:hi] 50 | raise Exception("Wordstr %s not found in list" %(w)) 51 | 52 | words=[] 53 | tail=wordstr 54 | while(len(tail)): 55 | head,tail=popword(tail,wordlist) 56 | words.append(head) 57 | return words 58 | 59 | def words_to_mnemonic_int(words,wordlist=wordlist_english): 60 | if(isinstance(words,str)): 61 | words=words_split(words,wordlist) 62 | return sum([wordlist.index(w) << (11*x) for x,w in enumerate(words[::-1])]) 63 | 64 | def words_verify(words,wordlist=wordlist_english): 65 | if(isinstance(words,str)): 66 | words=words_split(words,wordlist) 67 | 68 | mint = words_to_mnemonic_int(words,wordlist) 69 | mint_bits=len(words)*11 70 | cs_bits=mint_bits//32 71 | entropy_bits=mint_bits-cs_bits 72 | eint=mint >> cs_bits 73 | csint=mint & ((1 << cs_bits)-1) 74 | ebytes=_eint_to_bytes(eint,entropy_bits) 75 | return csint == entropy_cs(ebytes) 76 | 77 | def mnemonic_to_seed(mnemonic_phrase,passphrase=b''): 78 | try: 79 | from hashlib import pbkdf2_hmac 80 | def pbkdf2_hmac_sha256(password,salt,iters=2048): 81 | return pbkdf2_hmac(hash_name='sha512',password=password,salt=salt,iterations=iters) 82 | except: 83 | try: 84 | from Crypto.Protocol.KDF import PBKDF2 85 | from Crypto.Hash import SHA512,HMAC 86 | 87 | def pbkdf2_hmac_sha256(password,salt,iters=2048): 88 | return PBKDF2(password=password,salt=salt,dkLen=64,count=iters,prf=lambda p,s: HMAC.new(p,s,SHA512).digest()) 89 | except: 90 | try: 91 | 92 | from pbkdf2 import PBKDF2 93 | import hmac 94 | def pbkdf2_hmac_sha256(password,salt,iters=2048): 95 | return PBKDF2(password,salt, iterations=iters, macmodule=hmac, digestmodule=hashlib.sha512).read(64) 96 | except: 97 | raise RuntimeError("No implementation of pbkdf2 was found!") 98 | 99 | return pbkdf2_hmac_sha256(password=mnemonic_phrase,salt=b'mnemonic'+passphrase) 100 | 101 | def words_mine(prefix,entbits,satisfunction,wordlist=wordlist_english,randombits=random.getrandbits): 102 | prefix_bits=len(prefix)*11 103 | mine_bits=entbits-prefix_bits 104 | pint=words_to_mnemonic_int(prefix,wordlist) 105 | pint<<=mine_bits 106 | dint=randombits(mine_bits) 107 | count=0 108 | while(not satisfunction(entropy_to_words(eint_to_bytes(pint+dint,entbits)))): 109 | dint=randombits(mine_bits) 110 | if((count & 0xFFFF) == 0): 111 | print("Searched %f percent of the space" % (float(count)/float(1 << mine_bits))) 112 | 113 | return entropy_to_words(eint_to_bytes(pint+dint,entbits)) 114 | 115 | if __name__=="__main__": 116 | import json 117 | testvectors=json.load(open('vectors.json','r')) 118 | passed=True 119 | for v in testvectors['english']: 120 | ebytes=binascii.unhexlify(v[0]) 121 | w=' '.join(entropy_to_words(ebytes)) 122 | seed=mnemonic_to_seed(w,passphrase='TREZOR') 123 | passed = passed and w==v[1] 124 | passed = passed and binascii.hexlify(seed)==v[2] 125 | print("Tests %s." % ("Passed" if passed else "Failed")) 126 | 127 | 128 | -------------------------------------------------------------------------------- /bitcoin/py2specials.py: -------------------------------------------------------------------------------- 1 | import sys, re 2 | import binascii 3 | import os 4 | import hashlib 5 | 6 | 7 | if sys.version_info.major == 2: 8 | string_types = (str, unicode) 9 | string_or_bytes_types = string_types 10 | int_types = (int, float, long) 11 | 12 | # Base switching 13 | code_strings = { 14 | 2: '01', 15 | 10: '0123456789', 16 | 16: '0123456789abcdef', 17 | 32: 'abcdefghijklmnopqrstuvwxyz234567', 18 | 58: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz', 19 | 256: ''.join([chr(x) for x in range(256)]) 20 | } 21 | 22 | def bin_dbl_sha256(s): 23 | bytes_to_hash = from_string_to_bytes(s) 24 | return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() 25 | 26 | def lpad(msg, symbol, length): 27 | if len(msg) >= length: 28 | return msg 29 | return symbol * (length - len(msg)) + msg 30 | 31 | def get_code_string(base): 32 | if base in code_strings: 33 | return code_strings[base] 34 | else: 35 | raise ValueError("Invalid base!") 36 | 37 | def changebase(string, frm, to, minlen=0): 38 | if frm == to: 39 | return lpad(string, get_code_string(frm)[0], minlen) 40 | return encode(decode(string, frm), to, minlen) 41 | 42 | def bin_to_b58check(inp, magicbyte=0): 43 | if magicbyte == 0: 44 | inp = '\x00' + inp 45 | while magicbyte > 0: 46 | inp = chr(int(magicbyte % 256)) + inp 47 | magicbyte //= 256 48 | leadingzbytes = len(re.match('^\x00*', inp).group(0)) 49 | checksum = bin_dbl_sha256(inp)[:4] 50 | return '1' * leadingzbytes + changebase(inp+checksum, 256, 58) 51 | 52 | def bytes_to_hex_string(b): 53 | return b.encode('hex') 54 | 55 | def safe_from_hex(s): 56 | return s.decode('hex') 57 | 58 | def from_int_representation_to_bytes(a): 59 | return str(a) 60 | 61 | def from_int_to_byte(a): 62 | return chr(a) 63 | 64 | def from_byte_to_int(a): 65 | return ord(a) 66 | 67 | def from_bytes_to_string(s): 68 | return s 69 | 70 | def from_string_to_bytes(a): 71 | return a 72 | 73 | def safe_hexlify(a): 74 | return binascii.hexlify(a) 75 | 76 | def encode(val, base, minlen=0): 77 | base, minlen = int(base), int(minlen) 78 | code_string = get_code_string(base) 79 | result = "" 80 | while val > 0: 81 | result = code_string[val % base] + result 82 | val //= base 83 | return code_string[0] * max(minlen - len(result), 0) + result 84 | 85 | def decode(string, base): 86 | base = int(base) 87 | code_string = get_code_string(base) 88 | result = 0 89 | if base == 16: 90 | string = string.lower() 91 | while len(string) > 0: 92 | result *= base 93 | result += code_string.find(string[0]) 94 | string = string[1:] 95 | return result 96 | 97 | def random_string(x): 98 | return os.urandom(x) 99 | -------------------------------------------------------------------------------- /bitcoin/py3specials.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | import binascii 3 | import hashlib 4 | 5 | 6 | if sys.version_info.major == 3: 7 | string_types = (str) 8 | string_or_bytes_types = (str, bytes) 9 | int_types = (int, float) 10 | # Base switching 11 | code_strings = { 12 | 2: '01', 13 | 10: '0123456789', 14 | 16: '0123456789abcdef', 15 | 32: 'abcdefghijklmnopqrstuvwxyz234567', 16 | 58: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz', 17 | 256: ''.join([chr(x) for x in range(256)]) 18 | } 19 | 20 | def bin_dbl_sha256(s): 21 | bytes_to_hash = from_string_to_bytes(s) 22 | return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() 23 | 24 | def lpad(msg, symbol, length): 25 | if len(msg) >= length: 26 | return msg 27 | return symbol * (length - len(msg)) + msg 28 | 29 | def get_code_string(base): 30 | if base in code_strings: 31 | return code_strings[base] 32 | else: 33 | raise ValueError("Invalid base!") 34 | 35 | def changebase(string, frm, to, minlen=0): 36 | if frm == to: 37 | return lpad(string, get_code_string(frm)[0], minlen) 38 | return encode(decode(string, frm), to, minlen) 39 | 40 | def bin_to_b58check(inp, magicbyte=0): 41 | if magicbyte == 0: 42 | inp = from_int_to_byte(0) + inp 43 | while magicbyte > 0: 44 | inp = from_int_to_byte(magicbyte % 256) + inp 45 | magicbyte //= 256 46 | 47 | leadingzbytes = 0 48 | for x in inp: 49 | if x != 0: 50 | break 51 | leadingzbytes += 1 52 | 53 | checksum = bin_dbl_sha256(inp)[:4] 54 | return '1' * leadingzbytes + changebase(inp+checksum, 256, 58) 55 | 56 | def bytes_to_hex_string(b): 57 | if isinstance(b, str): 58 | return b 59 | 60 | return ''.join('{:02x}'.format(y) for y in b) 61 | 62 | def safe_from_hex(s): 63 | return bytes.fromhex(s) 64 | 65 | def from_int_representation_to_bytes(a): 66 | return bytes(str(a), 'utf-8') 67 | 68 | def from_int_to_byte(a): 69 | return bytes([a]) 70 | 71 | def from_byte_to_int(a): 72 | return a 73 | 74 | def from_string_to_bytes(a): 75 | return a if isinstance(a, bytes) else bytes(a, 'utf-8') 76 | 77 | def safe_hexlify(a): 78 | return str(binascii.hexlify(a), 'utf-8') 79 | 80 | def encode(val, base, minlen=0): 81 | base, minlen = int(base), int(minlen) 82 | code_string = get_code_string(base) 83 | result_bytes = bytes() 84 | while val > 0: 85 | curcode = code_string[val % base] 86 | result_bytes = bytes([ord(curcode)]) + result_bytes 87 | val //= base 88 | 89 | pad_size = minlen - len(result_bytes) 90 | 91 | padding_element = b'\x00' if base == 256 else b'1' \ 92 | if base == 58 else b'0' 93 | if (pad_size > 0): 94 | result_bytes = padding_element*pad_size + result_bytes 95 | 96 | result_string = ''.join([chr(y) for y in result_bytes]) 97 | result = result_bytes if base == 256 else result_string 98 | 99 | return result 100 | 101 | def decode(string, base): 102 | if base == 256 and isinstance(string, str): 103 | string = bytes(bytearray.fromhex(string)) 104 | base = int(base) 105 | code_string = get_code_string(base) 106 | result = 0 107 | if base == 256: 108 | def extract(d, cs): 109 | return d 110 | else: 111 | def extract(d, cs): 112 | return cs.find(d if isinstance(d, str) else chr(d)) 113 | 114 | if base == 16: 115 | string = string.lower() 116 | while len(string) > 0: 117 | result *= base 118 | result += extract(string[0], code_string) 119 | string = string[1:] 120 | return result 121 | 122 | def random_string(x): 123 | return str(os.urandom(x)) 124 | -------------------------------------------------------------------------------- /bitcoin/ripemd.py: -------------------------------------------------------------------------------- 1 | ## ripemd.py - pure Python implementation of the RIPEMD-160 algorithm. 2 | ## Bjorn Edstrom 16 december 2007. 3 | ## 4 | ## Copyrights 5 | ## ========== 6 | ## 7 | ## This code is a derived from an implementation by Markus Friedl which is 8 | ## subject to the following license. This Python implementation is not 9 | ## subject to any other license. 10 | ## 11 | ##/* 12 | ## * Copyright (c) 2001 Markus Friedl. All rights reserved. 13 | ## * 14 | ## * Redistribution and use in source and binary forms, with or without 15 | ## * modification, are permitted provided that the following conditions 16 | ## * are met: 17 | ## * 1. Redistributions of source code must retain the above copyright 18 | ## * notice, this list of conditions and the following disclaimer. 19 | ## * 2. Redistributions in binary form must reproduce the above copyright 20 | ## * notice, this list of conditions and the following disclaimer in the 21 | ## * documentation and/or other materials provided with the distribution. 22 | ## * 23 | ## * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 | ## * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | ## * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 | ## * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | ## * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 | ## * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | ## * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | ## * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | ## * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 | ## * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | ## */ 34 | ##/* 35 | ## * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160", 36 | ## * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997, 37 | ## * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf 38 | ## */ 39 | 40 | try: 41 | import psyco 42 | psyco.full() 43 | except ImportError: 44 | pass 45 | 46 | import sys 47 | 48 | is_python2 = sys.version_info.major == 2 49 | #block_size = 1 50 | digest_size = 20 51 | digestsize = 20 52 | 53 | try: 54 | range = xrange 55 | except: 56 | pass 57 | 58 | class RIPEMD160: 59 | """Return a new RIPEMD160 object. An optional string argument 60 | may be provided; if present, this string will be automatically 61 | hashed.""" 62 | 63 | def __init__(self, arg=None): 64 | self.ctx = RMDContext() 65 | if arg: 66 | self.update(arg) 67 | self.dig = None 68 | 69 | def update(self, arg): 70 | """update(arg)""" 71 | RMD160Update(self.ctx, arg, len(arg)) 72 | self.dig = None 73 | 74 | def digest(self): 75 | """digest()""" 76 | if self.dig: 77 | return self.dig 78 | ctx = self.ctx.copy() 79 | self.dig = RMD160Final(self.ctx) 80 | self.ctx = ctx 81 | return self.dig 82 | 83 | def hexdigest(self): 84 | """hexdigest()""" 85 | dig = self.digest() 86 | hex_digest = '' 87 | for d in dig: 88 | if (is_python2): 89 | hex_digest += '%02x' % ord(d) 90 | else: 91 | hex_digest += '%02x' % d 92 | return hex_digest 93 | 94 | def copy(self): 95 | """copy()""" 96 | import copy 97 | return copy.deepcopy(self) 98 | 99 | 100 | 101 | def new(arg=None): 102 | """Return a new RIPEMD160 object. An optional string argument 103 | may be provided; if present, this string will be automatically 104 | hashed.""" 105 | return RIPEMD160(arg) 106 | 107 | 108 | 109 | # 110 | # Private. 111 | # 112 | 113 | class RMDContext: 114 | def __init__(self): 115 | self.state = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 116 | 0x10325476, 0xC3D2E1F0] # uint32 117 | self.count = 0 # uint64 118 | self.buffer = [0]*64 # uchar 119 | def copy(self): 120 | ctx = RMDContext() 121 | ctx.state = self.state[:] 122 | ctx.count = self.count 123 | ctx.buffer = self.buffer[:] 124 | return ctx 125 | 126 | K0 = 0x00000000 127 | K1 = 0x5A827999 128 | K2 = 0x6ED9EBA1 129 | K3 = 0x8F1BBCDC 130 | K4 = 0xA953FD4E 131 | 132 | KK0 = 0x50A28BE6 133 | KK1 = 0x5C4DD124 134 | KK2 = 0x6D703EF3 135 | KK3 = 0x7A6D76E9 136 | KK4 = 0x00000000 137 | 138 | def ROL(n, x): 139 | return ((x << n) & 0xffffffff) | (x >> (32 - n)) 140 | 141 | def F0(x, y, z): 142 | return x ^ y ^ z 143 | 144 | def F1(x, y, z): 145 | return (x & y) | (((~x) % 0x100000000) & z) 146 | 147 | def F2(x, y, z): 148 | return (x | ((~y) % 0x100000000)) ^ z 149 | 150 | def F3(x, y, z): 151 | return (x & z) | (((~z) % 0x100000000) & y) 152 | 153 | def F4(x, y, z): 154 | return x ^ (y | ((~z) % 0x100000000)) 155 | 156 | def R(a, b, c, d, e, Fj, Kj, sj, rj, X): 157 | a = ROL(sj, (a + Fj(b, c, d) + X[rj] + Kj) % 0x100000000) + e 158 | c = ROL(10, c) 159 | return a % 0x100000000, c 160 | 161 | PADDING = [0x80] + [0]*63 162 | 163 | import sys 164 | import struct 165 | 166 | def RMD160Transform(state, block): #uint32 state[5], uchar block[64] 167 | x = [0]*16 168 | if sys.byteorder == 'little': 169 | if is_python2: 170 | x = struct.unpack('<16L', ''.join([chr(x) for x in block[0:64]])) 171 | else: 172 | x = struct.unpack('<16L', bytes(block[0:64])) 173 | else: 174 | raise "Error!!" 175 | a = state[0] 176 | b = state[1] 177 | c = state[2] 178 | d = state[3] 179 | e = state[4] 180 | 181 | #/* Round 1 */ 182 | a, c = R(a, b, c, d, e, F0, K0, 11, 0, x); 183 | e, b = R(e, a, b, c, d, F0, K0, 14, 1, x); 184 | d, a = R(d, e, a, b, c, F0, K0, 15, 2, x); 185 | c, e = R(c, d, e, a, b, F0, K0, 12, 3, x); 186 | b, d = R(b, c, d, e, a, F0, K0, 5, 4, x); 187 | a, c = R(a, b, c, d, e, F0, K0, 8, 5, x); 188 | e, b = R(e, a, b, c, d, F0, K0, 7, 6, x); 189 | d, a = R(d, e, a, b, c, F0, K0, 9, 7, x); 190 | c, e = R(c, d, e, a, b, F0, K0, 11, 8, x); 191 | b, d = R(b, c, d, e, a, F0, K0, 13, 9, x); 192 | a, c = R(a, b, c, d, e, F0, K0, 14, 10, x); 193 | e, b = R(e, a, b, c, d, F0, K0, 15, 11, x); 194 | d, a = R(d, e, a, b, c, F0, K0, 6, 12, x); 195 | c, e = R(c, d, e, a, b, F0, K0, 7, 13, x); 196 | b, d = R(b, c, d, e, a, F0, K0, 9, 14, x); 197 | a, c = R(a, b, c, d, e, F0, K0, 8, 15, x); #/* #15 */ 198 | #/* Round 2 */ 199 | e, b = R(e, a, b, c, d, F1, K1, 7, 7, x); 200 | d, a = R(d, e, a, b, c, F1, K1, 6, 4, x); 201 | c, e = R(c, d, e, a, b, F1, K1, 8, 13, x); 202 | b, d = R(b, c, d, e, a, F1, K1, 13, 1, x); 203 | a, c = R(a, b, c, d, e, F1, K1, 11, 10, x); 204 | e, b = R(e, a, b, c, d, F1, K1, 9, 6, x); 205 | d, a = R(d, e, a, b, c, F1, K1, 7, 15, x); 206 | c, e = R(c, d, e, a, b, F1, K1, 15, 3, x); 207 | b, d = R(b, c, d, e, a, F1, K1, 7, 12, x); 208 | a, c = R(a, b, c, d, e, F1, K1, 12, 0, x); 209 | e, b = R(e, a, b, c, d, F1, K1, 15, 9, x); 210 | d, a = R(d, e, a, b, c, F1, K1, 9, 5, x); 211 | c, e = R(c, d, e, a, b, F1, K1, 11, 2, x); 212 | b, d = R(b, c, d, e, a, F1, K1, 7, 14, x); 213 | a, c = R(a, b, c, d, e, F1, K1, 13, 11, x); 214 | e, b = R(e, a, b, c, d, F1, K1, 12, 8, x); #/* #31 */ 215 | #/* Round 3 */ 216 | d, a = R(d, e, a, b, c, F2, K2, 11, 3, x); 217 | c, e = R(c, d, e, a, b, F2, K2, 13, 10, x); 218 | b, d = R(b, c, d, e, a, F2, K2, 6, 14, x); 219 | a, c = R(a, b, c, d, e, F2, K2, 7, 4, x); 220 | e, b = R(e, a, b, c, d, F2, K2, 14, 9, x); 221 | d, a = R(d, e, a, b, c, F2, K2, 9, 15, x); 222 | c, e = R(c, d, e, a, b, F2, K2, 13, 8, x); 223 | b, d = R(b, c, d, e, a, F2, K2, 15, 1, x); 224 | a, c = R(a, b, c, d, e, F2, K2, 14, 2, x); 225 | e, b = R(e, a, b, c, d, F2, K2, 8, 7, x); 226 | d, a = R(d, e, a, b, c, F2, K2, 13, 0, x); 227 | c, e = R(c, d, e, a, b, F2, K2, 6, 6, x); 228 | b, d = R(b, c, d, e, a, F2, K2, 5, 13, x); 229 | a, c = R(a, b, c, d, e, F2, K2, 12, 11, x); 230 | e, b = R(e, a, b, c, d, F2, K2, 7, 5, x); 231 | d, a = R(d, e, a, b, c, F2, K2, 5, 12, x); #/* #47 */ 232 | #/* Round 4 */ 233 | c, e = R(c, d, e, a, b, F3, K3, 11, 1, x); 234 | b, d = R(b, c, d, e, a, F3, K3, 12, 9, x); 235 | a, c = R(a, b, c, d, e, F3, K3, 14, 11, x); 236 | e, b = R(e, a, b, c, d, F3, K3, 15, 10, x); 237 | d, a = R(d, e, a, b, c, F3, K3, 14, 0, x); 238 | c, e = R(c, d, e, a, b, F3, K3, 15, 8, x); 239 | b, d = R(b, c, d, e, a, F3, K3, 9, 12, x); 240 | a, c = R(a, b, c, d, e, F3, K3, 8, 4, x); 241 | e, b = R(e, a, b, c, d, F3, K3, 9, 13, x); 242 | d, a = R(d, e, a, b, c, F3, K3, 14, 3, x); 243 | c, e = R(c, d, e, a, b, F3, K3, 5, 7, x); 244 | b, d = R(b, c, d, e, a, F3, K3, 6, 15, x); 245 | a, c = R(a, b, c, d, e, F3, K3, 8, 14, x); 246 | e, b = R(e, a, b, c, d, F3, K3, 6, 5, x); 247 | d, a = R(d, e, a, b, c, F3, K3, 5, 6, x); 248 | c, e = R(c, d, e, a, b, F3, K3, 12, 2, x); #/* #63 */ 249 | #/* Round 5 */ 250 | b, d = R(b, c, d, e, a, F4, K4, 9, 4, x); 251 | a, c = R(a, b, c, d, e, F4, K4, 15, 0, x); 252 | e, b = R(e, a, b, c, d, F4, K4, 5, 5, x); 253 | d, a = R(d, e, a, b, c, F4, K4, 11, 9, x); 254 | c, e = R(c, d, e, a, b, F4, K4, 6, 7, x); 255 | b, d = R(b, c, d, e, a, F4, K4, 8, 12, x); 256 | a, c = R(a, b, c, d, e, F4, K4, 13, 2, x); 257 | e, b = R(e, a, b, c, d, F4, K4, 12, 10, x); 258 | d, a = R(d, e, a, b, c, F4, K4, 5, 14, x); 259 | c, e = R(c, d, e, a, b, F4, K4, 12, 1, x); 260 | b, d = R(b, c, d, e, a, F4, K4, 13, 3, x); 261 | a, c = R(a, b, c, d, e, F4, K4, 14, 8, x); 262 | e, b = R(e, a, b, c, d, F4, K4, 11, 11, x); 263 | d, a = R(d, e, a, b, c, F4, K4, 8, 6, x); 264 | c, e = R(c, d, e, a, b, F4, K4, 5, 15, x); 265 | b, d = R(b, c, d, e, a, F4, K4, 6, 13, x); #/* #79 */ 266 | 267 | aa = a; 268 | bb = b; 269 | cc = c; 270 | dd = d; 271 | ee = e; 272 | 273 | a = state[0] 274 | b = state[1] 275 | c = state[2] 276 | d = state[3] 277 | e = state[4] 278 | 279 | #/* Parallel round 1 */ 280 | a, c = R(a, b, c, d, e, F4, KK0, 8, 5, x) 281 | e, b = R(e, a, b, c, d, F4, KK0, 9, 14, x) 282 | d, a = R(d, e, a, b, c, F4, KK0, 9, 7, x) 283 | c, e = R(c, d, e, a, b, F4, KK0, 11, 0, x) 284 | b, d = R(b, c, d, e, a, F4, KK0, 13, 9, x) 285 | a, c = R(a, b, c, d, e, F4, KK0, 15, 2, x) 286 | e, b = R(e, a, b, c, d, F4, KK0, 15, 11, x) 287 | d, a = R(d, e, a, b, c, F4, KK0, 5, 4, x) 288 | c, e = R(c, d, e, a, b, F4, KK0, 7, 13, x) 289 | b, d = R(b, c, d, e, a, F4, KK0, 7, 6, x) 290 | a, c = R(a, b, c, d, e, F4, KK0, 8, 15, x) 291 | e, b = R(e, a, b, c, d, F4, KK0, 11, 8, x) 292 | d, a = R(d, e, a, b, c, F4, KK0, 14, 1, x) 293 | c, e = R(c, d, e, a, b, F4, KK0, 14, 10, x) 294 | b, d = R(b, c, d, e, a, F4, KK0, 12, 3, x) 295 | a, c = R(a, b, c, d, e, F4, KK0, 6, 12, x) #/* #15 */ 296 | #/* Parallel round 2 */ 297 | e, b = R(e, a, b, c, d, F3, KK1, 9, 6, x) 298 | d, a = R(d, e, a, b, c, F3, KK1, 13, 11, x) 299 | c, e = R(c, d, e, a, b, F3, KK1, 15, 3, x) 300 | b, d = R(b, c, d, e, a, F3, KK1, 7, 7, x) 301 | a, c = R(a, b, c, d, e, F3, KK1, 12, 0, x) 302 | e, b = R(e, a, b, c, d, F3, KK1, 8, 13, x) 303 | d, a = R(d, e, a, b, c, F3, KK1, 9, 5, x) 304 | c, e = R(c, d, e, a, b, F3, KK1, 11, 10, x) 305 | b, d = R(b, c, d, e, a, F3, KK1, 7, 14, x) 306 | a, c = R(a, b, c, d, e, F3, KK1, 7, 15, x) 307 | e, b = R(e, a, b, c, d, F3, KK1, 12, 8, x) 308 | d, a = R(d, e, a, b, c, F3, KK1, 7, 12, x) 309 | c, e = R(c, d, e, a, b, F3, KK1, 6, 4, x) 310 | b, d = R(b, c, d, e, a, F3, KK1, 15, 9, x) 311 | a, c = R(a, b, c, d, e, F3, KK1, 13, 1, x) 312 | e, b = R(e, a, b, c, d, F3, KK1, 11, 2, x) #/* #31 */ 313 | #/* Parallel round 3 */ 314 | d, a = R(d, e, a, b, c, F2, KK2, 9, 15, x) 315 | c, e = R(c, d, e, a, b, F2, KK2, 7, 5, x) 316 | b, d = R(b, c, d, e, a, F2, KK2, 15, 1, x) 317 | a, c = R(a, b, c, d, e, F2, KK2, 11, 3, x) 318 | e, b = R(e, a, b, c, d, F2, KK2, 8, 7, x) 319 | d, a = R(d, e, a, b, c, F2, KK2, 6, 14, x) 320 | c, e = R(c, d, e, a, b, F2, KK2, 6, 6, x) 321 | b, d = R(b, c, d, e, a, F2, KK2, 14, 9, x) 322 | a, c = R(a, b, c, d, e, F2, KK2, 12, 11, x) 323 | e, b = R(e, a, b, c, d, F2, KK2, 13, 8, x) 324 | d, a = R(d, e, a, b, c, F2, KK2, 5, 12, x) 325 | c, e = R(c, d, e, a, b, F2, KK2, 14, 2, x) 326 | b, d = R(b, c, d, e, a, F2, KK2, 13, 10, x) 327 | a, c = R(a, b, c, d, e, F2, KK2, 13, 0, x) 328 | e, b = R(e, a, b, c, d, F2, KK2, 7, 4, x) 329 | d, a = R(d, e, a, b, c, F2, KK2, 5, 13, x) #/* #47 */ 330 | #/* Parallel round 4 */ 331 | c, e = R(c, d, e, a, b, F1, KK3, 15, 8, x) 332 | b, d = R(b, c, d, e, a, F1, KK3, 5, 6, x) 333 | a, c = R(a, b, c, d, e, F1, KK3, 8, 4, x) 334 | e, b = R(e, a, b, c, d, F1, KK3, 11, 1, x) 335 | d, a = R(d, e, a, b, c, F1, KK3, 14, 3, x) 336 | c, e = R(c, d, e, a, b, F1, KK3, 14, 11, x) 337 | b, d = R(b, c, d, e, a, F1, KK3, 6, 15, x) 338 | a, c = R(a, b, c, d, e, F1, KK3, 14, 0, x) 339 | e, b = R(e, a, b, c, d, F1, KK3, 6, 5, x) 340 | d, a = R(d, e, a, b, c, F1, KK3, 9, 12, x) 341 | c, e = R(c, d, e, a, b, F1, KK3, 12, 2, x) 342 | b, d = R(b, c, d, e, a, F1, KK3, 9, 13, x) 343 | a, c = R(a, b, c, d, e, F1, KK3, 12, 9, x) 344 | e, b = R(e, a, b, c, d, F1, KK3, 5, 7, x) 345 | d, a = R(d, e, a, b, c, F1, KK3, 15, 10, x) 346 | c, e = R(c, d, e, a, b, F1, KK3, 8, 14, x) #/* #63 */ 347 | #/* Parallel round 5 */ 348 | b, d = R(b, c, d, e, a, F0, KK4, 8, 12, x) 349 | a, c = R(a, b, c, d, e, F0, KK4, 5, 15, x) 350 | e, b = R(e, a, b, c, d, F0, KK4, 12, 10, x) 351 | d, a = R(d, e, a, b, c, F0, KK4, 9, 4, x) 352 | c, e = R(c, d, e, a, b, F0, KK4, 12, 1, x) 353 | b, d = R(b, c, d, e, a, F0, KK4, 5, 5, x) 354 | a, c = R(a, b, c, d, e, F0, KK4, 14, 8, x) 355 | e, b = R(e, a, b, c, d, F0, KK4, 6, 7, x) 356 | d, a = R(d, e, a, b, c, F0, KK4, 8, 6, x) 357 | c, e = R(c, d, e, a, b, F0, KK4, 13, 2, x) 358 | b, d = R(b, c, d, e, a, F0, KK4, 6, 13, x) 359 | a, c = R(a, b, c, d, e, F0, KK4, 5, 14, x) 360 | e, b = R(e, a, b, c, d, F0, KK4, 15, 0, x) 361 | d, a = R(d, e, a, b, c, F0, KK4, 13, 3, x) 362 | c, e = R(c, d, e, a, b, F0, KK4, 11, 9, x) 363 | b, d = R(b, c, d, e, a, F0, KK4, 11, 11, x) #/* #79 */ 364 | 365 | t = (state[1] + cc + d) % 0x100000000; 366 | state[1] = (state[2] + dd + e) % 0x100000000; 367 | state[2] = (state[3] + ee + a) % 0x100000000; 368 | state[3] = (state[4] + aa + b) % 0x100000000; 369 | state[4] = (state[0] + bb + c) % 0x100000000; 370 | state[0] = t % 0x100000000; 371 | 372 | pass 373 | 374 | 375 | def RMD160Update(ctx, inp, inplen): 376 | if type(inp) == str: 377 | inp = [ord(i)&0xff for i in inp] 378 | 379 | have = int((ctx.count // 8) % 64) 380 | inplen = int(inplen) 381 | need = 64 - have 382 | ctx.count += 8 * inplen 383 | off = 0 384 | if inplen >= need: 385 | if have: 386 | for i in range(need): 387 | ctx.buffer[have+i] = inp[i] 388 | RMD160Transform(ctx.state, ctx.buffer) 389 | off = need 390 | have = 0 391 | while off + 64 <= inplen: 392 | RMD160Transform(ctx.state, inp[off:]) #<--- 393 | off += 64 394 | if off < inplen: 395 | # memcpy(ctx->buffer + have, input+off, len-off); 396 | for i in range(inplen - off): 397 | ctx.buffer[have+i] = inp[off+i] 398 | 399 | def RMD160Final(ctx): 400 | size = struct.pack(" 73: return False 180 | if (sig[0] != 0x30): return False 181 | if (sig[1] != len(sig)-3): return False 182 | rlen = sig[3] 183 | if (5+rlen >= len(sig)): return False 184 | slen = sig[5+rlen] 185 | if (rlen + slen + 7 != len(sig)): return False 186 | if (sig[2] != 0x02): return False 187 | if (rlen == 0): return False 188 | if (sig[4] & 0x80): return False 189 | if (rlen > 1 and (sig[4] == 0x00) and not (sig[5] & 0x80)): return False 190 | if (sig[4+rlen] != 0x02): return False 191 | if (slen == 0): return False 192 | if (sig[rlen+6] & 0x80): return False 193 | if (slen > 1 and (sig[6+rlen] == 0x00) and not (sig[7+rlen] & 0x80)): 194 | return False 195 | return True 196 | 197 | def txhash(tx, hashcode=None): 198 | if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): 199 | tx = changebase(tx, 16, 256) 200 | if hashcode: 201 | return dbl_sha256(from_string_to_bytes(tx) + encode(int(hashcode), 256, 4)[::-1]) 202 | else: 203 | return safe_hexlify(bin_dbl_sha256(tx)[::-1]) 204 | 205 | 206 | def bin_txhash(tx, hashcode=None): 207 | return binascii.unhexlify(txhash(tx, hashcode)) 208 | 209 | 210 | def ecdsa_tx_sign(tx, priv, hashcode=SIGHASH_ALL): 211 | rawsig = ecdsa_raw_sign(bin_txhash(tx, hashcode), priv) 212 | return der_encode_sig(*rawsig)+encode(hashcode, 16, 2) 213 | 214 | 215 | def ecdsa_tx_verify(tx, sig, pub, hashcode=SIGHASH_ALL): 216 | return ecdsa_raw_verify(bin_txhash(tx, hashcode), der_decode_sig(sig), pub) 217 | 218 | 219 | def ecdsa_tx_recover(tx, sig, hashcode=SIGHASH_ALL): 220 | z = bin_txhash(tx, hashcode) 221 | _, r, s = der_decode_sig(sig) 222 | left = ecdsa_raw_recover(z, (0, r, s)) 223 | right = ecdsa_raw_recover(z, (1, r, s)) 224 | return (encode_pubkey(left, 'hex'), encode_pubkey(right, 'hex')) 225 | 226 | # Scripts 227 | 228 | 229 | def mk_pubkey_script(addr): 230 | # Keep the auxiliary functions around for altcoins' sake 231 | return '76a914' + b58check_to_hex(addr) + '88ac' 232 | 233 | 234 | def mk_scripthash_script(addr): 235 | return 'a914' + b58check_to_hex(addr) + '87' 236 | 237 | # Address representation to output script 238 | 239 | 240 | def address_to_script(addr): 241 | if addr[0] == '3' or addr[0] == '2': 242 | return mk_scripthash_script(addr) 243 | else: 244 | return mk_pubkey_script(addr) 245 | 246 | # Output script to address representation 247 | 248 | 249 | def script_to_address(script, vbyte=0): 250 | if re.match('^[0-9a-fA-F]*$', script): 251 | script = binascii.unhexlify(script) 252 | if script[:3] == b'\x76\xa9\x14' and script[-2:] == b'\x88\xac' and len(script) == 25: 253 | return bin_to_b58check(script[3:-2], vbyte) # pubkey hash addresses 254 | else: 255 | if vbyte in [111, 196]: 256 | # Testnet 257 | scripthash_byte = 196 258 | elif vbyte == 0: 259 | # Mainnet 260 | scripthash_byte = 5 261 | else: 262 | scripthash_byte = vbyte 263 | # BIP0016 scripthash addresses 264 | return bin_to_b58check(script[2:-1], scripthash_byte) 265 | 266 | 267 | def p2sh_scriptaddr(script, magicbyte=5): 268 | if re.match('^[0-9a-fA-F]*$', script): 269 | script = binascii.unhexlify(script) 270 | return hex_to_b58check(hash160(script), magicbyte) 271 | scriptaddr = p2sh_scriptaddr 272 | 273 | 274 | def deserialize_script(script): 275 | if isinstance(script, str) and re.match('^[0-9a-fA-F]*$', script): 276 | return json_changebase(deserialize_script(binascii.unhexlify(script)), 277 | lambda x: safe_hexlify(x)) 278 | out, pos = [], 0 279 | while pos < len(script): 280 | code = from_byte_to_int(script[pos]) 281 | if code == 0: 282 | out.append(None) 283 | pos += 1 284 | elif code <= 75: 285 | out.append(script[pos+1:pos+1+code]) 286 | pos += 1 + code 287 | elif code <= 78: 288 | szsz = pow(2, code - 76) 289 | sz = decode(script[pos+szsz: pos:-1], 256) 290 | out.append(script[pos + 1 + szsz:pos + 1 + szsz + sz]) 291 | pos += 1 + szsz + sz 292 | elif code <= 96: 293 | out.append(code - 80) 294 | pos += 1 295 | else: 296 | out.append(code) 297 | pos += 1 298 | return out 299 | 300 | 301 | def serialize_script_unit(unit): 302 | if isinstance(unit, int): 303 | if unit < 16: 304 | return from_int_to_byte(unit + 80) 305 | else: 306 | return from_int_to_byte(unit) 307 | elif unit is None: 308 | return b'\x00' 309 | else: 310 | if len(unit) <= 75: 311 | return from_int_to_byte(len(unit))+unit 312 | elif len(unit) < 256: 313 | return from_int_to_byte(76)+from_int_to_byte(len(unit))+unit 314 | elif len(unit) < 65536: 315 | return from_int_to_byte(77)+encode(len(unit), 256, 2)[::-1]+unit 316 | else: 317 | return from_int_to_byte(78)+encode(len(unit), 256, 4)[::-1]+unit 318 | 319 | 320 | if is_python2: 321 | def serialize_script(script): 322 | if json_is_base(script, 16): 323 | return binascii.hexlify(serialize_script(json_changebase(script, 324 | lambda x: binascii.unhexlify(x)))) 325 | return ''.join(map(serialize_script_unit, script)) 326 | else: 327 | def serialize_script(script): 328 | if json_is_base(script, 16): 329 | return safe_hexlify(serialize_script(json_changebase(script, 330 | lambda x: binascii.unhexlify(x)))) 331 | 332 | result = bytes() 333 | for b in map(serialize_script_unit, script): 334 | result += b if isinstance(b, bytes) else bytes(b, 'utf-8') 335 | return result 336 | 337 | 338 | def mk_multisig_script(*args): # [pubs],k or pub1,pub2...pub[n],k 339 | if isinstance(args[0], list): 340 | pubs, k = args[0], int(args[1]) 341 | else: 342 | pubs = list(filter(lambda x: len(str(x)) >= 32, args)) 343 | k = int(args[len(pubs)]) 344 | return serialize_script([k]+pubs+[len(pubs)]+[0xae]) 345 | 346 | # Signing and verifying 347 | 348 | 349 | def verify_tx_input(tx, i, script, sig, pub): 350 | if re.match('^[0-9a-fA-F]*$', tx): 351 | tx = binascii.unhexlify(tx) 352 | if re.match('^[0-9a-fA-F]*$', script): 353 | script = binascii.unhexlify(script) 354 | if not re.match('^[0-9a-fA-F]*$', sig): 355 | sig = safe_hexlify(sig) 356 | hashcode = decode(sig[-2:], 16) 357 | modtx = signature_form(tx, int(i), script, hashcode) 358 | return ecdsa_tx_verify(modtx, sig, pub, hashcode) 359 | 360 | 361 | def sign(tx, i, priv, hashcode=SIGHASH_ALL): 362 | i = int(i) 363 | if (not is_python2 and isinstance(re, bytes)) or not re.match('^[0-9a-fA-F]*$', tx): 364 | return binascii.unhexlify(sign(safe_hexlify(tx), i, priv)) 365 | if len(priv) <= 33: 366 | priv = safe_hexlify(priv) 367 | pub = privkey_to_pubkey(priv) 368 | address = pubkey_to_address(pub) 369 | signing_tx = signature_form(tx, i, mk_pubkey_script(address), hashcode) 370 | sig = ecdsa_tx_sign(signing_tx, priv, hashcode) 371 | txobj = deserialize(tx) 372 | txobj["ins"][i]["script"] = serialize_script([sig, pub]) 373 | return serialize(txobj) 374 | 375 | 376 | def signall(tx, priv): 377 | # if priv is a dictionary, assume format is 378 | # { 'txinhash:txinidx' : privkey } 379 | if isinstance(priv, dict): 380 | for e, i in enumerate(deserialize(tx)["ins"]): 381 | k = priv["%s:%d" % (i["outpoint"]["hash"], i["outpoint"]["index"])] 382 | tx = sign(tx, e, k) 383 | else: 384 | for i in range(len(deserialize(tx)["ins"])): 385 | tx = sign(tx, i, priv) 386 | return tx 387 | 388 | 389 | def multisign(tx, i, script, pk, hashcode=SIGHASH_ALL): 390 | if re.match('^[0-9a-fA-F]*$', tx): 391 | tx = binascii.unhexlify(tx) 392 | if re.match('^[0-9a-fA-F]*$', script): 393 | script = binascii.unhexlify(script) 394 | modtx = signature_form(tx, i, script, hashcode) 395 | return ecdsa_tx_sign(modtx, pk, hashcode) 396 | 397 | 398 | def apply_multisignatures(*args): 399 | # tx,i,script,sigs OR tx,i,script,sig1,sig2...,sig[n] 400 | tx, i, script = args[0], int(args[1]), args[2] 401 | sigs = args[3] if isinstance(args[3], list) else list(args[3:]) 402 | 403 | if isinstance(script, str) and re.match('^[0-9a-fA-F]*$', script): 404 | script = binascii.unhexlify(script) 405 | sigs = [binascii.unhexlify(x) if x[:2] == '30' else x for x in sigs] 406 | if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): 407 | return safe_hexlify(apply_multisignatures(binascii.unhexlify(tx), i, script, sigs)) 408 | 409 | # Not pushing empty elements on the top of the stack if passing no 410 | # script (in case of bare multisig inputs there is no script) 411 | script_blob = [] if script.__len__() == 0 else [script] 412 | 413 | txobj = deserialize(tx) 414 | txobj["ins"][i]["script"] = serialize_script([None]+sigs+script_blob) 415 | return serialize(txobj) 416 | 417 | 418 | def is_inp(arg): 419 | return len(arg) > 64 or "output" in arg or "outpoint" in arg 420 | 421 | 422 | def mktx(*args): 423 | # [in0, in1...],[out0, out1...] or in0, in1 ... out0 out1 ... 424 | ins, outs = [], [] 425 | for arg in args: 426 | if isinstance(arg, list): 427 | for a in arg: (ins if is_inp(a) else outs).append(a) 428 | else: 429 | (ins if is_inp(arg) else outs).append(arg) 430 | 431 | txobj = {"locktime": 0, "version": 1, "ins": [], "outs": []} 432 | for i in ins: 433 | if isinstance(i, dict) and "outpoint" in i: 434 | txobj["ins"].append(i) 435 | else: 436 | if isinstance(i, dict) and "output" in i: 437 | i = i["output"] 438 | txobj["ins"].append({ 439 | "outpoint": {"hash": i[:64], "index": int(i[65:])}, 440 | "script": "", 441 | "sequence": 4294967295 442 | }) 443 | for o in outs: 444 | if isinstance(o, string_or_bytes_types): 445 | addr = o[:o.find(':')] 446 | val = int(o[o.find(':')+1:]) 447 | o = {} 448 | if re.match('^[0-9a-fA-F]*$', addr): 449 | o["script"] = addr 450 | else: 451 | o["address"] = addr 452 | o["value"] = val 453 | 454 | outobj = {} 455 | if "address" in o: 456 | outobj["script"] = address_to_script(o["address"]) 457 | elif "script" in o: 458 | outobj["script"] = o["script"] 459 | else: 460 | raise Exception("Could not find 'address' or 'script' in output.") 461 | outobj["value"] = o["value"] 462 | txobj["outs"].append(outobj) 463 | 464 | return serialize(txobj) 465 | 466 | 467 | def select(unspent, value): 468 | value = int(value) 469 | high = [u for u in unspent if u["value"] >= value] 470 | high.sort(key=lambda u: u["value"]) 471 | low = [u for u in unspent if u["value"] < value] 472 | low.sort(key=lambda u: -u["value"]) 473 | if len(high): 474 | return [high[0]] 475 | i, tv = 0, 0 476 | while tv < value and i < len(low): 477 | tv += low[i]["value"] 478 | i += 1 479 | if tv < value: 480 | raise Exception("Not enough funds") 481 | return low[:i] 482 | 483 | # Only takes inputs of the form { "output": blah, "value": foo } 484 | 485 | 486 | def mksend(*args): 487 | argz, change, fee = args[:-2], args[-2], int(args[-1]) 488 | ins, outs = [], [] 489 | for arg in argz: 490 | if isinstance(arg, list): 491 | for a in arg: 492 | (ins if is_inp(a) else outs).append(a) 493 | else: 494 | (ins if is_inp(arg) else outs).append(arg) 495 | 496 | isum = sum([i["value"] for i in ins]) 497 | osum, outputs2 = 0, [] 498 | for o in outs: 499 | if isinstance(o, string_types): 500 | o2 = { 501 | "address": o[:o.find(':')], 502 | "value": int(o[o.find(':')+1:]) 503 | } 504 | else: 505 | o2 = o 506 | outputs2.append(o2) 507 | osum += o2["value"] 508 | 509 | if isum < osum+fee: 510 | raise Exception("Not enough money") 511 | elif isum > osum+fee+5430: 512 | outputs2 += [{"address": change, "value": isum-osum-fee}] 513 | 514 | return mktx(ins, outputs2) 515 | -------------------------------------------------------------------------------- /hash: -------------------------------------------------------------------------------- 1 | Hash Tables 2 | -------------------------------------------------------------------------------- /motivation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/motivation.png -------------------------------------------------------------------------------- /session.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from tqdm import tqdm 4 | 5 | def storagespace(id, destination): 6 | def get_confirm_token(response): 7 | for key, value in response.cookies.items(): 8 | if key.startswith('download_warning'): 9 | return value 10 | 11 | return None 12 | 13 | def save_response_content(response, destination): 14 | CHUNK_SIZE = 32768 15 | 16 | with open(destination, "wb") as f: 17 | with tqdm(unit='B', unit_scale=True, unit_divisor=1024) as bar: 18 | for chunk in response.iter_content(CHUNK_SIZE): 19 | if chunk: 20 | f.write(chunk) 21 | bar.update(CHUNK_SIZE) 22 | 23 | URL = "https://docs.google.com/uc?export=download" 24 | 25 | session = requests.Session() 26 | 27 | response = session.get(URL, params = { 'id' : id }, stream = True) 28 | token = get_confirm_token(response) 29 | 30 | if token: 31 | params = { 'id' : id, 'confirm' : token } 32 | response = session.get(URL, params = params, stream = True) 33 | 34 | save_response_content(response, destination) 35 | 36 | 37 | if __name__ == "__main__": 38 | import sys 39 | if len(sys.argv) is not 3: 40 | print("") 41 | else: 42 | 43 | file_id = sys.argv[1] 44 | 45 | destination = sys.argv[2] 46 | storagespace(file_id, destination) 47 | -------------------------------------------------------------------------------- /storagespace: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demining/bitcoindigger/18075cb93fff6d7e7a168d2bb93d9bb4986865e9/storagespace --------------------------------------------------------------------------------