├── .gitignore ├── Blockchain ├── Backend │ ├── util │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── util.cpython-39.pyc │ │ │ ├── util.cpython-310.pyc │ │ │ ├── __init__.cpython-310.pyc │ │ │ └── __init__.cpython-39.pyc │ │ └── util.py │ └── core │ │ ├── EllepticCurve │ │ ├── __init__.py.txt │ │ ├── __pycache__ │ │ │ ├── Tx.cpython-38.pyc │ │ │ ├── op.cpython-38.pyc │ │ │ ├── op.cpython-39.pyc │ │ │ ├── Block.cpython-38.pyc │ │ │ ├── Point.cpython-38.pyc │ │ │ ├── Point.cpython-39.pyc │ │ │ ├── Tx1.cpython-38.pyc │ │ │ ├── op.cpython-310.pyc │ │ │ ├── helper.cpython-38.pyc │ │ │ ├── helper.cpython-39.pyc │ │ │ ├── mempool.cpython-38.pyc │ │ │ ├── network.cpython-38.pyc │ │ │ ├── script.cpython-38.pyc │ │ │ ├── database.cpython-38.pyc │ │ │ ├── database.cpython-39.pyc │ │ │ ├── network1.cpython-38.pyc │ │ │ ├── network1.cpython-39.pyc │ │ │ ├── FieldElement.cpython-38.pyc │ │ │ ├── FieldElement.cpython-39.pyc │ │ │ ├── bloomfilter.cpython-38.pyc │ │ │ ├── merkleblock.cpython-38.pyc │ │ │ ├── sendTransfer.cpython-38.pyc │ │ │ ├── EllepticCurve.cpython-310.pyc │ │ │ ├── EllepticCurve.cpython-38.pyc │ │ │ └── EllepticCurve.cpython-39.pyc │ │ ├── test.py │ │ ├── Sha256Field.py │ │ ├── op.py │ │ ├── FieldElement.py │ │ ├── Point.py │ │ └── EllepticCurve.py │ │ ├── __pycache__ │ │ ├── Tx.cpython-310.pyc │ │ ├── Tx.cpython-39.pyc │ │ ├── Script.cpython-39.pyc │ │ ├── block.cpython-310.pyc │ │ ├── block.cpython-39.pyc │ │ ├── Script.cpython-310.pyc │ │ ├── blockheader.cpython-39.pyc │ │ └── blockheader.cpython-310.pyc │ │ ├── network │ │ ├── __pycache__ │ │ │ ├── network.cpython-39.pyc │ │ │ ├── connection.cpython-39.pyc │ │ │ └── syncManager.cpython-39.pyc │ │ ├── connection.py │ │ ├── network.py │ │ └── syncManager.py │ │ ├── database │ │ ├── __pycache__ │ │ │ ├── database.cpython-310.pyc │ │ │ └── database.cpython-39.pyc │ │ └── database.py │ │ ├── block.py │ │ ├── blockheader.py │ │ ├── Script.py │ │ ├── Tx.py │ │ └── blockchain.py ├── Frontend │ ├── static │ │ ├── images │ │ │ ├── fav.PNG │ │ │ ├── wal5.jpg │ │ │ ├── cover.jpg │ │ │ ├── search.png │ │ │ └── CODIES ALERT.png │ │ └── css │ │ │ └── style.css │ ├── __pycache__ │ │ ├── run.cpython-39.pyc │ │ └── run.cpython-310.pyc │ ├── templates │ │ ├── home.html │ │ ├── transactions.html │ │ ├── wallet.html │ │ ├── block.html │ │ ├── mempool.html │ │ ├── base.html │ │ ├── address.html │ │ ├── txDetail.html │ │ └── blockDetails.html │ └── run.py └── client │ ├── __pycache__ │ ├── sendBTC.cpython-39.pyc │ ├── sendBTC.cpython-310.pyc │ └── autoBroadcastTX.cpython-39.pyc │ ├── autoBroadcastTX.py │ ├── account.py │ └── sendBTC.py ├── data ├── node └── account ├── config.ini ├── requirements.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .env -------------------------------------------------------------------------------- /Blockchain/Backend/util/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__init__.py.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/node: -------------------------------------------------------------------------------- 1 | [8888, 5555, 3333, 1111, 4444, 6666, 2222, 7777] -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | host = 127.0.0.1 3 | 4 | [MINER] 5 | port = 8888 6 | simulateBTC = True 7 | 8 | [Webhost] 9 | port = 5900 -------------------------------------------------------------------------------- /Blockchain/Frontend/static/images/fav.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/static/images/fav.PNG -------------------------------------------------------------------------------- /Blockchain/Frontend/static/images/wal5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/static/images/wal5.jpg -------------------------------------------------------------------------------- /Blockchain/Frontend/static/images/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/static/images/cover.jpg -------------------------------------------------------------------------------- /Blockchain/Frontend/static/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/static/images/search.png -------------------------------------------------------------------------------- /Blockchain/Frontend/__pycache__/run.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/__pycache__/run.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Frontend/static/images/CODIES ALERT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/static/images/CODIES ALERT.png -------------------------------------------------------------------------------- /Blockchain/Frontend/__pycache__/run.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Frontend/__pycache__/run.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/client/__pycache__/sendBTC.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/client/__pycache__/sendBTC.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/Tx.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/Tx.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/Tx.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/Tx.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/util/__pycache__/util.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/util/__pycache__/util.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/client/__pycache__/sendBTC.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/client/__pycache__/sendBTC.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/Script.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/Script.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/block.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/block.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/block.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/block.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/util/__pycache__/util.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/util/__pycache__/util.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/Script.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/Script.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/util/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/util/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/util/__pycache__/__init__.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/util/__pycache__/__init__.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/client/__pycache__/autoBroadcastTX.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/client/__pycache__/autoBroadcastTX.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/blockheader.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/blockheader.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/__pycache__/blockheader.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/__pycache__/blockheader.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/Tx.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/Tx.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/__pycache__/network.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/network/__pycache__/network.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/Block.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/Block.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/Point.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/Point.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/Point.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/Point.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/Tx1.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/Tx1.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/op.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/database/__pycache__/database.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/database/__pycache__/database.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/database/__pycache__/database.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/database/__pycache__/database.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/__pycache__/connection.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/network/__pycache__/connection.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/__pycache__/syncManager.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/network/__pycache__/syncManager.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/helper.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/helper.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/helper.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/helper.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/mempool.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/mempool.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/network.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/network.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/script.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/script.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/database.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/database.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/database.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/database.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/network1.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/network1.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/network1.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/network1.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/FieldElement.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/FieldElement.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/FieldElement.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/FieldElement.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/bloomfilter.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/bloomfilter.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/merkleblock.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/merkleblock.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/sendTransfer.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/sendTransfer.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-310.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-38.pyc -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anni1236012/Advanced-Blockchain-Course---Python/HEAD/Blockchain/Backend/core/EllepticCurve/__pycache__/EllepticCurve.cpython-39.pyc -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Home {% endblock %} {% block content 2 | %} 3 |
4 |

Codies Alert

5 |

Programming Bitcoin from Scratch in Python

6 |
7 | {% endblock%} 8 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/test.py: -------------------------------------------------------------------------------- 1 | from FieldElement import FieldElement 2 | from Point import Point 3 | a = FieldElement(num = 0, prime = 223) 4 | b = FieldElement(num = 7, prime = 223) 5 | x = FieldElement(num = 192, prime = 223) 6 | y = FieldElement(num = 105, prime = 223) 7 | 8 | p1 = Point(x, y, a, b) 9 | print(p1) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2021.10.8 2 | charset-normalizer==2.0.7 3 | click==8.0.3 4 | colorama==0.4.4 5 | Flask==2.0.2 6 | Flask-QRcode==3.0.0 7 | idna==3.3 8 | itsdangerous==2.0.1 9 | Jinja2==3.0.2 10 | MarkupSafe==2.0.1 11 | Pillow==8.4.0 12 | pycryptodome==3.11.0 13 | qrcode==7.3.1 14 | requests==2.26.0 15 | urllib3==1.26.7 16 | Werkzeug==2.0.2 17 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/Sha256Field.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from FieldElement import FieldElement 7 | from Point import Point 8 | 9 | P = 2 ** 256 - 2 ** 32 - 977 10 | 11 | 12 | class Sha256Field(FieldElement): 13 | def __init__(self, num, prime=None): 14 | super().__init__(num=num, prime=P) 15 | 16 | def __repr__(self): 17 | return "{:x}".format(self.num).zfill(64) 18 | -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/transactions.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} UTXOs {% endblock %} {% block 2 | content%} 3 |
4 |

Unspent Transactions (UTXO)

5 |
6 |
Transaction ID
7 |
8 | 9 | {% for Tx in allTransactions %} 10 | 11 |
12 |
{{ Tx }}
13 |
14 |
15 | {% endfor %} 16 |
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/wallet.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Home {% endblock %} {% block content 2 | %} 3 |
4 |

Send Bitcoin

5 | 6 |
7 |
8 |
9 |
10 |

11 |
12 |

13 | {{ message }}
14 | 15 |
16 |
17 | {% endblock%} 18 | -------------------------------------------------------------------------------- /Blockchain/client/autoBroadcastTX.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import random 4 | from Blockchain.Backend.core.database.database import AccountDB 5 | 6 | fromAccount = "1LYgXwYXw16GJXgDwHV7aCNijnQWYEdc1C" 7 | 8 | """ Read all the accounts """ 9 | AllAccounts = AccountDB().read() 10 | 11 | def autoBroadcast(): 12 | while True: 13 | for account in AllAccounts: 14 | if account["PublicAddress"] != fromAccount: 15 | paras = {"fromAddress": fromAccount, 16 | "toAddress": account["PublicAddress"], 17 | "Amount": random.randint(1,35)} 18 | 19 | res = requests.post(url ="http://localhost:5900/wallet", data = paras) 20 | time.sleep(3) -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/block.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Block {% endblock %} {% block 2 | content %} 3 |
4 |

Latest Blocks

5 |
6 |
Block Height
7 |
Block Header
8 |
Transactions
9 |
Size (Bytes)
10 |
11 | {% for block in blocks[::-1] %} 12 | 16 |
17 |
{{block["Height"]}}
18 |
19 | {{block["BlockHeader"]['blockHash']}} 20 |
21 |
{{block["Txcount"]}}
22 |
{{block["Blocksize"]}}
23 |
24 |
25 | {% endfor %} 26 |
27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/mempool.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Mempool {% endblock %} 2 | {% block content%} 3 | 4 |
5 | {% if not Txs %} 6 |

15 | Memory Pool (Unconfirmed Transactions) 16 |

17 |

26 | 0 Transactions to Mine 27 | 28 | {% else %} 29 |

Memory Pool (Unconfirmed Transactions)

30 |

31 | {{ Txs|length }} Transactions 32 |

33 | 34 | 35 |
36 |
Transaction ID
37 |
Amount
38 |
39 | 40 | 41 | {% for TxId in Txs|reverse %} 42 | 43 |
44 |
{{ TxId }}
45 |
{{ Txs[TxId][1] }} BTC
46 |
47 |
48 | 49 | {% endfor %} 50 | {% endif %} 51 |
52 | {% endblock %} 53 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/connection.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from Blockchain.Backend.core.network.network import NetworkEnvelope, FINISHED_SENDING 3 | 4 | class Node: 5 | def __init__(self, host, port): 6 | self.host = host 7 | self.port = port 8 | self.ADDR = (self.host, self.port) 9 | 10 | """ Start the Server and bind it to a particular port Number """ 11 | def startServer(self): 12 | self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | self.server.bind(self.ADDR) 14 | self.server.listen() 15 | 16 | def connect(self, port, bindPort = None): 17 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 18 | 19 | if bindPort: 20 | self.socket.bind((self.host, port)) 21 | 22 | self.socket.connect((self.host, self.port)) 23 | return self.socket 24 | 25 | def acceptConnection(self): 26 | self.conn, self.addr = self.server.accept() 27 | self.stream = self.conn.makefile('rb', None) 28 | return self.conn, self.addr 29 | 30 | def closeConnection(self): 31 | self.socket.close() 32 | 33 | def send(self, message): 34 | envelope = NetworkEnvelope(message.command, message.serialize()) 35 | self.socket.sendall(envelope.serialize()) 36 | 37 | def read(self): 38 | envelope = NetworkEnvelope.parse(self.stream) 39 | return envelope -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% block title %} {% endblock %} 11 | 12 | 13 |
14 | 15 | 22 | 23 |
24 |
25 | 31 | 32 |
33 |
34 | {% block content%} {% endblock %} 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/database/database.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | import os 7 | import json 8 | 9 | 10 | class BaseDB: 11 | def __init__(self): 12 | self.basepath = "data" 13 | self.filepath = "/".join((self.basepath, self.filename)) 14 | 15 | def read(self): 16 | if not os.path.exists(self.filepath): 17 | print(f"File {self.filepath} not available") 18 | return False 19 | 20 | with open(self.filepath, "r") as file: 21 | raw = file.readline() 22 | 23 | if len(raw) > 0: 24 | data = json.loads(raw) 25 | else: 26 | data = [] 27 | return data 28 | 29 | def update(self, data): 30 | with open(self.filepath,'w+') as f: 31 | f.write(json.dumps(data)) 32 | return True 33 | 34 | def write(self, item): 35 | data = self.read() 36 | if data: 37 | data = data + item 38 | else: 39 | data = item 40 | 41 | with open(self.filepath, "w+") as file: 42 | file.write(json.dumps(data)) 43 | 44 | 45 | class BlockchainDB(BaseDB): 46 | def __init__(self): 47 | self.filename = "blockchain" 48 | super().__init__() 49 | 50 | def lastBlock(self): 51 | data = self.read() 52 | 53 | if data: 54 | return data[-1] 55 | 56 | 57 | class AccountDB(BaseDB): 58 | def __init__(self): 59 | self.filename = "account" 60 | super().__init__() 61 | 62 | 63 | class NodeDB(BaseDB): 64 | def __init__(self): 65 | self.filename = "node" 66 | super().__init__() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Blockchain Course Python 2 | In this course, you will learn how to create your very own Blockchain from scratch with the Blockchain Explorer in python. 3 | 4 | In contrast to other courses, you will learn how to code the peer-to-peer network and the entire blockchain from scratch. 5 | One of the most crucial components of a blockchain is a peer network, but in most courses it is not implemented, and in those that do, third-party libraries or services are used to imitate p2p behavior. 6 | But, In this course you will create everything in this course from scratch, including the P2P Network. 7 | 8 | ## [Complete Udemy Course](https://www.udemy.com/course/advanced-blockchain-course-python/?referralCode=DEAE60079BFB4387226B) 9 | 10 | ![image](https://user-images.githubusercontent.com/86418669/179878712-15988107-e468-40cf-8aa0-ca8cc4ade30b.png) 11 | 12 | 13 | ![image](https://user-images.githubusercontent.com/86418669/179878631-d2f3dde8-56f4-46a3-acb5-3d07183b7afa.png) 14 | 15 | 16 | # Steps to clone and run it locally 17 | **Make sure your python version is Python 3.10.12.** 18 | 1. git clone https://github.com/anni1236012/Advanced-Blockchain-Course---Python Bitcoin 19 | 2. cd Bitcoin 20 | 3. pip install -r requirements.txt 21 | 4. **Windows** user search sys.path.append("/Users/Vmaha/Desktop/Bitcoin") and replace all it with your system path. 22 | **On Linux machine**, make sure you copy the complete path from /home/username/Desktop/Bitcoin 23 | 5. Open VSCODE and go to blockchain.py file inside the core directory and run it. If you get any error related to config file then try to run it in debug mode. Click on run -> Start debugging. You don't have to set the breakpoint. Sometimes config.ini does not work in batch mode. Keep that in mind. 24 | 6. Goto http://127.0.0.1:5900/ and your Blockchain is up and running now. 25 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/op.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts shouldn't be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.util.util import hash160 7 | from Blockchain.Backend.core.EllepticCurve.EllepticCurve import Sha256Point, Signature 8 | 9 | 10 | def op_dup(stack): 11 | 12 | if len(stack) < 1: 13 | return False 14 | stack.append(stack[-1]) 15 | 16 | return True 17 | 18 | 19 | def op_hash160(stack): 20 | if len(stack) < 1: 21 | return False 22 | element = stack.pop() 23 | h160 = hash160(element) 24 | stack.append(h160) 25 | return True 26 | 27 | 28 | def op_equal(stack): 29 | if len(stack) < 2: 30 | return False 31 | 32 | element1 = stack.pop() 33 | element2 = stack.pop() 34 | 35 | if element1 == element2: 36 | stack.append(1) 37 | else: 38 | stack.append(0) 39 | 40 | return True 41 | 42 | 43 | def op_verify(stack): 44 | if len(stack) < 1: 45 | False 46 | element = stack.pop() 47 | 48 | if element == 0: 49 | return False 50 | 51 | return True 52 | 53 | 54 | def op_equalverify(stack): 55 | return op_equal(stack) and op_verify(stack) 56 | 57 | 58 | def op_checksig(stack, z): 59 | if len(stack) < 1: 60 | return False 61 | 62 | sec_pubkey = stack.pop() 63 | der_signature = stack.pop()[:-1] 64 | 65 | try: 66 | point = Sha256Point.parse(sec_pubkey) 67 | sig = Signature.parse(der_signature) 68 | except Exception as e: 69 | return False 70 | 71 | if point.verify(z, sig): 72 | stack.append(1) 73 | return True 74 | else: 75 | stack.append(0) 76 | return False 77 | 78 | 79 | OP_CODE_FUNCTION = {118: op_dup, 136: op_equalverify, 169: op_hash160, 172: op_checksig} 80 | -------------------------------------------------------------------------------- /data/account: -------------------------------------------------------------------------------- 1 | [{"privateKey": 59024195091230105596801455306913435815673319996141880726735464739248197324364, "PublicAddress": "1LYgXwYXw16GJXgDwHV7aCNijnQWYEdc1C"}, {"privateKey": 95629386529787536068877381263626447076817289100272904234712298232786818210835, "PublicAddress": "1KNkLzy9wJa4cwmbbp82mNyhaYkjctuA7w"}, {"privateKey": 14241803319693785302977433572010542161600562356689826590184620410614411018040, "PublicAddress": "12nVUXEhvxwKPR148ERyxPnbXUinZ8KWx5"}, {"privateKey": 74241465003919167167847383132396408631376591346006916067241902760511164402519, "PublicAddress": "1NkCS35KFHwHjooYFUQqp59XSHHeHXaJhk"}, {"privateKey": 38218690195996144431871804694688923599868949863407644696050380779402460958123, "PublicAddress": "19mxW6bkSHjFxWhyvMf8myNaKHyNsgzXzK"}, {"privateKey": 81262123146290171349872215710868504269440109707743879790632633275501955706758, "PublicAddress": "1NNHt95DDM2hxVEaZEzz8nxsd2ufMabUt9"}, {"privateKey": 71217525177794417187056295406046535603694695538332938113971180618583252878229, "PublicAddress": "1F6ACuLodwAnef4PWjL8ntHx7H3xbUUmBN"}, {"privateKey": 28730334684357338934693169302804979518093614747550649653496067570289177897715, "PublicAddress": "1P3kmSjGwUqD9CSt849LHAAFrfRDdQ2gQv"}, {"privateKey": 72258023819865091775793089729765997106222985841350894556948614850721698042275, "PublicAddress": "16BTHfWTNwxeYVFWZhof8TkdvskpeLHXvz"}, {"privateKey": 25945709481872419887433567964938529387186718116012372145677792861917095760213, "PublicAddress": "17Kwunqq3rk7HTE9xXkFiJVT32ymoyDajU"}, {"privateKey": 38607915920392535632449799027979299388853754541286758130685976411702555930985, "PublicAddress": "12oDSLTiTn4EGNsFnbANrmGH1b82vesEK5"}, {"privateKey": 62318752128417999176878686136545132279513714012659686273987983647006233083166, "PublicAddress": "1JUGmgrsfMqDKyzkGT11UqHxhZLVQXFTcW"}, {"privateKey": 32115375488548095565142837530832008750075729634624907360231874439696032787507, "PublicAddress": "1QBTKzFdX7kMLtnywu7T96SNQkJpmWEsaQ"}, {"privateKey": 1209447159948850843915439633852132228452657164141103385206797147461057112669, "PublicAddress": "19aVUrkxZsamD4BExfjNNUzB2e8wKXLvoo"}, {"privateKey": 30241364820943766792020920412278054548911218727970360423801389436863038916232, "PublicAddress": "14X4suduK3graFvMqGUs2MSpGnHVVQtnSF"}, {"privateKey": 48923654186398080735393029485035937769703761542088117963121102982169832783053, "PublicAddress": "15TFGsvgTh4we2T4Q7nxMy3YP3TcN14FoJ"}, {"privateKey": 51599184197646827973329231632463425670065926277052075168179786506244702458639, "PublicAddress": "1NkNQwmnVkchbzEQK3EmdHHerghmQRePHg"}] -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/address.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Account {% endblock %} {% block 2 | content%} 3 | 4 |
5 |
6 |

Address

7 |

{{ publicAddress }}

8 |
9 | 10 |
11 | 12 |
13 |
14 |
TOTAL TX COUNT
15 |
TOTAL UNSPENT
16 |
17 |
18 |
{{ Txs|length }}
19 |
{{ amount/100000000 }} BTC
20 |
21 |
22 | 23 |

Transactions

24 | {% for blk in Txs %} 25 |
26 |
27 |

28 | 29 | {{ blk['TxId'] }} 30 | 31 |

32 |

Inputs

33 | {% for tx_in in blk['tx_ins'] %} 34 | 35 | 36 | {% if tx_in['prev_tx'].hex() 37 | =='0000000000000000000000000000000000000000000000000000000000000000' %} 38 |
#0 Coinbase
39 | {% else %} 40 | 45 | {%endif %} {% endfor %} 46 |
47 | 48 |
49 |

Outputs

50 | {% set TotaAmount = 0 %} {% for tx_out in blk['tx_outs'] %} 51 | 52 |
53 | {% set h160hash = tx_out['script_pubkey']['cmds'][2] %} {% set newAddr = 54 | main_prefix + h160hash %} {% set checksum = 55 | sha256(sha256(newAddr).digest()).digest()[:4] %} {% set newAddr =newAddr + 56 | checksum %} {% set pubAddress = encode_base58(newAddr) %} {% set 57 | TotaAmount = TotaAmount + tx_out['amount'] %} {% if 58 | (tx_out['amount']%100000000) == 0 %} {% set amount = 59 | (tx_out['amount']/100000000)|int %} {% else %} {% set amount = 60 | (tx_out['amount']/100000000) %} {% endif %} 61 | 62 | #{{ loop.index0 }} {{ pubAddress }} : {{ amount }} BTC 64 |
65 | {% endfor %} 66 |
67 |
68 | {% endfor %} {%endblock%} 69 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/block.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.core.blockheader import BlockHeader 7 | from Blockchain.Backend.core.Tx import Tx 8 | from Blockchain.Backend.util.util import (little_endian_to_int, int_to_little_endian, encode_varint, read_varint) 9 | class Block: 10 | """ 11 | Block is a storage containter that stores transactions 12 | """ 13 | command = b'block' 14 | 15 | def __init__(self, Height, Blocksize, BlockHeader, TxCount, Txs): 16 | self.Height = Height 17 | self.Blocksize = Blocksize 18 | self.BlockHeader = BlockHeader 19 | self.Txcount = TxCount 20 | self.Txs = Txs 21 | 22 | @classmethod 23 | def parse(cls, s): 24 | Height = little_endian_to_int(s.read(4)) 25 | BlockSize = little_endian_to_int(s.read(4)) 26 | blockHeader = BlockHeader.parse(s) 27 | numTxs = read_varint(s) 28 | 29 | Txs = [] 30 | 31 | for _ in range(numTxs): 32 | Txs.append(Tx.parse(s)) 33 | 34 | return cls(Height, BlockSize, blockHeader, numTxs, Txs) 35 | 36 | def serialize(self): 37 | result = int_to_little_endian(self.Height, 4) 38 | result += int_to_little_endian(self.Blocksize, 4) 39 | result += self.BlockHeader.serialize() 40 | result += encode_varint(len(self.Txs)) 41 | 42 | for tx in self.Txs: 43 | result += tx.serialize() 44 | 45 | return result 46 | 47 | @classmethod 48 | def to_obj(cls, lastblock): 49 | block = BlockHeader(lastblock['BlockHeader']['version'], 50 | bytes.fromhex(lastblock['BlockHeader']['prevBlockHash']), 51 | bytes.fromhex(lastblock['BlockHeader']['merkleRoot']), 52 | lastblock['BlockHeader']['timestamp'], 53 | bytes.fromhex(lastblock['BlockHeader']['bits'])) 54 | 55 | block.nonce = int_to_little_endian(lastblock['BlockHeader']['nonce'], 4) 56 | 57 | Transactions = [] 58 | for tx in lastblock['Txs']: 59 | Transactions.append(Tx.to_obj(tx)) 60 | 61 | block.BlockHash = bytes.fromhex(lastblock['BlockHeader']['blockHash']) 62 | return cls(lastblock['Height'], lastblock['Blocksize'], block, len(Transactions), Transactions) 63 | 64 | def to_dict(self): 65 | dt = self.__dict__ 66 | self.BlockHeader = self.BlockHeader.to_dict() 67 | return dt 68 | -------------------------------------------------------------------------------- /Blockchain/client/account.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | import sys 7 | 8 | sys.path.append("/Users/Vmaha/Desktop/Bitcoin") 9 | from Blockchain.Backend.core.EllepticCurve.EllepticCurve import Sha256Point 10 | from Blockchain.Backend.util.util import hash160, hash256 11 | from Blockchain.Backend.core.database.database import AccountDB 12 | import secrets 13 | 14 | 15 | class account: 16 | def createKeys(self): 17 | """Secp256k1 Curve Generator Points""" 18 | Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 19 | Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 20 | 21 | """Create an Instance of Class Sha256Point""" 22 | G = Sha256Point(Gx, Gy) 23 | 24 | """ Generate Secure Private Key """ 25 | self.privateKey = secrets.randbits(256) 26 | 27 | """ 28 | # Multiply Private Key with Generator Point 29 | # Returns X-coordinate and Y-Coordinate 30 | """ 31 | unCompressesPublicKey = self.privateKey * G 32 | xpoint = unCompressesPublicKey.x 33 | ypoint = unCompressesPublicKey.y 34 | 35 | """ Address Prefix for Odd or even value of YPoint """ 36 | if ypoint.num % 2 == 0: 37 | compressesKey = b"\x02" + xpoint.num.to_bytes(32, "big") 38 | else: 39 | compressesKey = b"\x03" + xpoint.num.to_bytes(32, "big") 40 | 41 | """ RIPEMD160 Hashing Algorithm returns the hash of Compressed Public Key""" 42 | 43 | hsh160 = hash160(compressesKey) 44 | 45 | """Prefix for Mainnet""" 46 | main_prefix = b"\x00" 47 | 48 | newAddr = main_prefix + hsh160 49 | 50 | """Checksum""" 51 | checksum = hash256(newAddr)[:4] 52 | 53 | newAddr = newAddr + checksum 54 | 55 | BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 56 | 57 | """Counter to find Leading zeros """ 58 | count = 0 59 | for c in newAddr: 60 | if c == 0: 61 | count += 1 62 | else: 63 | break 64 | """ Convert to Numeric from Bytes """ 65 | num = int.from_bytes(newAddr, "big") 66 | prefix = "1" * count 67 | 68 | result = "" 69 | 70 | """ BASE58 Encoding """ 71 | while num > 0: 72 | num, mod = divmod(num, 58) 73 | result = BASE58_ALPHABET[mod] + result 74 | 75 | self.PublicAddress = prefix + result 76 | 77 | print(f"Private Key {self.privateKey}") 78 | print(f"Public Key {self.PublicAddress}") 79 | print(f"Xpoint {xpoint} \n Ypoint {ypoint}") 80 | 81 | 82 | if __name__ == "__main__": 83 | acct = account() 84 | acct.createKeys() 85 | AccountDB().write([acct.__dict__]) 86 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/FieldElement.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts shouldn't be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | 7 | 8 | class FieldElement: 9 | def __init__(self, num, prime): 10 | if num >= prime or num < 0: 11 | error = "Num {} not in field range 0 to {}".format(num, prime - 1) 12 | raise ValueError(error) 13 | self.num = num 14 | self.prime = prime 15 | 16 | def __repr__(self): 17 | return "FieldElement_{}({})".format(self.prime, self.num) 18 | 19 | def __eq__(self, other): 20 | if other is None: 21 | return False 22 | return self.num == other.num and self.prime == other.prime 23 | 24 | def __ne__(self, other): 25 | # this should be the inverse of the == operator 26 | return not (self == other) 27 | 28 | def __add__(self, other): 29 | if self.prime != other.prime: 30 | raise TypeError("Cannot add two numbers in different Fields") 31 | # self.num and other.num are the actual values 32 | # self.prime is what we need to mod against 33 | num = (self.num + other.num) % self.prime 34 | # We return an element of the same class 35 | return self.__class__(num, self.prime) 36 | 37 | def __sub__(self, other): 38 | if self.prime != other.prime: 39 | raise TypeError("Cannot subtract two numbers in different Fields") 40 | # self.num and other.num are the actual values 41 | # self.prime is what we need to mod against 42 | num = (self.num - other.num) % self.prime 43 | # We return an element of the same class 44 | return self.__class__(num, self.prime) 45 | 46 | def __mul__(self, other): 47 | if self.prime != other.prime: 48 | raise TypeError("Cannot multiply two numbers in different Fields") 49 | # self.num and other.num are the actual values 50 | # self.prime is what we need to mod against 51 | num = (self.num * other.num) % self.prime 52 | # We return an element of the same class 53 | return self.__class__(num, self.prime) 54 | 55 | def __pow__(self, exponent): 56 | n = exponent % (self.prime - 1) 57 | num = pow(self.num, n, self.prime) 58 | return self.__class__(num, self.prime) 59 | 60 | def __truediv__(self, other): 61 | if self.prime != other.prime: 62 | raise TypeError("Cannot divide two numbers in different Fields") 63 | # self.num and other.num are the actual values 64 | # self.prime is what we need to mod against 65 | # use fermat's little theorem: 66 | # self.num**(p-1) % p == 1 67 | # this means: 68 | # 1/n == pow(n, p-2, p) 69 | num = (self.num * pow(other.num, self.prime - 2, self.prime)) % self.prime 70 | # We return an element of the same class 71 | return self.__class__(num, self.prime) 72 | 73 | def __rmul__(self, coefficient): 74 | num = (self.num * coefficient) % self.prime 75 | return self.__class__(num=num, prime=self.prime) 76 | -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/txDetail.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Codies Alert {% endblock %} {% block 2 | content%} 3 |

Transaction

4 | 5 |
6 |
7 |

{{Tx['TxId']}}

8 | {% if not Unconfirmed %} 9 |
Block Height
10 | {% endif %} 11 |
Status
12 |
Transaction Fee
13 |
Transaction Size
14 |
Version
15 |
Locktime
16 |
ETA
17 |
18 | 19 |
20 |

_

21 | {% if not Unconfirmed %} 22 | 26 |
{{ block['Height'] }}
27 |
28 | {% endif %} {% if Unconfirmed %} 29 |
Unconfirmed
30 | {% else %} 31 |
Confirmed
32 | {% endif %} 33 |
1
34 |
120
35 |
{{Tx['version']}}
36 |
{{Tx['locktime']}}
37 |
40 Seconds
38 |
39 |
40 | 41 |

Transactions

42 | 43 |
44 |
45 |

Inputs

46 |

47 | 48 | {{ Tx['TxId'] }} 49 | 50 |

51 | {% for tx_in in Tx['tx_ins'] %} {% if 52 | tx_in['prev_tx']=='0000000000000000000000000000000000000000000000000000000000000000' 53 | %} 54 |
#0 Coinbase
55 | {% else %} 56 | 61 | {% endif %} {% endfor %} 62 |
63 | 64 |
65 |

Outputs

66 | {% for tx_out in Tx['tx_outs'] %} 67 |
68 | {% set h160hash = bytes.fromhex(tx_out['script_pubkey']['cmds'][2]) %} {% 69 | set newAddr = main_prefix + h160hash %} {% set checksum = 70 | sha256(sha256(newAddr).digest()).digest()[:4] %} {% set newAddr =newAddr + 71 | checksum %} {% set pubAddress = encode_base58(newAddr) %} {% if 72 | (tx_out['amount']%100000000) == 0 %} {% set amount = 73 | (tx_out['amount']/100000000)|round()|int %} {% else %} {% set amount = 74 | tx_out['amount']/100000000 %} {% endif %} 75 | 76 | 77 | #{{ loop.index0 }} {{ pubAddress }} :{{ amount }} BTC 78 | 79 |
80 | {% endfor %} 81 |
82 |
83 | 84 | {%endblock%} 85 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/network.py: -------------------------------------------------------------------------------- 1 | from base64 import encode 2 | from io import BytesIO 3 | from Blockchain.Backend.util.util import (int_to_little_endian, little_endian_to_int, hash256, 4 | encode_varint, read_varint) 5 | 6 | NETWORK_MAGIC = b'\xf9\xbe\xb4\xd9' 7 | FINISHED_SENDING =b'\x0a\x11\x09\x07' 8 | class NetworkEnvelope: 9 | def __init__(self, command, payload): 10 | self.command = command 11 | self.payload = payload 12 | self.magic = NETWORK_MAGIC 13 | 14 | @classmethod 15 | def parse(cls, s): 16 | magic = s.read(4) 17 | 18 | if magic != NETWORK_MAGIC: 19 | raise RuntimeError(f"Magic is not right {magic.hex()} vs {NETWORK_MAGIC.hex()}") 20 | 21 | command = s.read(12) 22 | command = command.strip(b'\x00') 23 | payloadLen = little_endian_to_int(s.read(4)) 24 | checksum = s.read(4) 25 | payload = s.read(payloadLen) 26 | calculatedChecksum = hash256(payload)[:4] 27 | 28 | if calculatedChecksum != checksum: 29 | raise IOError("Checksum does not match") 30 | 31 | return cls(command, payload) 32 | 33 | def serialize(self): 34 | result = self.magic 35 | result += self.command + b'\x00' * (12 - len(self.command)) 36 | result += int_to_little_endian(len(self.payload), 4) 37 | result += hash256(self.payload)[:4] 38 | result += self.payload 39 | return result 40 | 41 | def stream(self): 42 | return BytesIO(self.payload) 43 | 44 | class requestBlock: 45 | command = b'requestBlock' 46 | 47 | def __init__(self, startBlock = None, endBlock = None) -> None: 48 | if startBlock is None: 49 | raise RuntimeError("Starting Block cannot be None") 50 | else: 51 | self.startBlock = startBlock 52 | 53 | if endBlock is None: 54 | self.endBlock = b'\x00' * 32 55 | else: 56 | self.endBlock = endBlock 57 | 58 | @classmethod 59 | def parse(cls, stream): 60 | startBlock = stream.read(32) 61 | endBlock = stream.read(32) 62 | return startBlock, endBlock 63 | 64 | def serialize(self): 65 | result = self.startBlock 66 | result += self.endBlock 67 | return result 68 | 69 | class portlist: 70 | command = b'portlist' 71 | def __init__(self, ports = None): 72 | self.ports = ports 73 | 74 | @classmethod 75 | def parse(cls, s): 76 | ports = [] 77 | length = read_varint(s) 78 | 79 | for _ in range(length): 80 | port = little_endian_to_int(s.read(4)) 81 | ports.append(port) 82 | 83 | return ports 84 | 85 | def serialize(self): 86 | result = encode_varint(len(self.ports)) 87 | 88 | for port in self.ports: 89 | result += int_to_little_endian(port, 4) 90 | 91 | return result 92 | 93 | class FinishedSending: 94 | command = b'Finished' 95 | 96 | @classmethod 97 | def parse(cls, s): 98 | magic = s.read(4) 99 | 100 | if magic == FINISHED_SENDING: 101 | return "Finished" 102 | 103 | def serialize(self): 104 | result = FINISHED_SENDING 105 | return result -------------------------------------------------------------------------------- /Blockchain/Frontend/templates/blockDetails.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block title %} Codies Alert {% endblock %} {% block 2 | content%} 3 | 4 |

BLOCK #{{ block['Height']}}

5 | 6 |
7 |
8 |

{{block['BlockHeader']['blockHash']}}

9 | 10 |
Previous Block Hash
11 |
Total Transactions
12 |
Block Size
13 |
Merkle Root
14 |
Target (Bits)
15 |
Nonce
16 |
Timestamp
17 |
18 | 19 |
20 |

_

21 | 22 | {% if (block['Height']) == 0 %} 23 |
24 | {{block['BlockHeader']['prevBlockHash']}} (GENESIS BLOCK) 25 |
26 | {% else %} 27 | 33 | {% endif %} 34 | 35 |
{{block['Txcount']}}
36 |
{{ block['Blocksize']}}
37 |
38 | {{block['BlockHeader']['merkleRoot']}} 39 |
40 |
{{block['BlockHeader']['bits']}}
41 |
{{block['BlockHeader']['nonce']}}
42 |
43 | {{block['BlockHeader']['timestamp']}} 44 |
45 |
46 |
47 | 48 |

Transactions

49 | {% for blk in block['Txs'] %} 50 |
51 |
52 |

53 | 54 | {{ blk['TxId'] }} 55 | 56 |

57 |

Inputs

58 | {% for tx_in in blk['tx_ins'] %} 59 | 60 | 61 | {% if 62 | tx_in['prev_tx']=='0000000000000000000000000000000000000000000000000000000000000000' 63 | %} 64 |
#0 Coinbase
65 | {% else %} 66 | 71 | {%endif %} {% endfor %} 72 |
73 | 74 |
75 |

Outputs

76 | {% set TotaAmount = 0 %} {% for tx_out in blk['tx_outs'] %} 77 | 78 |
79 | {% set h160hash = bytes.fromhex(tx_out['script_pubkey']['cmds'][2]) %} {% 80 | set newAddr = main_prefix + h160hash %} {% set checksum = 81 | sha256(sha256(newAddr).digest()).digest()[:4] %} {% set newAddr =newAddr + 82 | checksum %} {% set pubAddress = encode_base58(newAddr) %} {% set 83 | TotaAmount = TotaAmount + tx_out['amount'] %} {% if 84 | (tx_out['amount']%100000000) == 0 %} {% set amount = 85 | (tx_out['amount']/100000000)|int %} {% else %} {% set amount = 86 | (tx_out['amount']/100000000) %} {% endif %} 87 | 88 | #{{ loop.index0 }} {{ pubAddress }} : {{ amount }} BTC 90 |
91 | {% endfor %} 92 |
93 |
94 | {% endfor %} {%endblock%} 95 | -------------------------------------------------------------------------------- /Blockchain/client/sendBTC.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.util.util import decode_base58 7 | from Blockchain.Backend.core.Script import Script 8 | from Blockchain.Backend.core.Tx import TxIn, TxOut, Tx 9 | from Blockchain.Backend.core.database.database import AccountDB 10 | from Blockchain.Backend.core.EllepticCurve.EllepticCurve import PrivateKey 11 | import time 12 | import random 13 | class SendBTC: 14 | def __init__(self, fromAccount, toAccount, Amount, UTXOS): 15 | self.COIN = 100000000 16 | self.FromPublicAddress = fromAccount 17 | self.toAccount = toAccount 18 | self.Amount = Amount * self.COIN 19 | self.utxos = UTXOS 20 | 21 | def scriptPubKey(self, PublicAddress): 22 | h160 = decode_base58(PublicAddress) 23 | script_pubkey = Script().p2pkh_script(h160) 24 | return script_pubkey 25 | 26 | def getPrivateKey(self): 27 | AllAccounts = AccountDB().read() 28 | for account in AllAccounts: 29 | if account["PublicAddress"] == self.FromPublicAddress: 30 | return account["privateKey"] 31 | 32 | def prepareTxIn(self): 33 | TxIns = [] 34 | self.Total = 0 35 | 36 | """Convert Public Address into Public Hash to find tx_outs that are locked to this hash""" 37 | 38 | self.From_address_script_pubkey = self.scriptPubKey(self.FromPublicAddress) 39 | self.fromPubKeyHash = self.From_address_script_pubkey.cmds[2] 40 | 41 | newutxos = {} 42 | 43 | try: 44 | while len(newutxos) < 1: 45 | newutxos = dict(self.utxos) 46 | time.sleep(2) 47 | except Exception as e: 48 | print(f"Error in converting the Managed Dict to Normal Dict") 49 | 50 | for index, Txbyte in enumerate(newutxos): 51 | if index > random.randint(1, 30): 52 | if self.Total < self.Amount: 53 | TxObj = newutxos[Txbyte] 54 | 55 | for index, txout in enumerate(TxObj.tx_outs): 56 | if txout.script_pubkey.cmds[2] == self.fromPubKeyHash: 57 | self.Total += txout.amount 58 | prev_tx = bytes.fromhex(Txbyte) 59 | TxIns.append(TxIn(prev_tx, index)) 60 | else: 61 | break 62 | 63 | self.isBalanceEnough = True 64 | if self.Total < self.Amount: 65 | self.isBalanceEnough = False 66 | 67 | return TxIns 68 | 69 | def prepareTxOut(self): 70 | TxOuts = [] 71 | to_scriptPubkey = self.scriptPubKey(self.toAccount) 72 | TxOuts.append(TxOut(self.Amount, to_scriptPubkey)) 73 | 74 | """ Calculate Fee """ 75 | self.fee = self.COIN 76 | self.changeAmount = self.Total - self.Amount - self.fee 77 | TxOuts.append(TxOut(self.changeAmount, self.From_address_script_pubkey)) 78 | return TxOuts 79 | 80 | def signTx(self): 81 | secret = self.getPrivateKey() 82 | priv = PrivateKey(secret=secret) 83 | 84 | for index, input in enumerate(self.TxIns): 85 | self.TxObj.sign_input(index, priv, self.From_address_script_pubkey) 86 | 87 | def prepareTransaction(self): 88 | self.TxIns = self.prepareTxIn() 89 | 90 | if self.isBalanceEnough: 91 | self.TxOuts = self.prepareTxOut() 92 | self.TxObj = Tx(1, self.TxIns, self.TxOuts, 0) 93 | self.signTx() 94 | self.TxObj.TxId = self.TxObj.id() 95 | return self.TxObj 96 | 97 | return False 98 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/Point.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from FieldElement import FieldElement 7 | 8 | 9 | class Point: 10 | def __init__(self, x, y, a, b): 11 | self.a = a 12 | self.b = b 13 | self.x = x 14 | self.y = y 15 | if self.x is None and self.y is None: 16 | return 17 | if self.y ** 2 != self.x ** 3 + a * x + b: 18 | raise ValueError("({}, {}) is not on the curve".format(x, y)) 19 | 20 | # end::source1[] 21 | 22 | def __eq__(self, other): 23 | return ( 24 | self.x == other.x 25 | and self.y == other.y 26 | and self.a == other.a 27 | and self.b == other.b 28 | ) 29 | 30 | def __ne__(self, other): 31 | # this should be the inverse of the == operator 32 | return not (self == other) 33 | 34 | def __repr__(self): 35 | if self.x is None: 36 | return "Point(infinity)" 37 | elif isinstance(self.x, FieldElement): 38 | return "Point({},{})_{}_{} FieldElement({})".format( 39 | self.x.num, self.y.num, self.a.num, self.b.num, self.x.prime 40 | ) 41 | else: 42 | return "Point({},{})_{}_{}".format(self.x, self.y, self.a, self.b) 43 | 44 | def __add__(self, other): 45 | if self.a != other.a or self.b != other.b: 46 | raise TypeError( 47 | "Points {}, {} are not on the same curve".format(self, other) 48 | ) 49 | # Case 0.0: self is the point at infinity, return other 50 | if self.x is None: 51 | return other 52 | # Case 0.1: other is the point at infinity, return self 53 | if other.x is None: 54 | return self 55 | 56 | # Case 1: self.x == other.x, self.y != other.y 57 | # Result is point at infinity 58 | if self.x == other.x and self.y != other.y: 59 | return self.__class__(None, None, self.a, self.b) 60 | 61 | # Case 2: self.x ≠ other.x 62 | # Formula (x3,y3)==(x1,y1)+(x2,y2) 63 | # s=(y2-y1)/(x2-x1) 64 | # x3=s**2-x1-x2 65 | # y3=s*(x1-x3)-y1 66 | if self.x != other.x: 67 | s = (other.y - self.y) / (other.x - self.x) 68 | x = s ** 2 - self.x - other.x 69 | y = s * (self.x - x) - self.y 70 | return self.__class__(x, y, self.a, self.b) 71 | 72 | # Case 4: if we are tangent to the vertical line, 73 | # we return the point at infinity 74 | # note instead of figuring out what 0 is for each type 75 | # we just use 0 * self.x 76 | if self == other and self.y == 0 * self.x: 77 | return self.__class__(None, None, self.a, self.b) 78 | 79 | # Case 3: self == other 80 | # Formula (x3,y3)=(x1,y1)+(x1,y1) 81 | # s=(3*x1**2+a)/(2*y1) 82 | # x3=s**2-2*x1 83 | # y3=s*(x1-x3)-y1 84 | if self == other: 85 | s = (3 * self.x ** 2 + self.a) / (2 * self.y) 86 | x = s ** 2 - 2 * self.x 87 | y = s * (self.x - x) - self.y 88 | return self.__class__(x, y, self.a, self.b) 89 | 90 | # tag::source3[] 91 | def __rmul__(self, coefficient): 92 | coef = coefficient 93 | current = self # <1> 94 | result = self.__class__(None, None, self.a, self.b) # <2> 95 | while coef: 96 | if coef & 1: # <3> 97 | result += current 98 | current += current # <4> 99 | coef >>= 1 # <5> 100 | return result 101 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/blockheader.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.core.database.database import BlockchainDB 7 | from Blockchain.Backend.util.util import ( 8 | hash256, 9 | int_to_little_endian, 10 | little_endian_to_int, 11 | int_to_little_endian, 12 | bits_to_target 13 | ) 14 | 15 | 16 | class BlockHeader: 17 | def __init__(self, version, prevBlockHash, merkleRoot, timestamp, bits, nonce = None): 18 | self.version = version 19 | self.prevBlockHash = prevBlockHash 20 | self.merkleRoot = merkleRoot 21 | self.timestamp = timestamp 22 | self.bits = bits 23 | self.nonce = nonce 24 | self.blockHash = "" 25 | 26 | @classmethod 27 | def parse(cls, s): 28 | version = little_endian_to_int(s.read(4)) 29 | prevBlockHash = s.read(32)[::-1] 30 | merkleRoot = s.read(32)[::-1] 31 | timestamp = little_endian_to_int(s.read(4)) 32 | bits = s.read(4) 33 | nonce = s.read(4) 34 | return cls(version, prevBlockHash, merkleRoot, timestamp, bits, nonce) 35 | 36 | 37 | def serialize(self): 38 | result = int_to_little_endian(self.version, 4) 39 | result += self.prevBlockHash[::-1] 40 | result += self.merkleRoot[::-1] 41 | result += int_to_little_endian(self.timestamp, 4) 42 | result += self.bits 43 | result += self.nonce 44 | return result 45 | 46 | def to_hex(self): 47 | self.blockHash = self.generateBlockHash() 48 | self.nonce = little_endian_to_int(self.nonce) 49 | self.prevBlockHash = self.prevBlockHash.hex() 50 | self.merkleRoot = self.merkleRoot.hex() 51 | self.bits = self.bits.hex() 52 | 53 | def to_bytes(self): 54 | self.nonce = int_to_little_endian(self.nonce, 4) 55 | self.prevBlockHash = bytes.fromhex(self.prevBlockHash) 56 | self.merkleRoot = bytes.fromhex(self.merkleRoot) 57 | self.blockHash = bytes.fromhex(self.blockHash) 58 | self.bits = bytes.fromhex(self.bits) 59 | 60 | def mine(self, target, newBlockAvailable): 61 | self.blockHash = target + 1 62 | competitionOver = False 63 | 64 | while self.blockHash > target: 65 | if newBlockAvailable: 66 | competitionOver = True 67 | return competitionOver 68 | 69 | self.blockHash = little_endian_to_int( 70 | hash256( 71 | int_to_little_endian(self.version, 4) 72 | + bytes.fromhex(self.prevBlockHash)[::-1] 73 | + bytes.fromhex(self.merkleRoot)[::-1] 74 | + int_to_little_endian(self.timestamp, 4) 75 | + self.bits 76 | + int_to_little_endian(self.nonce, 4) 77 | ) 78 | ) 79 | self.nonce += 1 80 | print(f"Mining Started {self.nonce}", end="\r") 81 | self.blockHash = int_to_little_endian(self.blockHash, 32).hex()[::-1] 82 | self.nonce -= 1 83 | self.bits = self.bits.hex() 84 | 85 | def validateBlock(self): 86 | lastBlock = BlockchainDB().lastBlock() 87 | 88 | if self.prevBlockHash.hex() == lastBlock['BlockHeader']['blockHash']: 89 | if self.check_pow(): 90 | return True 91 | 92 | def check_pow(self): 93 | sha = hash256(self.serialize()) 94 | proof = little_endian_to_int(sha) 95 | return proof < bits_to_target(self.bits) 96 | 97 | def generateBlockHash(self): 98 | sha = hash256(self.serialize()) 99 | proof = little_endian_to_int(sha) 100 | return int_to_little_endian(proof, 32).hex()[::-1] 101 | 102 | def to_dict(self): 103 | dt = self.__dict__ 104 | return dt -------------------------------------------------------------------------------- /Blockchain/Backend/util/util.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | 7 | import hashlib 8 | from Crypto.Hash import RIPEMD160 9 | from hashlib import sha256 10 | from math import log 11 | 12 | from Blockchain.Backend.core.EllepticCurve.EllepticCurve import BASE58_ALPHABET 13 | 14 | 15 | def hash256(s): 16 | """Two rounds of SHA256""" 17 | return hashlib.sha256(hashlib.sha256(s).digest()).digest() 18 | 19 | 20 | def hash160(s): 21 | return RIPEMD160.new(sha256(s).digest()).digest() 22 | 23 | 24 | def bytes_needed(n): 25 | if n == 0: 26 | return 1 27 | return int(log(n, 256)) + 1 28 | 29 | 30 | def int_to_little_endian(n, length): 31 | """Int_to_little_endian takes an interger and return the little-endian byte sequence of length""" 32 | return n.to_bytes(length, "little") 33 | 34 | 35 | def little_endian_to_int(b): 36 | """takes a byte sequence and returns an integer""" 37 | return int.from_bytes(b, "little") 38 | 39 | def encode_base58(s): 40 | # determine how many 0 bytes (b'\x00') s starts with 41 | count = 0 42 | for c in s: 43 | if c == 0: 44 | count += 1 45 | else: 46 | break 47 | # convert to big endian integer 48 | num = int.from_bytes(s, 'big') 49 | prefix = '1' * count 50 | result = '' 51 | while num > 0: 52 | num, mod = divmod(num, 58) 53 | result = BASE58_ALPHABET[mod] + result 54 | return prefix + result 55 | 56 | 57 | def decode_base58(s): 58 | num = 0 59 | 60 | for c in s: 61 | num *= 58 62 | num += BASE58_ALPHABET.index(c) 63 | 64 | combined = num.to_bytes(25, byteorder="big") 65 | checksum = combined[-4:] 66 | 67 | if hash256(combined[:-4])[:4] != checksum: 68 | raise ValueError(f"bad Address {checksum} {hash256(combined[:-4][:4])}") 69 | 70 | return combined[1:-4] 71 | 72 | def read_varint(s): 73 | '''read_varint reads a variable integer from a stream''' 74 | i = s.read(1)[0] 75 | if i == 0xfd: 76 | # 0xfd means the next two bytes are the number 77 | return little_endian_to_int(s.read(2)) 78 | elif i == 0xfe: 79 | # 0xfe means the next four bytes are the number 80 | return little_endian_to_int(s.read(4)) 81 | elif i == 0xff: 82 | # 0xff means the next eight bytes are the number 83 | return little_endian_to_int(s.read(8)) 84 | else: 85 | # anything else is just the integer 86 | return i 87 | 88 | def encode_varint(i): 89 | """encodes an integer as a varint""" 90 | if i < 0xFD: 91 | return bytes([i]) 92 | elif i < 0x10000: 93 | return b"\xfd" + int_to_little_endian(i, 2) 94 | elif i < 0x100000000: 95 | return b"\xfe" + int_to_little_endian(i, 4) 96 | elif i < 0x10000000000000000: 97 | return b"\xff" + int_to_little_endian(i, 8) 98 | else: 99 | raise ValueError("integer too large: {}".format(i)) 100 | 101 | 102 | def merkle_parent_level(hashes): 103 | """takes a list of binary hashes and returns a list that's half of the length""" 104 | 105 | if len(hashes) % 2 == 1: 106 | hashes.append(hashes[-1]) 107 | 108 | parent_level = [] 109 | 110 | for i in range(0, len(hashes), 2): 111 | parent = hash256(hashes[i] + hashes[i + 1]) 112 | parent_level.append(parent) 113 | return parent_level 114 | 115 | 116 | def merkle_root(hashes): 117 | """Takes a list of binary hashes and return the merkle root""" 118 | current_level = hashes 119 | 120 | while len(current_level) > 1: 121 | current_level = merkle_parent_level(current_level) 122 | 123 | return current_level[0] 124 | 125 | 126 | def target_to_bits(target): 127 | """Turns a target integer back into bits""" 128 | raw_bytes = target.to_bytes(32, "big") 129 | raw_bytes = raw_bytes.lstrip(b"\x00") # <1> 130 | if raw_bytes[0] > 0x7F: # <2> 131 | exponent = len(raw_bytes) + 1 132 | coefficient = b"\x00" + raw_bytes[:2] 133 | else: 134 | exponent = len(raw_bytes) # <3> 135 | coefficient = raw_bytes[:3] # <4> 136 | new_bits = coefficient[::-1] + bytes([exponent]) # <5> 137 | return new_bits 138 | 139 | def bits_to_target(bits): 140 | exponent = bits[-1] 141 | coefficient = little_endian_to_int(bits[:-1]) 142 | return coefficient * 256**(exponent - 3) 143 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/Script.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.util.util import int_to_little_endian, encode_varint, little_endian_to_int, read_varint 7 | from Blockchain.Backend.core.EllepticCurve.op import OP_CODE_FUNCTION 8 | 9 | 10 | class Script: 11 | def __init__(self, cmds=None): 12 | if cmds is None: 13 | self.cmds = [] 14 | else: 15 | self.cmds = cmds 16 | 17 | def __add__(self, other): 18 | return Script(self.cmds + other.cmds) 19 | 20 | def serialize(self): 21 | # initialize what we'll send back 22 | result = b"" 23 | # go through each cmd 24 | for cmd in self.cmds: 25 | # if the cmd is an integer, it's an opcode 26 | if type(cmd) == int: 27 | # turn the cmd into a single byte integer using int_to_little_endian 28 | # result += int_to_little_endian(cmd, 1) 29 | result += int_to_little_endian(cmd, 1) 30 | else: 31 | # otherwise, this is an element 32 | # get the length in bytes 33 | length = len(cmd) 34 | # for large lengths, we have to use a pushdata opcode 35 | if length < 75: 36 | # turn the length into a single byte integer 37 | result += int_to_little_endian(length, 1) 38 | elif length > 75 and length < 0x100: 39 | # 76 is pushdata1 40 | result += int_to_little_endian(76, 1) 41 | result += int_to_little_endian(length, 1) 42 | elif length >= 0x100 and length <= 520: 43 | # 77 is pushdata2 44 | result += int_to_little_endian(77, 1) 45 | result += int_to_little_endian(length, 2) 46 | else: 47 | raise ValueError("too long an cmd") 48 | 49 | result += cmd 50 | # get the length of the whole thing 51 | total = len(result) 52 | # encode_varint the total length of the result and prepend 53 | return encode_varint(total) + result 54 | 55 | @classmethod 56 | def parse(cls, s): 57 | # get the length of the entire field 58 | length = read_varint(s) 59 | # initialize the cmds array 60 | cmds = [] 61 | # initialize the number of bytes we've read to 0 62 | count = 0 63 | # loop until we've read length bytes 64 | while count < length: 65 | # get the current byte 66 | current = s.read(1) 67 | # increment the bytes we've read 68 | count += 1 69 | # convert the current byte to an integer 70 | current_byte = current[0] 71 | # if the current byte is between 1 and 75 inclusive 72 | if current_byte >= 1 and current_byte <= 75: 73 | # we have an cmd set n to be the current byte 74 | n = current_byte 75 | # add the next n bytes as an cmd 76 | cmds.append(s.read(n)) 77 | # increase the count by n 78 | count += n 79 | elif current_byte == 76: 80 | # op_pushdata1 81 | data_length = little_endian_to_int(s.read(1)) 82 | cmds.append(s.read(data_length)) 83 | count += data_length + 1 84 | elif current_byte == 77: 85 | # op_pushdata2 86 | data_length = little_endian_to_int(s.read(2)) 87 | cmds.append(s.read(data_length)) 88 | count += data_length + 2 89 | else: 90 | # we have an opcode. set the current byte to op_code 91 | op_code = current_byte 92 | # add the op_code to the list of cmds 93 | cmds.append(op_code) 94 | if count != length: 95 | raise SyntaxError('parsing script failed') 96 | return cls(cmds) 97 | 98 | def evaluate(self, z): 99 | cmds = self.cmds[:] 100 | stack = [] 101 | 102 | while len(cmds) > 0: 103 | cmd = cmds.pop(0) 104 | 105 | if type(cmd) == int: 106 | operation = OP_CODE_FUNCTION[cmd] 107 | 108 | if cmd == 172: 109 | if not operation(stack, z): 110 | print(f"Error in Signature Verification") 111 | return False 112 | 113 | elif not operation(stack): 114 | print(f"Error in Signature Verification") 115 | return False 116 | else: 117 | stack.append(cmd) 118 | return True 119 | 120 | @classmethod 121 | def p2pkh_script(cls, h160): 122 | """Takes a hash160 and returns the p2pkh ScriptPubKey""" 123 | return Script([0x76, 0xA9, h160, 0x88, 0xAC]) 124 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/network/syncManager.py: -------------------------------------------------------------------------------- 1 | from Blockchain.Backend.core.block import Block 2 | from Blockchain.Backend.core.blockheader import BlockHeader 3 | from Blockchain.Backend.core.network.connection import Node 4 | from Blockchain.Backend.core.database.database import BlockchainDB, NodeDB 5 | from Blockchain.Backend.core.Tx import Tx 6 | from Blockchain.Backend.core.network.network import NetworkEnvelope, requestBlock, FinishedSending, portlist 7 | from threading import Thread 8 | 9 | from Blockchain.Backend.util.util import little_endian_to_int 10 | class syncManager: 11 | def __init__(self, host, port, newBlockAvailable = None, secondryChain = None, Mempool = None): 12 | self.host = host 13 | self.port = port 14 | self.newBlockAvailable = newBlockAvailable 15 | self.secondryChain = secondryChain 16 | self.Mempool = Mempool 17 | 18 | def spinUpTheServer(self): 19 | self.server = Node(self.host, self.port) 20 | self.server.startServer() 21 | print("SERVER STARTED") 22 | print(f"[LISTENING] at {self.host}:{self.port}") 23 | 24 | while True: 25 | self.conn, self.addr = self.server.acceptConnection() 26 | handleConn = Thread(target = self.handleConnection) 27 | handleConn.start() 28 | 29 | def handleConnection(self): 30 | envelope = self.server.read() 31 | try: 32 | if len(str(self.addr[1])) == 4: 33 | self.addNode() 34 | 35 | if envelope.command == b'Tx': 36 | Transaction = Tx.parse(envelope.stream()) 37 | Transaction.TxId = Transaction.id() 38 | self.Mempool[Transaction.TxId] = Transaction 39 | 40 | if envelope.command == b'block': 41 | blockObj = Block.parse(envelope.stream()) 42 | BlockHeaderObj = BlockHeader(blockObj.BlockHeader.version, 43 | blockObj.BlockHeader.prevBlockHash, 44 | blockObj.BlockHeader.merkleRoot, 45 | blockObj.BlockHeader.timestamp, 46 | blockObj.BlockHeader.bits, 47 | blockObj.BlockHeader.nonce) 48 | 49 | self.newBlockAvailable[BlockHeaderObj.generateBlockHash()] = blockObj 50 | print(f"New Block Received : {blockObj.Height}") 51 | 52 | if envelope.command == requestBlock.command: 53 | start_block, end_block = requestBlock.parse(envelope.stream()) 54 | self.sendBlockToRequestor(start_block) 55 | print(f"Start Block is {start_block} \n End Block is {end_block}") 56 | 57 | self.conn.close() 58 | except Exception as e: 59 | self.conn.close() 60 | print(f" Error while processing the client request \n {e}") 61 | 62 | def addNode(self): 63 | nodeDb = NodeDB() 64 | portList = nodeDb.read() 65 | 66 | if self.addr[1] and (self.addr[1] + 1) not in portList: 67 | nodeDb.write([self.addr[1] + 1]) 68 | 69 | def sendBlockToRequestor(self, start_block): 70 | blocksToSend = self.fetchBlocksFromBlockchain(start_block) 71 | 72 | try: 73 | self.sendBlock(blocksToSend) 74 | self.sendSecondryChain() 75 | self.sendPortlist() 76 | self.sendFinishedMessage() 77 | except Exception as e: 78 | print(f"Unable to send the blocks \n {e}") 79 | 80 | def sendPortlist(self): 81 | nodeDB = NodeDB() 82 | portLists = nodeDB.read() 83 | 84 | portLst = portlist(portLists) 85 | envelope = NetworkEnvelope(portLst.command, portLst.serialize()) 86 | self.conn.sendall(envelope.serialize()) 87 | 88 | def sendSecondryChain(self): 89 | TempSecChain = dict(self.secondryChain) 90 | 91 | for blockHash in TempSecChain: 92 | envelope = NetworkEnvelope(TempSecChain[blockHash].command, TempSecChain[blockHash].serialize()) 93 | self.conn.sendall(envelope.serialize()) 94 | 95 | 96 | def sendFinishedMessage(self): 97 | MessageFinish = FinishedSending() 98 | envelope = NetworkEnvelope(MessageFinish.command, MessageFinish.serialize()) 99 | self.conn.sendall(envelope.serialize()) 100 | 101 | def sendBlock(self, blockstoSend): 102 | for block in blockstoSend: 103 | cblock = Block.to_obj(block) 104 | envelope = NetworkEnvelope(cblock.command, cblock.serialize()) 105 | self.conn.sendall(envelope.serialize()) 106 | print(f"Block Sent {cblock.Height}") 107 | 108 | def fetchBlocksFromBlockchain(self, start_Block): 109 | fromBlocksOnwards = start_Block.hex() 110 | 111 | blocksToSend = [] 112 | blockchain = BlockchainDB() 113 | blocks = blockchain.read() 114 | 115 | foundBlock = False 116 | for block in blocks: 117 | if block['BlockHeader']['blockHash'] == fromBlocksOnwards: 118 | foundBlock = True 119 | continue 120 | 121 | if foundBlock: 122 | blocksToSend.append(block) 123 | 124 | return blocksToSend 125 | 126 | def connectToHost(self, localport, port, bindPort = None): 127 | self.connect = Node(self.host, port) 128 | 129 | if bindPort: 130 | self.socket = self.connect.connect(localport, bindPort) 131 | else: 132 | self.socket = self.connect.connect(localport) 133 | 134 | self.stream = self.socket.makefile('rb', None) 135 | 136 | def publishBlock(self, localport, port, block): 137 | self.connectToHost(localport, port) 138 | self.connect.send(block) 139 | 140 | def publishTx(self, Tx): 141 | self.connect.send(Tx) 142 | 143 | def startDownload(self, localport, port, bindPort): 144 | lastBlock = BlockchainDB().lastBlock() 145 | 146 | if not lastBlock: 147 | lastBlockHeader = "0000bbe173a3c36eabec25b0574bf7b055db9861b07f9ee10ad796eb06428b9b" 148 | else: 149 | lastBlockHeader = lastBlock['BlockHeader']['blockHash'] 150 | 151 | startBlock = bytes.fromhex(lastBlockHeader) 152 | 153 | getHeaders = requestBlock(startBlock=startBlock) 154 | self.connectToHost(localport, port, bindPort) 155 | self.connect.send(getHeaders) 156 | 157 | while True: 158 | envelope = NetworkEnvelope.parse(self.stream) 159 | if envelope.command == b"Finished": 160 | blockObj = FinishedSending.parse(envelope.stream()) 161 | print(f"All Blocks Received") 162 | self.socket.close() 163 | break 164 | 165 | if envelope.command == b'portlist': 166 | ports = portlist.parse(envelope.stream()) 167 | nodeDb = NodeDB() 168 | portlists = nodeDb.read() 169 | 170 | for port in ports: 171 | if port not in portlists: 172 | nodeDb.write([port]) 173 | 174 | if envelope.command == b'block': 175 | blockObj = Block.parse(envelope.stream()) 176 | BlockHeaderObj = BlockHeader(blockObj.BlockHeader.version, 177 | blockObj.BlockHeader.prevBlockHash, 178 | blockObj.BlockHeader.merkleRoot, 179 | blockObj.BlockHeader.timestamp, 180 | blockObj.BlockHeader.bits, 181 | blockObj.BlockHeader.nonce) 182 | 183 | if BlockHeaderObj.validateBlock(): 184 | for idx, tx in enumerate(blockObj.Txs): 185 | tx.TxId = tx.id() 186 | blockObj.Txs[idx] = tx.to_dict() 187 | 188 | BlockHeaderObj.blockHash = BlockHeaderObj.generateBlockHash() 189 | BlockHeaderObj.prevBlockHash = BlockHeaderObj.prevBlockHash.hex() 190 | BlockHeaderObj.merkleRoot = BlockHeaderObj.merkleRoot.hex() 191 | BlockHeaderObj.nonce = little_endian_to_int(BlockHeaderObj.nonce) 192 | BlockHeaderObj.bits = BlockHeaderObj.bits.hex() 193 | blockObj.BlockHeader = BlockHeaderObj 194 | BlockchainDB().write([blockObj.to_dict()]) 195 | print(f"Block Received - {blockObj.Height}") 196 | else: 197 | self.secondryChain[BlockHeaderObj.generateBlockHash()] = blockObj 198 | 199 | -------------------------------------------------------------------------------- /Blockchain/Frontend/run.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from flask import Flask, render_template, request, redirect, url_for 7 | from Blockchain.client.sendBTC import SendBTC 8 | from Blockchain.Backend.core.Tx import Tx 9 | from Blockchain.Backend.core.database.database import BlockchainDB, NodeDB 10 | from Blockchain.Backend.util.util import encode_base58, decode_base58 11 | from Blockchain.Backend.core.network.syncManager import syncManager 12 | from hashlib import sha256 13 | from multiprocessing import Process 14 | from flask_qrcode import QRcode 15 | 16 | app = Flask(__name__) 17 | qrcode = QRcode(app) 18 | main_prefix = b'\x00' 19 | global memoryPool 20 | memoryPool ={} 21 | 22 | @app.route('/') 23 | def index(): 24 | return render_template('home.html') 25 | 26 | @app.route('/transactions/') 27 | @app.route('/transactions') 28 | def transactions(txid = None): 29 | if txid: 30 | return redirect(url_for('txDetail', txid = txid)) 31 | else: 32 | ErrorFlag = True 33 | while ErrorFlag: 34 | try: 35 | allTxs = dict(UTXOS) 36 | ErrorFlag = False 37 | return render_template("transactions.html",allTransactions = allTxs,refreshtime = 10) 38 | except: 39 | ErrorFlag = True 40 | return render_template('transactions.html', allTransactions={}, refreshtime = 10) 41 | 42 | @app.route('/tx/') 43 | def txDetail(txid): 44 | blocks = readDatabase() 45 | for block in blocks: 46 | for Tx in block['Txs']: 47 | if Tx['TxId'] == txid: 48 | return render_template('txDetail.html', Tx=Tx, block = block , encode_base58 = encode_base58, 49 | bytes = bytes, sha256 = sha256, main_prefix = main_prefix) 50 | return "

No Results Found

" 51 | 52 | @app.route('/mempool') 53 | def mempool(): 54 | try: 55 | blocks = readDatabase() 56 | ErrorFlag = True 57 | while ErrorFlag: 58 | try: 59 | mempooltxs = dict(MEMPOOL) 60 | ErrorFlag = False 61 | except: 62 | ErrorFlag = True 63 | 64 | """" If TxId is not in the Origional list then remove it from the mempool """ 65 | for txid in memoryPool: 66 | if txid not in mempooltxs: 67 | del memoryPool[txid] 68 | 69 | """Add the new Tx to the mempool if it is not already there""" 70 | for Txid in mempooltxs: 71 | amount = 0 72 | TxObj = mempooltxs[Txid] 73 | matchFound = False 74 | 75 | """ Total Amount """ 76 | for txin in TxObj.tx_ins: 77 | for block in blocks: 78 | for Tx in block['Txs']: 79 | if Tx['TxId'] == txin.prev_tx.hex(): 80 | amount += Tx['tx_outs'][txin.prev_index]['amount'] 81 | matchFound = True 82 | break 83 | if matchFound: 84 | matchFound = False 85 | break 86 | memoryPool[TxObj.TxId] = [TxObj.to_dict(), amount/100000000, txin.prev_index] 87 | return render_template('mempool.html', Txs = memoryPool,refreshtime = 2) 88 | 89 | except Exception as e: 90 | return render_template('mempool.html', Txs = memoryPool,refreshtime = 2) 91 | 92 | @app.route('/memTx/') 93 | def memTxDetails(txid): 94 | if txid in memoryPool: 95 | Tx = memoryPool.get(txid)[0] 96 | return render_template('txDetail.html', Tx = Tx, refreshtime = 2, 97 | encode_base58 = encode_base58, bytes = bytes, sha256 = sha256, main_prefix = main_prefix, 98 | Unconfirmed = True) 99 | else: 100 | return redirect(url_for('transactions', txid = txid)) 101 | 102 | @app.route('/search') 103 | def search(): 104 | identifier = request.args.get('search') 105 | if len(identifier) == 64: 106 | if identifier[:4] == "0000": 107 | return redirect(url_for('showBlock', blockHeader = identifier)) 108 | else: 109 | return redirect(url_for('txDetail', txid = identifier)) 110 | else: 111 | return redirect(url_for('address', publicAddress = identifier)) 112 | 113 | """ Read data from the Blockchain """ 114 | def readDatabase(): 115 | ErrorFlag = True 116 | while ErrorFlag: 117 | try: 118 | blockchain = BlockchainDB() 119 | blocks = blockchain.read() 120 | ErrorFlag = False 121 | except: 122 | ErrorFlag = True 123 | print("Error reading database") 124 | return blocks 125 | 126 | @app.route('/block') 127 | def block(): 128 | header = request.args.get('blockHeader') 129 | if request.args.get('blockHeader'): 130 | return redirect(url_for('showBlock', blockHeader=request.args.get('blockHeader')) ) 131 | else: 132 | blocks = readDatabase() 133 | return render_template('block.html', blocks=blocks, refreshtime = 10) 134 | 135 | @app.route('/block/') 136 | def showBlock(blockHeader): 137 | blocks = readDatabase() 138 | for block in blocks: 139 | if block['BlockHeader']['blockHash'] == blockHeader: 140 | return render_template('blockDetails.html', block = block, main_prefix = main_prefix, 141 | encode_base58 = encode_base58, bytes = bytes, sha256 = sha256) 142 | 143 | return "

Invalid Identifier

" 144 | 145 | @app.route('/address/') 146 | def address(publicAddress): 147 | if len(publicAddress) < 35 and publicAddress[:1] == "1": 148 | h160 = decode_base58(publicAddress) 149 | 150 | ErrorFlag = True 151 | while ErrorFlag: 152 | try: 153 | AllUtxos = dict(UTXOS) 154 | ErrorFlag = False 155 | except Exception as e: 156 | ErrorFlag = True 157 | 158 | amount = 0 159 | AccountUtxos = [] 160 | 161 | for TxId in AllUtxos: 162 | for tx_out in AllUtxos[TxId].tx_outs: 163 | if tx_out.script_pubkey.cmds[2] == h160: 164 | amount += tx_out.amount 165 | AccountUtxos.append(AllUtxos[TxId]) 166 | 167 | return render_template('address.html', Txs = AccountUtxos, amount = amount, 168 | encode_base58 = encode_base58, bytes = bytes, sha256 = sha256, main_prefix = main_prefix, 169 | publicAddress = publicAddress, qrcode = qrcode) 170 | else: 171 | return "

Invalid Identifier

" 172 | 173 | 174 | @app.route("/wallet", methods=["GET", "POST"]) 175 | def wallet(): 176 | message = "" 177 | if request.method == "POST": 178 | FromAddress = request.form.get("fromAddress") 179 | ToAddress = request.form.get("toAddress") 180 | Amount = request.form.get("Amount", type=int) 181 | sendCoin = SendBTC(FromAddress, ToAddress, Amount, UTXOS) 182 | TxObj = sendCoin.prepareTransaction() 183 | 184 | scriptPubKey = sendCoin.scriptPubKey(FromAddress) 185 | verified = True 186 | 187 | if not TxObj: 188 | message = "Invalid Transaction" 189 | 190 | if isinstance(TxObj, Tx): 191 | for index, tx in enumerate(TxObj.tx_ins): 192 | if not TxObj.verify_input(index, scriptPubKey): 193 | verified = False 194 | 195 | if verified: 196 | MEMPOOL[TxObj.TxId] = TxObj 197 | relayTxs = Process(target = broadcastTx, args = (TxObj, localHostPort)) 198 | relayTxs.start() 199 | message = "Transaction added in memory Pool" 200 | 201 | return render_template("wallet.html", message=message) 202 | 203 | def broadcastTx(TxObj, localHostPort = None): 204 | try: 205 | node = NodeDB() 206 | portList = node.read() 207 | 208 | for port in portList: 209 | if localHostPort != port: 210 | sync = syncManager('127.0.0.1', port) 211 | try: 212 | sync.connectToHost(localHostPort - 1, port) 213 | sync.publishTx(TxObj) 214 | 215 | except Exception as err: 216 | pass 217 | 218 | except Exception as err: 219 | pass 220 | 221 | def main(utxos, MemPool, port, localPort): 222 | global UTXOS 223 | global MEMPOOL 224 | global localHostPort 225 | UTXOS = utxos 226 | MEMPOOL = MemPool 227 | localHostPort = localPort 228 | app.run(port = port) 229 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/Tx.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | from Blockchain.Backend.core.Script import Script 7 | from Blockchain.Backend.util.util import ( 8 | int_to_little_endian, 9 | bytes_needed, 10 | decode_base58, 11 | little_endian_to_int, 12 | encode_varint, 13 | hash256, 14 | read_varint 15 | ) 16 | 17 | ZERO_HASH = b"\0" * 32 18 | REWARD = 50 19 | 20 | PRIVATE_KEY = ( 21 | "59024195091230105596801455306913435815673319996141880726735464739248197324364" 22 | ) 23 | MINER_ADDRESS = "1LYgXwYXw16GJXgDwHV7aCNijnQWYEdc1C" 24 | SIGHASH_ALL = 1 25 | 26 | 27 | class CoinbaseTx: 28 | def __init__(self, BlockHeight): 29 | self.BlockHeightInLittleEndian = int_to_little_endian( 30 | BlockHeight, bytes_needed(BlockHeight) 31 | ) 32 | 33 | def CoinbaseTransaction(self): 34 | prev_tx = ZERO_HASH 35 | prev_index = 0xFFFFFFFF 36 | tx_ins = [] 37 | tx_ins.append(TxIn(prev_tx, prev_index)) 38 | tx_ins[0].script_sig.cmds.append(self.BlockHeightInLittleEndian) 39 | 40 | tx_outs = [] 41 | target_amount = REWARD * 100000000 42 | target_h160 = decode_base58(MINER_ADDRESS) 43 | target_script = Script.p2pkh_script(target_h160) 44 | tx_outs.append(TxOut(amount=target_amount, script_pubkey=target_script)) 45 | coinBaseTx = Tx(1, tx_ins, tx_outs, 0) 46 | coinBaseTx.TxId = coinBaseTx.id() 47 | 48 | return coinBaseTx 49 | 50 | 51 | class Tx: 52 | command = b'Tx' 53 | def __init__(self, version, tx_ins, tx_outs, locktime): 54 | self.version = version 55 | self.tx_ins = tx_ins 56 | self.tx_outs = tx_outs 57 | self.locktime = locktime 58 | 59 | def id(self): 60 | """Human-readable Tx id""" 61 | return self.hash().hex() 62 | 63 | def hash(self): 64 | """Binary Has of serialization""" 65 | return hash256(self.serialize())[::-1] 66 | 67 | @classmethod 68 | def parse(cls, s): 69 | '''Takes a byte stream and parses the transaction at the start 70 | return a Tx object 71 | ''' 72 | # s.read(n) will return n bytes 73 | # version is an integer in 4 bytes, little-endian 74 | # num_inputs is a varint, use read_varint(s) 75 | # parse num_inputs number of TxIns 76 | # num_outputs is a varint, use read_varint(s) 77 | # parse num_outputs number of TxOuts 78 | # locktime is an integer in 4 bytes, little-endian 79 | # return an instance of the class (see __init__ for args) 80 | 81 | version = little_endian_to_int(s.read(4)) 82 | num_inputs = read_varint(s) 83 | inputs = [] 84 | for _ in range(num_inputs): 85 | inputs.append(TxIn.parse(s)) 86 | num_outputs = read_varint(s) 87 | outputs = [] 88 | for _ in range(num_outputs): 89 | outputs.append(TxOut.parse(s)) 90 | locktime = little_endian_to_int(s.read(4)) 91 | return cls(version, inputs, outputs, locktime) 92 | 93 | def serialize(self): 94 | result = int_to_little_endian(self.version, 4) 95 | result += encode_varint(len(self.tx_ins)) 96 | 97 | for tx_in in self.tx_ins: 98 | result += tx_in.serialize() 99 | 100 | result += encode_varint(len(self.tx_outs)) 101 | 102 | for tx_out in self.tx_outs: 103 | result += tx_out.serialize() 104 | 105 | result += int_to_little_endian(self.locktime, 4) 106 | return result 107 | 108 | def sigh_hash(self, input_index, script_pubkey): 109 | s = int_to_little_endian(self.version, 4) 110 | s += encode_varint(len(self.tx_ins)) 111 | 112 | for i, tx_in in enumerate(self.tx_ins): 113 | if i == input_index: 114 | s += TxIn(tx_in.prev_tx, tx_in.prev_index, script_pubkey).serialize() 115 | else: 116 | s += TxIn(tx_in.prev_tx, tx_in.prev_index).serialize() 117 | 118 | s += encode_varint(len(self.tx_outs)) 119 | 120 | for tx_out in self.tx_outs: 121 | s += tx_out.serialize() 122 | 123 | s += int_to_little_endian(self.locktime, 4) 124 | s += int_to_little_endian(SIGHASH_ALL, 4) 125 | h256 = hash256(s) 126 | return int.from_bytes(h256, "big") 127 | 128 | def sign_input(self, input_index, private_key, script_pubkey): 129 | z = self.sigh_hash(input_index, script_pubkey) 130 | der = private_key.sign(z).der() 131 | sig = der + SIGHASH_ALL.to_bytes(1, "big") 132 | sec = private_key.point.sec() 133 | self.tx_ins[input_index].script_sig = Script([sig, sec]) 134 | 135 | def verify_input(self, input_index, script_pubkey): 136 | tx_in = self.tx_ins[input_index] 137 | z = self.sigh_hash(input_index, script_pubkey) 138 | combined = tx_in.script_sig + script_pubkey 139 | return combined.evaluate(z) 140 | 141 | def is_coinbase(self): 142 | """ 143 | # Check that there us exactly 1 input 144 | # grab the first input and check if the prev_tx is b'\x00' * 32 145 | # check that the first input prev_index is 0xffffffff 146 | """ 147 | 148 | if len(self.tx_ins) != 1: 149 | return False 150 | 151 | first_input = self.tx_ins[0] 152 | 153 | if first_input.prev_tx != b"\x00" * 32: 154 | return False 155 | 156 | if first_input.prev_index != 0xFFFFFFFF: 157 | return False 158 | 159 | return True 160 | 161 | @classmethod 162 | def to_obj(cls, item): 163 | TxInList = [] 164 | TxOutList = [] 165 | cmds = [] 166 | 167 | """ Convert Transaction Input to the object """ 168 | for tx_in in item['tx_ins']: 169 | for cmd in tx_in['script_sig']['cmds']: 170 | 171 | if tx_in['prev_tx'] == "0000000000000000000000000000000000000000000000000000000000000000": 172 | cmds.append(int_to_little_endian(int(cmd), bytes_needed(int(cmd)))) 173 | else: 174 | if type(cmd) == int: 175 | cmds.append(cmd) 176 | else: 177 | cmds.append(bytes.fromhex(cmd)) 178 | TxInList.append(TxIn(bytes.fromhex(tx_in['prev_tx']),tx_in['prev_index'],Script(cmds))) 179 | 180 | 181 | """" Convert Transaction output to Object """ 182 | cmdsout = [] 183 | for tx_out in item['tx_outs']: 184 | for cmd in tx_out['script_pubkey']['cmds']: 185 | if type(cmd) == int: 186 | cmdsout.append(cmd) 187 | else: 188 | cmdsout.append(bytes.fromhex(cmd)) 189 | 190 | TxOutList.append(TxOut(tx_out['amount'],Script(cmdsout))) 191 | cmdsout= [] 192 | 193 | return cls(1, TxInList, TxOutList, 0) 194 | 195 | 196 | 197 | def to_dict(self): 198 | """ 199 | Convert Transaction 200 | # Convert prev_tx Hash in hex from bytes 201 | # Convert Blockheight in hex which is stored in Script signature 202 | """ 203 | for tx_index, tx_in in enumerate(self.tx_ins): 204 | if self.is_coinbase(): 205 | tx_in.script_sig.cmds[0] = little_endian_to_int( 206 | tx_in.script_sig.cmds[0] 207 | ) 208 | 209 | tx_in.prev_tx = tx_in.prev_tx.hex() 210 | 211 | for index, cmd in enumerate(tx_in.script_sig.cmds): 212 | if isinstance(cmd, bytes): 213 | tx_in.script_sig.cmds[index] = cmd.hex() 214 | 215 | tx_in.script_sig = tx_in.script_sig.__dict__ 216 | self.tx_ins[tx_index] = tx_in.__dict__ 217 | 218 | """ 219 | Convert Transaction Output to dict 220 | # If there are Numbers we don't need to do anything 221 | # If values is in bytes, convert it to hex 222 | # Loop Through all the TxOut Objects and convert them into dict 223 | """ 224 | for index, tx_out in enumerate(self.tx_outs): 225 | tx_out.script_pubkey.cmds[2] = tx_out.script_pubkey.cmds[2].hex() 226 | tx_out.script_pubkey = tx_out.script_pubkey.__dict__ 227 | self.tx_outs[index] = tx_out.__dict__ 228 | 229 | return self.__dict__ 230 | 231 | 232 | class TxIn: 233 | def __init__(self, prev_tx, prev_index, script_sig=None, sequence=0xFFFFFFFF): 234 | self.prev_tx = prev_tx 235 | self.prev_index = prev_index 236 | 237 | if script_sig is None: 238 | self.script_sig = Script() 239 | else: 240 | self.script_sig = script_sig 241 | 242 | self.sequence = sequence 243 | 244 | def serialize(self): 245 | result = self.prev_tx[::-1] 246 | result += int_to_little_endian(self.prev_index, 4) 247 | result += self.script_sig.serialize() 248 | result += int_to_little_endian(self.sequence, 4) 249 | return result 250 | 251 | @classmethod 252 | def parse(cls, s): 253 | prev_tx = s.read(32)[::-1] 254 | prev_index = little_endian_to_int(s.read(4)) 255 | script_sig = Script.parse(s) 256 | sequence = little_endian_to_int(s.read(4)) 257 | return cls(prev_tx, prev_index, script_sig, sequence) 258 | 259 | 260 | class TxOut: 261 | def __init__(self, amount, script_pubkey): 262 | self.amount = amount 263 | self.script_pubkey = script_pubkey 264 | 265 | def serialize(self): 266 | result = int_to_little_endian(self.amount, 8) 267 | result += self.script_pubkey.serialize() 268 | return result 269 | 270 | @classmethod 271 | def parse(cls,s): 272 | amount = little_endian_to_int(s.read(8)) 273 | script_pubkey = Script.parse(s) 274 | return cls(amount, script_pubkey) 275 | -------------------------------------------------------------------------------- /Blockchain/Frontend/static/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | color: whitesmoke; 6 | font-family: Verdana, Geneva, Tahoma, sans-serif; 7 | } 8 | 9 | :root { 10 | --navHoverColor: linear-gradient( 11 | to right, 12 | rgba(11, 67, 71, 0.719), 13 | hsla(157, 76%, 26%, 0.781) 14 | ); 15 | } 16 | 17 | body { 18 | background-color: black; 19 | } 20 | 21 | #cover { 22 | /* background-image: url('/static/images/wal5.jpg'); */ 23 | /* background-image: linear-gradient(110deg,black, black,rgba(230,85,237,255),rgba(254,238,148,255),rgba(230,85,237,90),purple); */ 24 | 25 | background-image: linear-gradient( 26 | 180deg, 27 | rgba(0, 0, 0, 0.9), 28 | rgba(0, 0, 0, 0.1), 29 | rgba(212, 88, 216, 0.1), 30 | rgba(0, 0, 0.5) 31 | ), 32 | url("/static/images/wal5.jpg"); 33 | 34 | background-size: cover; 35 | background-position: center; 36 | height: 100vh; 37 | padding: 2em; 38 | position: relative; 39 | } 40 | 41 | #logo { 42 | float: left; 43 | height: 8em; 44 | width: 8em; 45 | background: inherit; 46 | margin-left: 1em; 47 | } 48 | 49 | section ul { 50 | list-style: none; 51 | } 52 | 53 | section li a { 54 | position: relative; 55 | float: left; 56 | color: white; 57 | font-size: 1.3em; 58 | text-align: center; 59 | margin-left: 1.5em; 60 | padding: 0.8em 0.8em; 61 | text-decoration: none; 62 | } 63 | 64 | section li a:hover { 65 | /* background-image: var(--navHoverColor); */ 66 | border-bottom: 3px solid rgb(0, 247, 255); 67 | } 68 | 69 | section li a:active { 70 | /* background-image: var(--navHoverColor); */ 71 | background-image: var(--navHoverColor); 72 | } 73 | 74 | section li .active { 75 | border-bottom: 3px solid rgb(0, 247, 255); 76 | } 77 | 78 | .search-container { 79 | margin-top: 0.5em; 80 | margin-right: 3em; 81 | float: right; 82 | } 83 | 84 | .search-container input[type="text"] { 85 | width: 27em; 86 | padding: 1em; 87 | margin-top: 0.1em; 88 | font-size: 1em; 89 | border: none; 90 | color: whitesmoke; 91 | /* background-image: linear-gradient(to right, rgba(230,85,237,255),rgba(254,238,148,255)); */ 92 | background-image: linear-gradient( 93 | to right, 94 | rgb(0, 89, 255), 95 | rgb(225, 0, 255) 96 | ); 97 | } 98 | 99 | .search-container input::placeholder { 100 | color: whitesmoke; 101 | } 102 | 103 | .search-container button { 104 | float: right; 105 | margin-top: 0.5em; 106 | padding-left: 0.5em; 107 | background-color: inherit; 108 | border: none; 109 | } 110 | 111 | .search-container input:focus { 112 | box-shadow: 0 0 2em #8df3eb; 113 | } 114 | 115 | .search-container button img { 116 | width: 3em; 117 | height: 3em; 118 | } 119 | 120 | .mainText { 121 | clear: left; 122 | } 123 | 124 | .mainText > h1 { 125 | position: absolute; 126 | text-align: center; 127 | margin-left: 3.5em; 128 | font-size: 7em; 129 | top: 30%; 130 | color: whitesmoke; 131 | 132 | /* background: linear-gradient(to bottom, rgba(231,84,237,255) , rgba(255,239,148,255) ); 133 | -webkit-background-clip: text; 134 | -webkit-text-fill-color: transparent; */ 135 | } 136 | 137 | .mainText > h2 { 138 | position: absolute; 139 | text-align: center; 140 | margin-left: 3em; 141 | margin-right: 1em; 142 | font-size: 3em; 143 | top: 50%; 144 | } 145 | 146 | /* Style Sheet for Block html */ 147 | .grid-container { 148 | display: grid; 149 | grid-template-columns: auto; 150 | background-image: linear-gradient( 151 | to right, 152 | rgb(0, 89, 255), 153 | rgb(225, 0, 255) 154 | ); 155 | /* background-color:rgb(204, 0, 255); */ 156 | margin: 8em 5em 0em 5em; 157 | border-radius: 1em; 158 | overflow: hidden; 159 | } 160 | 161 | .grid-container h1 { 162 | float: left; 163 | font-size: 2em; 164 | margin: 1em; 165 | } 166 | 167 | .grid-container .blockheader { 168 | display: grid; 169 | grid-template-columns: 10em 1fr 10em 10em; 170 | margin-left: 1em; 171 | padding: 1em; 172 | font-weight: bold; 173 | text-align: center; 174 | font-size: 1.3em; 175 | } 176 | 177 | .grid-container .block { 178 | display: grid; 179 | grid-template-columns: 10em 1fr 10em 10em; 180 | margin-left: 1em; 181 | padding: 1em 1em 1em 6em; 182 | font-weight: bold; 183 | border-top: 0.01em solid wheat; 184 | } 185 | 186 | .loadmore { 187 | background-color: rgb(204, 0, 255); 188 | border: none; 189 | color: whitesmoke; 190 | padding: 1em; 191 | text-decoration: none; 192 | text-align: center; 193 | height: 3em; 194 | width: 10em; 195 | font-size: 1em; 196 | margin-left: 44%; 197 | margin-bottom: 2em; 198 | margin-top: 2em; 199 | } 200 | 201 | .grid-container a { 202 | text-decoration: none; 203 | } 204 | .grid-container #detail:hover { 205 | /* background-color: rgb(64, 224, 163); */ 206 | /* background-color: rgba(254,120,150,230); */ 207 | background-color: rgb(225, 0, 255); 208 | border-radius: 4em; 209 | } 210 | 211 | .grid-container .block .block-item { 212 | padding: 1em 1em 1em 0; 213 | font-weight: normal; 214 | } 215 | 216 | /* Text align Txcount and size details underneath Header */ 217 | .grid-container .block .TxCountx, 218 | .BlockSize { 219 | text-align: center; 220 | } 221 | 222 | .grid-container .block .BlockHeader { 223 | padding-left: 5em; 224 | } 225 | 226 | .grid-container1 .blockheader { 227 | display: grid; 228 | grid-template-columns: 1fr 22em; 229 | margin-left: 1em; 230 | padding: 1em; 231 | font-weight: bold; 232 | text-align: center; 233 | font-size: 1.3em; 234 | } 235 | 236 | .grid-container1 { 237 | display: grid; 238 | grid-template-columns: auto; 239 | background-image: linear-gradient( 240 | to right, 241 | rgb(0, 89, 255), 242 | rgb(225, 0, 255) 243 | ); 244 | margin: 8em 5em 0em 5em; 245 | border-radius: 1em; 246 | overflow: hidden; 247 | } 248 | 249 | .grid-container1 h1 { 250 | float: left; 251 | font-size: 2em; 252 | margin: 1em; 253 | } 254 | 255 | .grid-container1 .block .BlockHeader { 256 | grid-column-start: 2; 257 | grid-column-end: 3; 258 | } 259 | 260 | .grid-container1 .block { 261 | display: grid; 262 | grid-template-columns: 1fr 15em; 263 | margin-left: 1em; 264 | padding: 1em; 265 | font-weight: bold; 266 | border-top: 0.01em solid wheat; 267 | } 268 | 269 | .grid-container1 a { 270 | text-decoration: none; 271 | } 272 | 273 | .grid-container1 #detail:hover { 274 | /* background-color: rgb(64, 224, 163); */ 275 | background-color: rgb(225, 0, 255); 276 | border-radius: 4em; 277 | } 278 | 279 | .grid-container1 .block .block-item { 280 | padding: 1em 1em 1em 0; 281 | font-weight: normal; 282 | } 283 | 284 | .grid-container1 .block .BlockHeader { 285 | grid-column-start: 2; 286 | grid-column-end: 3; 287 | } 288 | 289 | /* Secondry Nav Bar for Block,Mempool and Transcation Screen */ 290 | 291 | .secNavBar ul { 292 | list-style-type: none; 293 | margin: 0; 294 | padding: 0; 295 | overflow: hidden; 296 | background-color: #333; 297 | } 298 | 299 | .secNavBar li { 300 | float: left; 301 | border-right: 1px solid #bbb; 302 | } 303 | 304 | .secNavBar li:last-child { 305 | border-right: none; 306 | } 307 | 308 | .secNavBar li a { 309 | display: block; 310 | color: white; 311 | text-align: center; 312 | padding: 14px 16px; 313 | text-decoration: none; 314 | } 315 | 316 | .secNavBar li a:hover:not(.active) { 317 | background-color: #111; 318 | } 319 | 320 | .secNavBar .active { 321 | background-color: #04aa6d; 322 | } 323 | 324 | /* Block Details Styles */ 325 | .BlockNumber { 326 | clear: left; 327 | margin: 3em 3em 0em 3em; 328 | border-radius: 1em; 329 | text-align: left; 330 | font-size: 2em; 331 | } 332 | 333 | .grid-container3 { 334 | display: grid; 335 | grid-template-columns: 20em 1fr; 336 | background-image: linear-gradient( 337 | to right, 338 | rgb(0, 89, 255), 339 | rgb(225, 0, 255) 340 | ); 341 | margin: 1em 5em 0em 5em; 342 | padding: 1em; 343 | border-radius: 1em; 344 | overflow: hidden; 345 | } 346 | 347 | .grid-container3 .TxItem { 348 | text-align: left; 349 | padding: 1em; 350 | font-size: 1.1em; 351 | border-top: 0.01em solid whitesmoke; 352 | } 353 | 354 | .grid-container3 .TxHeader h3 { 355 | padding-bottom: 1em; 356 | } 357 | 358 | .grid-container3 .TxItemDetail { 359 | text-align: left; 360 | padding: 1em; 361 | padding-left: 10em; 362 | font-size: 1.1em; 363 | border-top: 0.01em solid whitesmoke; 364 | } 365 | 366 | .TransactionsHeader { 367 | clear: left; 368 | margin: 1em 3em 0em 3em; 369 | border-radius: 1em; 370 | text-align: left; 371 | font-size: 2em; 372 | } 373 | 374 | .TxDetails h1, 375 | .TxHeader h1 { 376 | padding: 1em; 377 | } 378 | .TranscationsDiv { 379 | display: grid; 380 | position: relative; 381 | grid-template-columns: 1fr 1fr; 382 | background-image: linear-gradient( 383 | to right, 384 | rgb(0, 89, 255), 385 | rgb(225, 0, 255) 386 | ); 387 | margin: 1em 5em 0em 5em; 388 | border-radius: 1em; 389 | text-align: left; 390 | word-break: break-all; 391 | } 392 | 393 | .TxStyle { 394 | padding: 1em 1em 1em 1em; 395 | } 396 | 397 | .TxStyle a { 398 | text-decoration: none; 399 | } 400 | 401 | .TxStyle .TxId a { 402 | color: rgb(0, 255, 157); 403 | } 404 | 405 | .TxHeader h1 { 406 | color: rgb(0, 255, 242); 407 | } 408 | 409 | .TxStyle h3 { 410 | padding-left: 1em; 411 | } 412 | 413 | .TxInput { 414 | background-image: linear-gradient( 415 | to right, 416 | rgb(255, 0, 221), 417 | rgb(143, 143, 143) 418 | ); 419 | border-radius: 1em; 420 | margin-top: 1em; 421 | padding: 1em; 422 | } 423 | 424 | /* output style */ 425 | 426 | .Txoutput { 427 | background-image: linear-gradient( 428 | to right, 429 | rgb(255, 0, 221), 430 | rgb(76, 0, 255) 431 | ); 432 | padding: 1em; 433 | margin-top: 1em; 434 | border-radius: 1em; 435 | } 436 | 437 | .address { 438 | clear: both; 439 | display: grid; 440 | grid-template-columns: 1fr 1fr; 441 | } 442 | 443 | .address .addTag { 444 | padding-left: 6em; 445 | } 446 | .address .addTag h1 { 447 | font-size: 3em; 448 | } 449 | 450 | .address .addTag h3 { 451 | color: cyan; 452 | } 453 | 454 | /*Send MAAN design*/ 455 | 456 | /*Style Wallet Page*/ 457 | .wallet-container { 458 | background-image: linear-gradient( 459 | to right, 460 | rgb(0, 89, 255), 461 | rgb(225, 0, 255) 462 | ); 463 | margin: 8em 5em 0em 5em; 464 | border-radius: 1em; 465 | overflow: hidden; 466 | } 467 | 468 | .wallet-container h1 { 469 | color: whitesmoke; 470 | text-align: center; 471 | font-size: 2.3em; 472 | padding: 1em 1em 0 1em; 473 | margin-right: 3em; 474 | } 475 | 476 | #form { 477 | margin-left: 8em; 478 | margin-bottom: 3em; 479 | font-size: 1.2em; 480 | font-family: Verdana, Geneva, Tahoma, sans-serif; 481 | } 482 | 483 | #form input:focus { 484 | box-shadow: 0 0 2em #8df3eb; 485 | } 486 | 487 | #form input { 488 | background-image: linear-gradient( 489 | to right, 490 | rgb(255, 0, 221), 491 | rgb(76, 0, 255) 492 | ); 493 | border-radius: 1em; 494 | padding: 1em; 495 | width: 70vw; 496 | border: none; 497 | margin-top: 1em; 498 | margin-bottom: 1em; 499 | } 500 | 501 | /* Send Button Style*/ 502 | #form input[type="submit"] { 503 | width: 20vw; 504 | background-image: linear-gradient( 505 | to right, 506 | rgb(0, 255, 234), 507 | rgb(255, 0, 221) 508 | ); 509 | margin-left: 25em; 510 | font-size: 1em; 511 | } 512 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/EllepticCurve/EllepticCurve.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | 7 | A = 0 8 | B = 7 9 | 10 | P = 2 ** 256 - 2 ** 32 - 977 11 | 12 | N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 13 | BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 14 | 15 | from random import randint 16 | import hmac 17 | import hashlib 18 | 19 | # Had to install Cryto Hash because RIPEMD160 is not available in hashlib 20 | from Crypto.Hash import RIPEMD160 21 | from io import BytesIO 22 | 23 | 24 | class FieldElement: 25 | def __init__(self, num, prime): 26 | if num >= prime or num < 0: 27 | error = "Num {} not in field range 0 to {}".format(num, prime - 1) 28 | raise ValueError(error) 29 | self.num = num 30 | self.prime = prime 31 | 32 | def __repr__(self): 33 | return "FieldElement_{}({})".format(self.prime, self.num) 34 | 35 | def __eq__(self, other): 36 | if other is None: 37 | return False 38 | return self.num == other.num and self.prime == other.prime 39 | 40 | def __ne__(self, other): 41 | # this should be the inverse of the == operator 42 | return not (self == other) 43 | 44 | def __add__(self, other): 45 | if self.prime != other.prime: 46 | raise TypeError("Cannot add two numbers in different Fields") 47 | # self.num and other.num are the actual values 48 | # self.prime is what we need to mod against 49 | num = (self.num + other.num) % self.prime 50 | # We return an element of the same class 51 | return self.__class__(num, self.prime) 52 | 53 | def __sub__(self, other): 54 | if self.prime != other.prime: 55 | raise TypeError("Cannot subtract two numbers in different Fields") 56 | # self.num and other.num are the actual values 57 | # self.prime is what we need to mod against 58 | num = (self.num - other.num) % self.prime 59 | # We return an element of the same class 60 | return self.__class__(num, self.prime) 61 | 62 | def __mul__(self, other): 63 | if self.prime != other.prime: 64 | raise TypeError("Cannot multiply two numbers in different Fields") 65 | # self.num and other.num are the actual values 66 | # self.prime is what we need to mod against 67 | num = (self.num * other.num) % self.prime 68 | # We return an element of the same class 69 | return self.__class__(num, self.prime) 70 | 71 | def __pow__(self, exponent): 72 | n = exponent % (self.prime - 1) 73 | num = pow(self.num, n, self.prime) 74 | 75 | return self.__class__(num, self.prime) 76 | 77 | def __truediv__(self, other): 78 | if self.prime != other.prime: 79 | raise TypeError("Cannot divide two numbers in different Fields") 80 | # self.num and other.num are the actual values 81 | # self.prime is what we need to mod against 82 | # use fermat's little theorem: 83 | # self.num**(p-1) % p == 1 84 | # this means: 85 | # 1/n == pow(n, p-2, p) 86 | num = (self.num * pow(other.num, self.prime - 2, self.prime)) % self.prime 87 | # We return an element of the same class 88 | return self.__class__(num, self.prime) 89 | 90 | def __rmul__(self, coefficient): 91 | num = (self.num * coefficient) % self.prime 92 | return self.__class__(num=num, prime=self.prime) 93 | 94 | 95 | class Point: 96 | def __init__(self, x, y, a, b): 97 | self.a = a 98 | self.b = b 99 | self.x = x 100 | self.y = y 101 | if self.x is None and self.y is None: 102 | return 103 | if self.y ** 2 != self.x ** 3 + a * x + b: 104 | raise ValueError("({}, {}) is not on the curve".format(x, y)) 105 | 106 | # end::source1[] 107 | 108 | def __eq__(self, other): 109 | return ( 110 | self.x == other.x 111 | and self.y == other.y 112 | and self.a == other.a 113 | and self.b == other.b 114 | ) 115 | 116 | def __ne__(self, other): 117 | # this should be the inverse of the == operator 118 | return not (self == other) 119 | 120 | def __repr__(self): 121 | if self.x is None: 122 | return "Point(infinity)" 123 | elif isinstance(self.x, FieldElement): 124 | return "Point({},{})_{}_{} FieldElement({})".format( 125 | self.x.num, self.y.num, self.a.num, self.b.num, self.x.prime 126 | ) 127 | else: 128 | return "Point({},{})_{}_{}".format(self.x, self.y, self.a, self.b) 129 | 130 | def __add__(self, other): 131 | if self.a != other.a or self.b != other.b: 132 | raise TypeError( 133 | "Points {}, {} are not on the same curve".format(self, other) 134 | ) 135 | # Case 0.0: self is the point at infinity, return other 136 | if self.x is None: 137 | return other 138 | # Case 0.1: other is the point at infinity, return self 139 | if other.x is None: 140 | return self 141 | 142 | # Case 1: self.x == other.x, self.y != other.y 143 | # Result is point at infinity 144 | if self.x == other.x and self.y != other.y: 145 | return self.__class__(None, None, self.a, self.b) 146 | 147 | # Case 2: self.x ≠ other.x 148 | # Formula (x3,y3)==(x1,y1)+(x2,y2) 149 | # s=(y2-y1)/(x2-x1) 150 | # x3=s**2-x1-x2 151 | # y3=s*(x1-x3)-y1 152 | if self.x != other.x: 153 | s = (other.y - self.y) / (other.x - self.x) 154 | x = s ** 2 - self.x - other.x 155 | y = s * (self.x - x) - self.y 156 | return self.__class__(x, y, self.a, self.b) 157 | 158 | # Case 4: if we are tangent to the vertical line, when x1 = x2 and y1,y2 = 0 159 | # we return the point at infinity 160 | # note instead of figuring out what 0 is for each type 161 | # we just use 0 * self.x 162 | if self == other and self.y == 0 * self.x: 163 | return self.__class__(None, None, self.a, self.b) 164 | 165 | # Case 3: self == other 166 | # Formula (x3,y3)=(x1,y1)+(x1,y1) 167 | # s=(3*x1**2+a)/(2*y1) 168 | # x3=s**2-2*x1 169 | # y3=s*(x1-x3)-y1 170 | if self == other: 171 | s = (3 * self.x ** 2 + self.a) / (2 * self.y) 172 | x = s ** 2 - 2 * self.x 173 | y = s * (self.x - x) - self.y 174 | return self.__class__(x, y, self.a, self.b) 175 | 176 | # tag::source3[] 177 | def __rmul__(self, coefficient): 178 | coef = coefficient 179 | current = self # <1> 180 | result = self.__class__(None, None, self.a, self.b) # <2> 181 | while coef: 182 | if coef & 1: # <3> 183 | result += current 184 | current += current # <4> 185 | coef >>= 1 # <5> 186 | return result 187 | 188 | 189 | class Sha256Field(FieldElement): 190 | def __init__(self, num, prime=None): 191 | super().__init__(num=num, prime=P) 192 | 193 | def __repr__(self): 194 | return "{:x}".format(self.num).zfill(64) 195 | 196 | def sqrt(self): 197 | return self ** ((P + 1) // 4) 198 | 199 | 200 | class Sha256Point(Point): 201 | def __init__(self, x, y, a=None, b=None): 202 | a, b = Sha256Field(A), Sha256Field(B) 203 | if type(x) == int: 204 | super().__init__(x=Sha256Field(x), y=Sha256Field(y), a=a, b=b) 205 | else: 206 | super().__init__(x=x, y=y, a=a, b=b) # <1> 207 | 208 | # end::source7[] 209 | 210 | def __repr__(self): 211 | if self.x is None: 212 | return "Sha256Point(infinity)" 213 | else: 214 | return "Sha256Point({}, {})".format(self.x, self.y) 215 | 216 | # tag::source8[] 217 | def __rmul__(self, coefficient): 218 | coef = coefficient % N # <1> 219 | return super().__rmul__(coef) 220 | 221 | # end::source8[] 222 | 223 | # tag::source12[] 224 | def verify(self, z, sig): 225 | s_inv = pow(sig.s, N - 2, N) # <1> 226 | u = z * s_inv % N # <2> 227 | v = sig.r * s_inv % N # <3> 228 | total = u * G + v * self # <4> 229 | return total.x.num == sig.r # <5> 230 | 231 | # end::source12[] 232 | def sec(self, compressed=True): 233 | """returns the binary version of the SEC format""" 234 | if compressed: 235 | if self.y.num % 2 == 0: 236 | return b"\x02" + self.x.num.to_bytes(32, "big") 237 | else: 238 | return b"\x03" + self.x.num.to_bytes(32, "big") 239 | else: 240 | return ( 241 | b"\x04" 242 | + self.x.num.to_bytes(32, "big") 243 | + self.y.num.to_bytes(32, "big") 244 | ) 245 | 246 | # get sha256 hash of compressed public key from sec() 247 | # then do ripemd160 of that hash 248 | def hash160(self, compressed=True): 249 | return RIPEMD160.new(hashlib.sha256(self.sec(compressed)).digest()).digest() 250 | 251 | def encode_base58(self, s): 252 | count = 0 253 | for c in s: # <1> 254 | if c == 0: 255 | count += 1 256 | else: 257 | break 258 | num = int.from_bytes(s, "big") 259 | prefix = "1" * count 260 | result = "" 261 | while num > 0: # <2> 262 | num, mod = divmod(num, 58) 263 | result = BASE58_ALPHABET[mod] + result 264 | return prefix + result # <3> 265 | 266 | def encode_base58_checksum(self, b): 267 | return self.encode_base58( 268 | b + (hashlib.sha256(hashlib.sha256(b).digest()).digest())[:4] 269 | ) 270 | 271 | def address(self, compressed=True, testnet=False): 272 | """Returns the address string""" 273 | h160 = self.hash160(compressed) 274 | if testnet: 275 | prefix = b"\x6f" 276 | else: 277 | prefix = b"\x00" 278 | return self.encode_base58_checksum(prefix + h160) 279 | 280 | @classmethod 281 | def parse(self, sec_bin): 282 | """returns a Point object from a SEC binary (not hex)""" 283 | if sec_bin[0] == 4: # <1> 284 | x = int.from_bytes(sec_bin[1:33], "big") 285 | y = int.from_bytes(sec_bin[33:65], "big") 286 | return Sha256Point(x=x, y=y) 287 | is_even = sec_bin[0] == 2 # <2> 288 | x = Sha256Field(int.from_bytes(sec_bin[1:], "big")) 289 | # right side of the equation y^2 = x^3 + 7 290 | alpha = x ** 3 + Sha256Field(B) 291 | # solve for left side 292 | beta = alpha.sqrt() # <3> 293 | if beta.num % 2 == 0: # <4> 294 | even_beta = beta 295 | odd_beta = Sha256Field(P - beta.num) 296 | else: 297 | even_beta = Sha256Field(P - beta.num) 298 | odd_beta = beta 299 | if is_even: 300 | return Sha256Point(x, even_beta) 301 | else: 302 | return Sha256Point(x, odd_beta) 303 | 304 | 305 | G = Sha256Point( 306 | 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 307 | 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, 308 | ) 309 | 310 | 311 | class Signature: 312 | def __init__(self, r, s): 313 | self.r = r 314 | self.s = s 315 | 316 | def __repr__(self): 317 | return "Signature({:x},{:x})".format(self.r, self.s) 318 | 319 | def der(self): 320 | rbin = self.r.to_bytes(32, byteorder="big") 321 | # remove all null bytes at the beginning 322 | rbin = rbin.lstrip(b"\x00") 323 | # if rbin has a high bit, add a \x00 324 | if rbin[0] & 0x80: 325 | rbin = b"\x00" + rbin 326 | result = bytes([2, len(rbin)]) + rbin # <1> 327 | sbin = self.s.to_bytes(32, byteorder="big") 328 | # remove all null bytes at the beginning 329 | sbin = sbin.lstrip(b"\x00") 330 | # if sbin has a high bit, add a \x00 331 | if sbin[0] & 0x80: 332 | sbin = b"\x00" + sbin 333 | result += bytes([2, len(sbin)]) + sbin 334 | return bytes([0x30, len(result)]) + result 335 | 336 | @classmethod 337 | def parse(cls, signature_bin): 338 | s = BytesIO(signature_bin) 339 | compound = s.read(1)[0] 340 | if compound != 0x30: 341 | raise SyntaxError("Bad Signature") 342 | length = s.read(1)[0] 343 | if length + 2 != len(signature_bin): 344 | raise SyntaxError("Bad Signature Length") 345 | marker = s.read(1)[0] 346 | if marker != 0x02: 347 | raise SyntaxError("Bad Signature") 348 | rlength = s.read(1)[0] 349 | r = int.from_bytes(s.read(rlength), "big") 350 | marker = s.read(1)[0] 351 | if marker != 0x02: 352 | raise SyntaxError("Bad Signature") 353 | slength = s.read(1)[0] 354 | s = int.from_bytes(s.read(slength), "big") 355 | if len(signature_bin) != 6 + rlength + slength: 356 | raise SyntaxError("Signature too long") 357 | return cls(r, s) 358 | 359 | 360 | class PrivateKey: 361 | def __init__(self, secret): 362 | self.secret = secret 363 | self.point = secret * G # <1> 364 | 365 | def hex(self): 366 | return "{:x}".format(self.secret).zfill(64) 367 | 368 | # end::source13[] 369 | 370 | # tag::source14[] 371 | def sign(self, z): 372 | k = self.deterministic_k(z) # <1> 373 | r = (k * G).x.num 374 | k_inv = pow(k, N - 2, N) 375 | s = (z + r * self.secret) * k_inv % N 376 | if s > N / 2: 377 | s = N - s 378 | return Signature(r, s) 379 | 380 | def deterministic_k(self, z): 381 | k = b"\x00" * 32 382 | v = b"\x01" * 32 383 | if z > N: 384 | z -= N 385 | z_bytes = z.to_bytes(32, "big") 386 | secret_bytes = self.secret.to_bytes(32, "big") 387 | s256 = hashlib.sha256 388 | k = hmac.new(k, v + b"\x00" + secret_bytes + z_bytes, s256).digest() 389 | v = hmac.new(k, v, s256).digest() 390 | k = hmac.new(k, v + b"\x01" + secret_bytes + z_bytes, s256).digest() 391 | v = hmac.new(k, v, s256).digest() 392 | while True: 393 | v = hmac.new(k, v, s256).digest() 394 | candidate = int.from_bytes(v, "big") 395 | if candidate >= 1 and candidate < N: 396 | return candidate # <2> 397 | k = hmac.new(k, v + b"\x00", s256).digest() 398 | v = hmac.new(k, v, s256).digest() 399 | 400 | # end::source14[] 401 | -------------------------------------------------------------------------------- /Blockchain/Backend/core/blockchain.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2021 Codiesalert.com 3 | These scripts should be used for commercial purpose without Codies Alert Permission 4 | Any violations may lead to legal action 5 | """ 6 | import sys 7 | 8 | sys.path.append("/Users/Vmaha/Desktop/Bitcoin") 9 | 10 | import copy 11 | import configparser 12 | from Blockchain.Backend.core.block import Block 13 | from Blockchain.Backend.core.blockheader import BlockHeader 14 | from Blockchain.Backend.util.util import hash256, merkle_root, target_to_bits, bits_to_target 15 | from Blockchain.Backend.core.database.database import BlockchainDB, NodeDB 16 | from Blockchain.Backend.core.Tx import CoinbaseTx, Tx 17 | from multiprocessing import Process, Manager 18 | from Blockchain.Frontend.run import main 19 | from Blockchain.Backend.core.network.syncManager import syncManager 20 | from Blockchain.client.autoBroadcastTX import autoBroadcast 21 | import time 22 | 23 | ZERO_HASH = "0" * 64 24 | VERSION = 1 25 | INITIAL_TARGET = 0x0000FFFF00000000000000000000000000000000000000000000000000000000 26 | MAX_TARGET = 0x0000ffff00000000000000000000000000000000000000000000000000000000 27 | 28 | """ 29 | # Calculate new Target to keep our Block mine time under 20 seconds 30 | # Reset Block Difficulty after every 10 Blocks 31 | """ 32 | AVERAGE_BLOCK_MINE_TIME = 20 33 | RESET_DIFFICULTY_AFTER_BLOCKS = 10 34 | AVERAGE_MINE_TIME = AVERAGE_BLOCK_MINE_TIME * RESET_DIFFICULTY_AFTER_BLOCKS 35 | 36 | class Blockchain: 37 | def __init__(self, utxos, MemPool, newBlockAvailable, secondryChain): 38 | self.utxos = utxos 39 | self.MemPool = MemPool 40 | self.newBlockAvailable = newBlockAvailable 41 | self.secondryChain = secondryChain 42 | self.current_target = INITIAL_TARGET 43 | self.bits = target_to_bits(INITIAL_TARGET) 44 | 45 | def write_on_disk(self, block): 46 | blockchainDB = BlockchainDB() 47 | blockchainDB.write(block) 48 | 49 | def fetch_last_block(self): 50 | blockchainDB = BlockchainDB() 51 | return blockchainDB.lastBlock() 52 | 53 | def GenesisBlock(self): 54 | BlockHeight = 0 55 | prevBlockHash = ZERO_HASH 56 | self.addBlock(BlockHeight, prevBlockHash) 57 | 58 | """ Start the Sync Node """ 59 | def startSync(self, block = None): 60 | try: 61 | node = NodeDB() 62 | portList = node.read() 63 | 64 | for port in portList: 65 | if localHostPort != port: 66 | sync = syncManager(localHost, port, secondryChain = self.secondryChain) 67 | try: 68 | if block: 69 | sync.publishBlock(localHostPort - 1, port, block) 70 | else: 71 | sync.startDownload(localHostPort - 1, port, True) 72 | 73 | except Exception as err: 74 | pass 75 | 76 | except Exception as err: 77 | pass 78 | 79 | """ Keep Track of all the unspent Transaction in cache memory for fast retrival""" 80 | def store_uxtos_in_cache(self): 81 | for tx in self.addTransactionsInBlock: 82 | print(f"Transaction added {tx.TxId} ") 83 | self.utxos[tx.TxId] = tx 84 | 85 | def remove_spent_Transactions(self): 86 | for txId_index in self.remove_spent_transactions: 87 | if txId_index[0].hex() in self.utxos: 88 | 89 | if len(self.utxos[txId_index[0].hex()].tx_outs) < 2: 90 | print(f" Spent Transaction removed {txId_index[0].hex()} ") 91 | del self.utxos[txId_index[0].hex()] 92 | else: 93 | prev_trans = self.utxos[txId_index[0].hex()] 94 | self.utxos[txId_index[0].hex()] = prev_trans.tx_outs.pop( 95 | txId_index[1] 96 | ) 97 | 98 | """ Check if it is a double spending Attempt """ 99 | def doubleSpendingAttempt(self, tx): 100 | for txin in tx.tx_ins: 101 | if txin.prev_tx not in self.prevTxs and txin.prev_tx.hex() in self.utxos: 102 | self.prevTxs.append(txin.prev_tx) 103 | else: 104 | return True 105 | 106 | """ Read Transactions from Memory Pool""" 107 | def read_transaction_from_memorypool(self): 108 | self.Blocksize = 80 109 | self.TxIds = [] 110 | self.addTransactionsInBlock = [] 111 | self.remove_spent_transactions = [] 112 | self.prevTxs = [] 113 | deleteTxs = [] 114 | 115 | tempMemPool = dict(self.MemPool) 116 | 117 | if self.Blocksize < 1000000: 118 | for tx in tempMemPool: 119 | if not self.doubleSpendingAttempt(tempMemPool[tx]): 120 | tempMemPool[tx].TxId = tx 121 | self.TxIds.append(bytes.fromhex(tx)) 122 | self.addTransactionsInBlock.append(tempMemPool[tx]) 123 | self.Blocksize += len(tempMemPool[tx].serialize()) 124 | 125 | for spent in tempMemPool[tx].tx_ins: 126 | self.remove_spent_transactions.append([spent.prev_tx, spent.prev_index]) 127 | else: 128 | deleteTxs.append(tx) 129 | 130 | for txId in deleteTxs: 131 | del self.MemPool[txId] 132 | 133 | 134 | """ Remove Transactions from Memory pool """ 135 | def remove_transactions_from_memorypool(self): 136 | for tx in self.TxIds: 137 | if tx.hex() in self.MemPool: 138 | del self.MemPool[tx.hex()] 139 | 140 | def convert_to_json(self): 141 | self.TxJson = [] 142 | for tx in self.addTransactionsInBlock: 143 | self.TxJson.append(tx.to_dict()) 144 | 145 | def calculate_fee(self): 146 | self.input_amount = 0 147 | self.output_amount = 0 148 | """ Calculate Input Amount """ 149 | for TxId_index in self.remove_spent_transactions: 150 | if TxId_index[0].hex() in self.utxos: 151 | self.input_amount += ( 152 | self.utxos[TxId_index[0].hex()].tx_outs[TxId_index[1]].amount 153 | ) 154 | 155 | """ Calculate Output Amount """ 156 | for tx in self.addTransactionsInBlock: 157 | for tx_out in tx.tx_outs: 158 | self.output_amount += tx_out.amount 159 | 160 | self.fee = self.input_amount - self.output_amount 161 | 162 | def buildUTXOS(self): 163 | allTxs = {} 164 | blocks = BlockchainDB().read() 165 | 166 | for block in blocks: 167 | for tx in block['Txs']: 168 | allTxs[tx['TxId']] = tx 169 | 170 | for block in blocks: 171 | for tx in block['Txs']: 172 | for txin in tx['tx_ins']: 173 | if txin['prev_tx'] != "0000000000000000000000000000000000000000000000000000000000000000": 174 | if len(allTxs[txin['prev_tx']]['tx_outs']) < 2: 175 | del allTxs[txin['prev_tx']] 176 | else: 177 | txOut = allTxs[txin['prev_tx']]['tx_outs'] 178 | txOut.pop(txin['prev_index']) 179 | 180 | for tx in allTxs: 181 | self.utxos[tx] = Tx.to_obj(allTxs[tx]) 182 | 183 | 184 | def settargetWhileBooting(self): 185 | bits, timestamp = self.getTargetDifficultyAndTimestamp() 186 | self.bits = bytes.fromhex(bits) 187 | self.current_target = bits_to_target(self.bits) 188 | 189 | def getTargetDifficultyAndTimestamp(self, BlockHeight = None): 190 | if BlockHeight: 191 | blocks = BlockchainDB().read() 192 | bits = blocks[BlockHeight]['BlockHeader']['bits'] 193 | timestamp = blocks[BlockHeight]['BlockHeader']['timestamp'] 194 | else: 195 | block = BlockchainDB().lastBlock() 196 | bits = block['BlockHeader']['bits'] 197 | timestamp = block['BlockHeader']['timestamp'] 198 | return bits, timestamp 199 | 200 | 201 | def adjustTargetDifficulty(self, BlockHeight): 202 | if BlockHeight % 10 == 0: 203 | bits, timestamp = self.getTargetDifficultyAndTimestamp(BlockHeight - 10) 204 | Lastbits, lastTimestamp = self.getTargetDifficultyAndTimestamp() 205 | 206 | lastTarget = bits_to_target(bytes.fromhex(bits)) 207 | AverageBlockMineTime = lastTimestamp - timestamp 208 | timeRatio = AverageBlockMineTime / AVERAGE_MINE_TIME 209 | 210 | NEW_TARGET = int(format(int(lastTarget * timeRatio))) 211 | 212 | if NEW_TARGET > MAX_TARGET: 213 | NEW_TARGET = MAX_TARGET 214 | 215 | self.bits = target_to_bits(NEW_TARGET) 216 | self.current_target = NEW_TARGET 217 | 218 | def BroadcastBlock(self, block): 219 | self.startSync(block) 220 | 221 | def LostCompetition(self): 222 | deleteBlock = [] 223 | tempBlocks = dict(self.newBlockAvailable) 224 | 225 | for newblock in tempBlocks: 226 | block = tempBlocks[newblock] 227 | deleteBlock.append(newblock) 228 | 229 | BlockHeaderObj = BlockHeader(block.BlockHeader.version, 230 | block.BlockHeader.prevBlockHash, 231 | block.BlockHeader.merkleRoot, 232 | block.BlockHeader.timestamp, 233 | block.BlockHeader.bits, 234 | block.BlockHeader.nonce) 235 | 236 | if BlockHeaderObj.validateBlock(): 237 | for idx, tx in enumerate(block.Txs): 238 | self.utxos[tx.id()] = tx.serialize() 239 | block.Txs[idx].TxId = tx.id() 240 | 241 | """ Remove Spent Transactions """ 242 | for txin in tx.tx_ins: 243 | if txin.prev_tx.hex() in self.utxos: 244 | del self.utxos[txin.prev_tx.hex()] 245 | 246 | if tx.id() in self.MemPool: 247 | del self.MemPool[tx.id()] 248 | 249 | block.Txs[idx] = tx.to_dict() 250 | 251 | block.BlockHeader.to_hex() 252 | BlockchainDB().write([block.to_dict()]) 253 | else: 254 | """ Resolve the Conflict b/w ther Miners """ 255 | orphanTxs = {} 256 | validTxs = {} 257 | if self.secondryChain: 258 | addBlocks = [] 259 | addBlocks.append(block) 260 | prevBlockhash = block.BlockHeader.prevBlockHash.hex() 261 | count = 0 262 | 263 | while count != len(self.secondryChain): 264 | if prevBlockhash in self.secondryChain: 265 | addBlocks.append(self.secondryChain[prevBlockhash]) 266 | prevBlockhash = self.secondryChain[prevBlockhash].BlockHeader.prevBlockHash.hex() 267 | count += 1 268 | 269 | blockchain = BlockchainDB().read() 270 | lastValidBlock = blockchain[-len(addBlocks)] 271 | 272 | if lastValidBlock['BlockHeader']['blockHash'] == prevBlockhash: 273 | for i in range(len(addBlocks) - 1): 274 | orphanBlock = blockchain.pop() 275 | 276 | for tx in orphanBlock['Txs']: 277 | if tx['TxId'] in self.utxos: 278 | del self.utxos[tx['TxId']] 279 | 280 | """ Don't Include COINBASE TX because it didn't come from MEMPOOL""" 281 | if tx['tx_ins'][0]['prev_tx'] != "0000000000000000000000000000000000000000000000000000000000000000": 282 | orphanTxs[tx['TxId']] = tx 283 | 284 | BlockchainDB().update(blockchain) 285 | 286 | for Bobj in addBlocks[::-1]: 287 | validBlock = copy.deepcopy(Bobj) 288 | validBlock.BlockHeader.to_hex() 289 | 290 | for index, tx in enumerate(validBlock.Txs): 291 | validBlock.Txs[index].TxId = tx.id() 292 | self.utxos[tx.id()] = tx 293 | 294 | """ Remove Spent Transactions """ 295 | for txin in tx.tx_ins: 296 | if txin.prev_tx.hex() in self.utxos: 297 | del self.utxos[txin.prev_tx.hex()] 298 | 299 | if tx.tx_ins[0].prev_tx.hex() != "0000000000000000000000000000000000000000000000000000000000000000": 300 | validTxs[validBlock.Txs[index].TxId] = tx 301 | 302 | validBlock.Txs[index] = tx.to_dict() 303 | 304 | BlockchainDB().write([validBlock.to_dict()]) 305 | 306 | """ Add Transactoins Back to MemPool """ 307 | for TxId in orphanTxs: 308 | if TxId not in validTxs: 309 | self.MemPool[TxId] = Tx.to_obj(orphanTxs[TxId]) 310 | 311 | self.secondryChain[newblock] = block 312 | 313 | 314 | for blockHash in deleteBlock: 315 | del self.newBlockAvailable[blockHash] 316 | 317 | def addBlock(self, BlockHeight, prevBlockHash): 318 | self.read_transaction_from_memorypool() 319 | self.calculate_fee() 320 | timestamp = int(time.time()) 321 | coinbaseInstance = CoinbaseTx(BlockHeight) 322 | coinbaseTx = coinbaseInstance.CoinbaseTransaction() 323 | self.Blocksize += len(coinbaseTx.serialize()) 324 | 325 | coinbaseTx.tx_outs[0].amount = coinbaseTx.tx_outs[0].amount + self.fee 326 | 327 | self.TxIds.insert(0, bytes.fromhex(coinbaseTx.id())) 328 | self.addTransactionsInBlock.insert(0, coinbaseTx) 329 | 330 | merkleRoot = merkle_root(self.TxIds)[::-1].hex() 331 | self.adjustTargetDifficulty(BlockHeight) 332 | blockheader = BlockHeader( 333 | VERSION, prevBlockHash, merkleRoot, timestamp, self.bits, nonce = 0 334 | ) 335 | competitionOver = blockheader.mine(self.current_target, self.newBlockAvailable) 336 | 337 | if competitionOver: 338 | self.LostCompetition() 339 | else: 340 | newBlock = Block(BlockHeight, self.Blocksize, blockheader, len(self.addTransactionsInBlock), 341 | self.addTransactionsInBlock) 342 | blockheader.to_bytes() 343 | block = copy.deepcopy(newBlock) 344 | broadcastNewBlock = Process(target = self.BroadcastBlock, args = (block, )) 345 | broadcastNewBlock.start() 346 | blockheader.to_hex() 347 | self.remove_spent_Transactions() 348 | self.remove_transactions_from_memorypool() 349 | self.store_uxtos_in_cache() 350 | self.convert_to_json() 351 | 352 | print( 353 | f"Block {BlockHeight} mined successfully with Nonce value of {blockheader.nonce}" 354 | ) 355 | self.write_on_disk( 356 | [ 357 | Block( 358 | BlockHeight, self.Blocksize, blockheader.__dict__, len(self.TxJson), self.TxJson 359 | ).__dict__ 360 | ] 361 | ) 362 | 363 | def main(self): 364 | lastBlock = self.fetch_last_block() 365 | if lastBlock is None: 366 | self.GenesisBlock() 367 | 368 | while True: 369 | lastBlock = self.fetch_last_block() 370 | BlockHeight = lastBlock["Height"] + 1 371 | print(f"Current Block Height is is {BlockHeight}") 372 | prevBlockHash = lastBlock["BlockHeader"]["blockHash"] 373 | self.addBlock(BlockHeight, prevBlockHash) 374 | 375 | if __name__ == "__main__": 376 | 377 | """ read configuration file """ 378 | config = configparser.ConfigParser() 379 | config.read('config.ini') 380 | localHost = config['DEFAULT']['host'] 381 | localHostPort = int(config['MINER']['port']) 382 | simulateBTC = bool(config['MINER']['simulateBTC']) 383 | webport = int(config['Webhost']['port']) 384 | 385 | with Manager() as manager: 386 | utxos = manager.dict() 387 | MemPool = manager.dict() 388 | newBlockAvailable = manager.dict() 389 | secondryChain = manager.dict() 390 | 391 | webapp = Process(target=main, args=(utxos, MemPool, webport, localHostPort)) 392 | webapp.start() 393 | 394 | """ Start Server and Listen for miner requests """ 395 | sync = syncManager(localHost, localHostPort, newBlockAvailable, secondryChain, MemPool) 396 | startServer = Process(target = sync.spinUpTheServer) 397 | startServer.start() 398 | 399 | blockchain = Blockchain(utxos, MemPool, newBlockAvailable, secondryChain) 400 | blockchain.startSync() 401 | blockchain.buildUTXOS() 402 | 403 | if simulateBTC: 404 | autoBroadcastTxs = Process(target = autoBroadcast) 405 | autoBroadcastTxs.start() 406 | 407 | blockchain.settargetWhileBooting() 408 | blockchain.main() 409 | --------------------------------------------------------------------------------