Commit fb9756fb authored by Saswat's avatar Saswat

node implementation of blockchain handling

parent 1406a81e
from utils import *
from simulate import Event
class Block:
def __init__(self, ID, transactions, previous_block_ID):
def __init__(self, peer, ID, transactions, previous_block_ID):
# Initialize block attributes
self.blk_Id = ID
self.transactions = transactions
self.prev_blk_Id = previous_block_ID
self.pow_user_id = peer
return
class Blockchain:
def __init__(self):
# Initialize blockchain attributes
self.chain = {}
self.genensis_block = Block(0, [], -1)
self.chain[self.genensis_block.blk_Id] = self.genensis_block
self.head = 0
self.len_longest_chain = 1
self.seen_transactions = set()
self.pending_transactions = set()
self.next_pow_completion_time = 0
pass
def mine_block(peer, blockchain, longest_chain):
# Simulate PoW mining and block creation
pass
def validate_block(peer, block):
# Validate transactions in the block
pass
def resolve_forks(peer, blockchain, longest_chain):
# Resolve forks and update the longest chain
pass
def update_tree_file(peer, blockchain):
# Update tree file with block information for each node
pass
\ No newline at end of file
def get_chain_length(self, blk_Id = None):
# Return the length of the longest chain
if blk_Id is None:
curr = self.len_longest_chain
curr = blk_Id
cnt = 0
while(curr != -1):
if curr not in self.chain:
print("ERROR: Block not found in the chain")
break
curr = self.chain[curr].prev_blk_Id
cnt += 1
return cnt
def receive_txn(self, txn):
"""
Receive transaction from a neighbor
if already seen, return 0 else return 1
"""
if txn in self.seen_transactions:
return 0
else:
self.seen_transactions.add(txn_id)
self.pending_transactions.add(txn)
return 1
def verify_blk(self, blk):
"""
Verify the block
if valid, return 1 else 0
"""
return 1
def add_mined_block(self, blk):
"""
Add the mined block to the blockchain
"""
return
def
from node import Node
import random
from simulate import Event
from utils import *
from utils import sample_exponential
class Network:
def __init__(self, sim, args):
self.args = args
self.sim = sim
self.pij = float(random.randrange(10, 500)) * 0.001# speed of light propagation delay in ms
self.I = 600
self.create_nodes()
self.create_connections()
self.sim.push_event(Event(0, self.init_simulation,))
......@@ -52,7 +53,7 @@ class Network:
for i in range(self.args.num_nodes):
self.nodes.append(Node(self.sim, i, bandwidth_type[i],\
cpu_type[i], Tk[i], self.args.T_tx,\
cpu_type[i], float(self.I)/Tk[i], self.args.T_tx,\
self.args.num_nodes, self.pij))
return
......
from blockchain import Blockchain
from simulate import Event
from utils import *
from utils import sample_exponential, gen_txn_id, get_txn_id
import random
#TODO(SM): Need to bind each transaction with a time of arrival at a node
txn_id = 0
def gen_txn_id():
global txn_id
txn_id += 1
return txn_id
def get_txn_id(txn):
return txn.split(":")[0]
class Node:
def __init__(self, sim, ID, bandwidth_type, cpu_type, Tk, T_tx, num_nodes, pij):
......@@ -22,14 +15,13 @@ class Node:
self.cpuType = cpu_type
self.bandwidth_type = bandwidth_type
self.Tk = Tk
self.I = 600
self.T_tx = T_tx
self.num_nodes = num_nodes
self.pij = pij
self.neighbors = []
self.blockchain = Blockchain()
self.pending_transactions = []
def init_simulation(self):
"""
......@@ -40,8 +32,10 @@ class Node:
# schedule the first transaction
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.T_tx),\
self._event_generate_transaction))
pass
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.Tk),\
self._event_generate_block, self.blockchain.create_new_block_for_pow()))
def get_latency(self, node, data):
"""
Get the latency to send the transaction to the given node
......@@ -64,15 +58,43 @@ class Node:
m = 1024
return latency + (float(m)/cij)
def _event_generate_transaction(self, args):
"""
Generate a transaction for the given peer
Format: "TxnID: IDx pays IDy C coins"
"""
# Select a random destination node and amount
dest = self.nodeId
while dest == self.nodeId:
dest = random.randint(0, self.num_nodes)
amount = random.randint(1, self.balance + 10)
# Create a transaction and it to current nodes pending transactions
txn = str(gen_txn_id()) + ": " + str(self.nodeId) + " pays "\
+ str(dest) + " " + str(amount) + " coins"
print(self.sim.curr_time, self.nodeId, "Generated a txn:", txn)
self.pending_transactions.append(txn)
# schedule the next transaction
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.T_tx),\
self._event_generate_transaction))
# broadcast the transaction to the neighbors
self.broadcast_transaction(txn)
pass
def _event_receive_transaction(self, txn):
"""
Event to receive a transaction from a neighbor
"""
txn = txn[0]
print(self.sim.curr_time, self.nodeId, "Received transaction", get_txn_id(txn))
if txn not in self.pending_transactions:
self.pending_transactions.append(txn)
# Receive the transaction and add it to the pending transactions
# If the transaction is new, add it and broadcast to the neighbors
if self.blockchain.receive_txn(txn) == 1:
# Broadcast the received transaction to the neighbors immediately
self.broadcast_transaction(txn)
else:
......@@ -92,30 +114,57 @@ class Node:
self.sim.push_event(Event(self.sim.curr_time + self.get_latency(neighbor, txn),\
neighbor._event_receive_transaction, txn))
return
def _event_generate_transaction(self, args):
def _event_generate_block(self, blk):
"""
Generate a transaction for the given peer
Format: "TxnID: IDx pays IDy C coins"
"""
Event to perform create a block and perform PoW and broadcast it
"""
# discard the event if the time is not right
# this means this event has been overriden
if self.sim.curr_time != self.blockchain.next_pow_completion_time:
return
# Add the block it to the blockchain and broadcast it to the neighbors
self.blockchain.add_new_mined_block(blk)
self.broadcast_block(blk)
# Select a random destination node and amount
dest = self.nodeId
while dest == self.nodeId:
dest = random.randint(0, self.num_nodes)
amount = random.randint(1, self.balance + 10)
# Schedule the next block creation event
new_blk = self.blockchain.create_new_block_for_pow()
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.Tk),\
self._event_generate_block, new_blk))
return
def _event_receive_block(self, blk):
"""
Event to receive a block from a neighbor
Receive the block and validate it's transactions / hash
If valid, check if it is the longest chain
If it is the longest chain, add this block to the blockchain
Schedule the next block creation event
If not valid ignore
"""
# Create a transaction and it to current nodes pending transactions
txn = str(gen_txn_id()) + ": " + str(self.nodeId) + " pays "\
+ str(dest) + " " + str(amount) + " coins"
print(self.sim.curr_time, self.nodeId, "Generated a txn:", txn)
if self.blockchain.alread_exist(blk) or self.blockchain.verify_blk(blk) == 0:
return
self.blockchain.add_new_mined_block(blk)
print(self.sim.curr_time, self.nodeId, "Received block", blk.blkId)
chain_length = self.blockchain.get_chain_length(blk)
if chain_length > self.blockchain.len_longest_chain:
self.blockchain.len_longest_chain = self.blockchain.get_chain_length(blk)
self.blockchain.head = blk.blkId
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.Tk),\
self._event_generate_block, self.blockchain.create_new_block_for_pow()))
self.pending_transactions.append(txn)
self.broadcast_block(blk)
# schedule the next transaction
self.sim.push_event(Event(self.sim.curr_time + sample_exponential(self.T_tx),\
self._event_generate_transaction))
# broadcast the transaction to the neighbors
self.broadcast_transaction(txn)
pass
def broadcast_block(self, blk):
"""
Broadcast the block to the neighbors
"""
for neighbor in self.neighbors:
self.sim.push_event(Event(self.sim.curr_time + self.get_latency(neighbor, blk),\
neighbor._event_receive_blk, blk))
return
\ No newline at end of file
import random
def sample_exponential(mean):
return random.expovariate(1/mean)
\ No newline at end of file
return random.expovariate(1/mean)
txn_id = 0
def gen_txn_id():
global txn_id
txn_id += 1
return txn_id
def get_txn_id(txn):
return txn.split(":")[0]
blk_id = 0
def gen_blk_id():
global blk_id
blk_id += 1
return blk_id
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment