├── .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 |
8 |
9 | {% for Tx in allTransactions %}
10 |
11 |
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 |
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 |
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 |
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 |
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 | 
11 |
12 |
13 | 
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 |
17 |
18 |
{{ Txs|length }}
19 |
{{ amount/100000000 }} BTC
20 |
21 |
22 |
23 |
24 | {% for blk in Txs %}
25 |
26 |
27 |
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 |
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 |
42 |
43 |
44 |
45 |
Inputs
46 |
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 |
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 |
49 | {% for blk in block['Txs'] %}
50 |
51 |
52 |
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 |
--------------------------------------------------------------------------------