-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
Added/blockchain basics in python #9465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
a76f89d
e41e32d
b3c81a1
2fe4801
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Building a Transaction Representation | ||
|
||
Welcome to this hands-on lesson where you'll embark on the journey of constructing your own blockchain in Python! This tutorial assumes a prior understanding of Python syntax, functions, loops, library imports, and class construction. However, we've included some hints along the way to assist you. If you're new to Python, you may find it beneficial to [acquire some foundational Python knowledge through geeksforgeeks](https://www.geeksforgeeks.org/python-programming-language/) | ||
|
||
## The Role of Transactions | ||
|
||
Blockchain technology introduces a novel approach to securely store and transmit data. Most notably, it excels at managing transactions, which involve exchanges of information between two parties. Before we dive into the creation of our blockchain, let's consider an effective way to represent a transaction like the one illustrated below: | ||
|
||
**Transaction Representation** | ||
|
||
Consider the following transaction details: | ||
|
||
- **Amount:** 20 | ||
- **Sender:** Add | ||
- **Receiver:** White | ||
|
||
In this scenario, Add aims to transfer 20 units of a particular currency to White. To represent this transaction effectively in Python, we opt for a data type that suits its structure. | ||
|
||
The ideal choice for representing such transactions is by utilizing a Python dictionary. This dictionary can hold keys corresponding to the essential fields and values that contain transaction-specific information. | ||
|
||
These transactions are commonly stored within a component known as the "mempool." The mempool serves as a reservoir of pending transactions, which miners consult when determining the set of transactions they intend to validate. | ||
|
||
|
||
### Instructions | ||
|
||
#### Step 1: Creating a Transaction | ||
|
||
To begin, let's craft a transaction and incorporate it into the `mempool`. We'll name this new transaction `my_transaction` and assign key-value pairs for `amount`, `sender`, and `receiver`. | ||
|
||
**Hint:** In Python, you can create a dictionary using the following syntax: `dictionary = {}` | ||
|
||
#### Step 2: Joining the Mempool | ||
|
||
Next, let's include `my_transaction` within the `mempool` list. | ||
|
||
**Hint:** You can add an item to a Python list using the following syntax: `list.append(element)` | ||
|
||
#### Step 3: Compiling Block Transactions | ||
|
||
Now, create a fresh list named `block_transactions` and populate it with three transactions sourced from the `mempool`. This step will prepare the transactions for future integration into our evolving Block structure. | ||
|
||
By following these steps, you'll gain hands-on experience in managing transactions within the blockchain and laying the groundwork for their incorporation into Blocks. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
transaction1 = { | ||
'amount': '20', | ||
'sender': 'Add', | ||
'receiver': 'White'} | ||
transaction2 = { | ||
'amount': '200', | ||
'sender': 'White', | ||
'receiver': 'Add'} | ||
transaction3 = { | ||
'amount': '300', | ||
'sender': 'Alice', | ||
'receiver': 'Timothy' } | ||
transaction4 = { | ||
'amount': '300', | ||
'sender': 'Rodrigo', | ||
'receiver': 'Thomas' } | ||
transaction5 = { | ||
'amount': '200', | ||
'sender': 'Timothy', | ||
'receiver': 'Thomas' } | ||
|
||
|
||
mempool = [transaction1, transaction2, transaction3, transaction4, transaction5] | ||
|
||
# add your code below | ||
my_transaction = { | ||
'amount': '500', | ||
'sender': 'name_1', | ||
'receiver': 'name_2' | ||
} | ||
|
||
mempool.append(my_transaction) | ||
|
||
block_transactions = [transaction1, transaction3, my_transaction] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Building Blocks | ||
|
||
Now, let's consider an effective approach to represent a block in Python. Instead of using a large dictionary to store our data, we can leverage object-oriented programming principles and create a Block Class. This Block Class will facilitate the straightforward creation of new blocks. | ||
|
||
Remember that a Block encompasses the following fundamental properties: | ||
|
||
Timestamp | ||
Transaction | ||
Hash | ||
Previous Hash | ||
Nonce | ||
In this exercise, we'll be crafting the default constructor for the Block class within our Mini-Blockchain. | ||
|
||
# Building Blocks and Managing Timestamps | ||
|
||
In this guide, you will learn how to incorporate timestamps and initialize a Block class for your Mini-Blockchain project. | ||
|
||
## Introduction | ||
|
||
A blockchain relies on the structured arrangement of blocks, each containing vital information. We'll work on integrating timestamps into your blockchain and create a Block class to store essential blockchain data. | ||
|
||
### Step 1: Importing the `datetime` Module | ||
|
||
Every `Block` in the blockchain is associated with a timestamp, representing its creation time. To generate this timestamp dynamically, we need to import the `datetime` module from the `datetime` library. | ||
|
||
**Hint:** To make a module accessible in your code, you must import it from the respective library. Use the following format to import a specific module: | ||
|
||
```python | ||
from datetime import datetime | ||
|
||
#### Step: 2 | ||
Inside the [datetime module](https://docs.python.org/2/library/datetime.html) there is a `.now()` method that returns the current date and time. | ||
|
||
Call the `datetime` module’s `.now()` method to print out the current date and time. | ||
|
||
###### Hint: | ||
The appropriate way to call this method is `datetime.now()` enclosed in a `print()` statement. | ||
|
||
#### Step: 3 | ||
Now let’s work on creating our `Block`. We will be passing `transactions` and `previous_hash` to the default constructor each time a `Block` is created. | ||
|
||
Complete the `__init__()` method inside the Block class by initializing the following instance variables: | ||
|
||
- `transactions` | ||
- `previous_hash` | ||
- `nonce` (with a default value of `0`). | ||
|
||
###### Hint: | ||
The header for the function should look as follows: | ||
|
||
`def __init__(self, transactions, previous_hash, nonce = 0):` | ||
|
||
Be sure to initialize all the variables as well: | ||
|
||
```def __init__(self, value): | ||
# Initialization: | ||
self.value = value``` | ||
|
||
#### Step: 4 | ||
Inside the `__init__()` method, create a `timestamp` instance variable that stores the current date and time. | ||
|
||
###### Hint: | ||
Call the `.now()` method from the `datetime` module and store the result in `timestamp`. | ||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Import the datetime module from the datetime library | ||
from datetime import datetime | ||
|
||
# Print the current date and time | ||
print(datetime.now()) | ||
|
||
# Create a Block class | ||
class Block: | ||
# Initialize a timestamp variable with a default value of 0 | ||
timestamp = 0 | ||
|
||
# Default constructor for the Block class | ||
def __init__(self, transactions, previous_hash, nonce=0): | ||
# Initialize instance variables | ||
self.transactions = transactions # Store transaction data | ||
self.previous_hash = previous_hash # Store the hash of the previous block | ||
self.nonce = nonce # Initialize the nonce with a default value of 0 | ||
|
||
# Set the timestamp to the current date and time | ||
self.timestamp = datetime.now() | ||
|
||
# This is the end of the Block class definition | ||
|
||
# There's an indentation error on the "add comments explaining everystep" line, so I've removed it for clarity. | ||
|
||
# The code defines a Block class with a constructor that initializes instance variables such as transactions, previous_hash, nonce, and timestamp. The timestamp is set to the current date and time using the datetime module. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Blockchain Summary | ||
Congratulations! You have completed all the steps required to build a basic blockchain! In this exercise, we will bring the key parts together to review what we have built so far. | ||
|
||
*Note: * The blockchain we have built only exists on a local machine. It is important to know that actual blockchain applications operate on multiple computers in a decentralized manner. | ||
|
||
### Instructions | ||
|
||
|
||
#### Step: 1 | ||
Create a Blockchain object named `local_blockchain`. Verify that this automatically creates a Genesis Block by printing out the contents of `local_blockchain`. | ||
|
||
###### Hint: | ||
Use the `.print_blocks()` method to print out the contents of the blockchain. | ||
|
||
#### Step: 2 | ||
Individually add `block_one_transactions`, `block_two_transactions`, and `block_three_transactions` respectively into `local_blockchain`. Print out the contents of `local_blockchain` to see what the block holds. | ||
|
||
###### Hint: | ||
Use the method `.add_block(transactions)` to add blocks that contain the required transactions. | ||
|
||
#### Step: 3 | ||
Modify the second block you added in `local_blockchain` by changing the block’s transactions to `fake_transactions`. Check to see if the blockchain is still valid using the correct method. | ||
|
||
###### Hint: | ||
You can access the block by indexing into `local_blockchain.chain`. You can validate the block using the `.validate_chain()` method. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Import the datetime module for timestamp and hashlib module for SHA-256 hashing | ||
import datetime | ||
from hashlib import sha256 | ||
|
||
# Create a Block class | ||
class Block: | ||
# Initialize the Block object with transactions and the previous block's hash | ||
def __init__(self, transactions, previous_hash): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
# Set the timestamp to the current date and time | ||
self.time_stamp = datetime.datetime.now() | ||
self.transactions = transactions # Store transaction data | ||
self.previous_hash = previous_hash # Store the hash of the previous block | ||
self.nonce = 0 # Initialize the nonce (number used once) to 0 | ||
self.hash = self.generate_hash() # Compute and store the block's hash | ||
|
||
# Generate a hash for the block | ||
def generate_hash(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: |
||
# Create a block header by combining timestamp, transactions, previous hash, and nonce | ||
block_header = str(self.time_stamp) + str(self.transactions) + str(self.previous_hash) + str(self.nonce) | ||
# Calculate the SHA-256 hash of the block header | ||
block_hash = sha256(block_header.encode()) | ||
return block_hash.hexdigest() # Return the hexadecimal representation of the hash | ||
|
||
# Print the contents of the block | ||
def print_contents(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: |
||
print("timestamp:", self.time_stamp) | ||
print("transactions:", self.transactions) | ||
print("current hash:", self.generate_hash()) | ||
print("previous hash:", self.previous_hash) | ||
|
||
# This is the end of the Block class definition | ||
|
||
# Example usage: | ||
# Create a new block with some sample transactions and a previous block's hash | ||
transactions_data = "Sample transactions go here" | ||
previous_block_hash = "Previous block's hash goes here" | ||
block = Block(transactions_data, previous_block_hash) | ||
|
||
# Print the contents of the block | ||
block.print_contents() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Import the Block class from block.py | ||
from block import Block | ||
|
||
# Create a Blockchain class | ||
class Blockchain: | ||
# Constructor to initialize the blockchain | ||
def __init__(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: |
||
self.chain = [] # List to hold blocks in the blockchain | ||
self.all_transactions = [] # List to store all transactions across blocks | ||
self.genesis_block() # Create the genesis block to start the blockchain | ||
|
||
# Create the genesis block (the first block in the blockchain) | ||
def genesis_block(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: |
||
transactions = {} # Transactions are empty for the genesis block | ||
genesis_block = Block(transactions, "0") # Create a new Block object for the genesis block | ||
self.chain.append(genesis_block) # Add the genesis block to the blockchain | ||
return self.chain | ||
|
||
# Function to print the contents of all blocks in the blockchain | ||
def print_blocks(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: |
||
for i in range(len(self.chain)): | ||
current_block = self.chain[i] | ||
print("Block {} {}".format(i, current_block)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned in the Contributing Guidelines, please do not use printf style formatting or |
||
current_block.print_contents() # Call the print_contents() method of the Block class to print block details | ||
|
||
# Function to add a new block to the blockchain | ||
def add_block(self, transactions): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: Please provide type hint for the parameter: |
||
previous_block_hash = self.chain[len(self.chain) - 1].hash # Get the hash of the previous block | ||
new_block = Block(transactions, previous_block_hash) # Create a new Block with the provided transactions | ||
self.chain.append(new_block) # Add the new block to the blockchain | ||
|
||
# Function to validate the integrity of the blockchain | ||
def validate_chain(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: |
||
for i in range(1, len(self.chain)): | ||
current = self.chain[i] | ||
previous = self.chain[i - 1] | ||
if (current.hash != current.generate_hash()): | ||
print("The current hash of the block does not equal the generated hash of the block.") | ||
return False | ||
if (current.previous_hash != previous.generate_hash()): | ||
print("The previous block's hash does not equal the previous hash value stored in the current block.") | ||
return False | ||
return True | ||
|
||
# Function to perform proof of work (mining) | ||
def proof_of_work(self, block, difficulty=2): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file Please provide return type hint for the function: Please provide type hint for the parameter: Please provide type hint for the parameter: |
||
self.proof = block.generate_hash() # Calculate the hash of the block | ||
while self.proof[:difficulty] != '0' * difficulty: | ||
block.nonce += 1 # Increment the nonce value | ||
self.proof = block.generate_hash() # Recalculate the hash | ||
block.nonce = 0 # Reset the nonce value | ||
return self.proof | ||
|
||
# This is the end of the Blockchain class definition |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Understanding Consensus Algorithms | ||
|
||
Consensus algorithms are at the heart of blockchain technology. They are the mechanisms that enable multiple nodes (computers) in a decentralized network to agree on the state of a shared ledger, ensuring data integrity and security. In this README, we will explore the concept of consensus algorithms and their importance in blockchain networks. | ||
|
||
## Table of Contents | ||
|
||
1. [What Is Consensus?](#what-is-consensus) | ||
2. [Why Do We Need Consensus Algorithms?](#why-do-we-need-consensus-algorithms) | ||
3. [Popular Consensus Algorithms](#popular-consensus-algorithms) | ||
- [Proof of Work (PoW)](#proof-of-work-pow) | ||
- [Proof of Stake (PoS)](#proof-of-stake-pos) | ||
4. [How Consensus Algorithms Work](#how-consensus-algorithms-work) | ||
5. [Implementing Consensus Algorithms](#implementing-consensus-algorithms) | ||
6. [Conclusion](#conclusion) | ||
|
||
## What Is Consensus? | ||
|
||
Consensus, in the context of blockchain, refers to the agreement among participants (nodes) in a network about the validity of transactions and the order in which they are added to the blockchain. Achieving consensus ensures that all nodes have a consistent view of the ledger, even in a decentralized and trustless environment. | ||
|
||
## Why Do We Need Consensus Algorithms? | ||
|
||
Consensus algorithms serve several critical purposes in blockchain networks: | ||
|
||
- **Security:** They prevent malicious actors from tampering with the blockchain, making it highly secure and resistant to attacks. | ||
- **Data Integrity:** Consensus ensures that the data stored in the blockchain is accurate and consistent. | ||
- **Decentralization:** They enable decentralized control and decision-making, eliminating the need for a central authority. | ||
|
||
## Popular Consensus Algorithms | ||
|
||
### Proof of Work (PoW) | ||
|
||
- PoW is used by Bitcoin and many other cryptocurrencies. | ||
- Miners compete to solve complex mathematical puzzles to add new blocks to the blockchain. | ||
- The first miner to solve the puzzle gets the right to add the block and is rewarded with cryptocurrency. | ||
- Energy-intensive but highly secure. | ||
|
||
### Proof of Stake (PoS) | ||
|
||
- PoS is used in Ethereum 2.0 and other cryptocurrencies. | ||
- Validators are chosen to create new blocks based on the amount of cryptocurrency they "stake" or hold. | ||
- More energy-efficient compared to PoW. | ||
- Promotes decentralization and economic incentives for validators. | ||
|
||
## How Consensus Algorithms Work | ||
|
||
Consensus algorithms work by defining a set of rules and protocols that all participants in the network must follow: | ||
|
||
1. **Transaction Propagation:** Nodes broadcast transactions to their peers on the network. | ||
2. **Validation:** Transactions are validated by nodes to ensure they meet specific criteria. | ||
3. **Block Creation:** Valid transactions are grouped into blocks. | ||
4. **Consensus Process:** Nodes participate in the consensus process to agree on the next block. | ||
5. **Block Addition:** Once consensus is reached, the new block is added to the blockchain. | ||
|
||
## Implementing Consensus Algorithms | ||
|
||
Implementing a consensus algorithm from scratch is a complex task. It involves designing protocols, handling network communication, and managing node behavior. Various blockchain development libraries and platforms, such as Ethereum and Hyperledger Fabric, provide tools to simplify the implementation of consensus algorithms. | ||
|
||
## Conclusion | ||
|
||
Consensus algorithms are the foundation of blockchain technology, ensuring that decentralized networks maintain trust and security. Understanding the nuances of different consensus mechanisms is essential for blockchain developers and enthusiasts alike, as it impacts the scalability, security, and energy efficiency of blockchain networks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please provide return type hint for the function:
__init__
. If the function does not return a value, please provide the type hint as:def function() -> None:
Please provide type hint for the parameter:
transactions
Please provide type hint for the parameter:
previous_hash
Please provide type hint for the parameter:
nonce