Skip to content
This repository was archived by the owner on Jul 15, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/codes/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def get_auth():
'public': wallet['public'],
}
auth_data['signature'] = sign_object(private_key, auth_data)
print('auth', auth_data)
return auth_data
except:
auth_data = {}
Expand Down
35 changes: 33 additions & 2 deletions app/codes/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,36 @@ def mine_block(self, cur, text, fees=0):

block = self.create_block(cur, block, block_hash)
return block

def mine_empty_block(self, cur, text):
"""Mine an empty block"""
print("Mining empty block")
last_block_cursor = cur.execute(
'SELECT block_index, hash, timestamp FROM blocks ORDER BY block_index DESC LIMIT 1')
last_block = last_block_cursor.fetchone()
last_block_index = last_block[0] if last_block is not None else 0
last_block_hash = last_block[1] if last_block is not None else 0
last_block_timestamp = last_block[2] if last_block is not None else 0

EMPTY_BLOCK_NONCE = 42

new_block_timestamp = int(last_block_timestamp) + 1

block = {
'index': last_block_index + 1,
'timestamp': new_block_timestamp,
'proof': EMPTY_BLOCK_NONCE,
'text': text,
# 'creator_wallet': get_node_wallet_address(),
# 'fees': fees,
'previous_hash': last_block_hash
}

block_hash = self.calculate_hash(block)
print("New block hash is ", block_hash)

block = self.create_block(cur, block, block_hash)
return block

def get_latest_ts(self, cur=None):
"""Get the timestamp of latest block"""
Expand Down Expand Up @@ -167,15 +197,16 @@ def get_last_block_hash():
con = sqlite3.connect(NEWRL_DB)
cur = con.cursor()
last_block_cursor = cur.execute(
'SELECT block_index, hash FROM blocks ORDER BY block_index DESC LIMIT 1'
'SELECT block_index, hash, timestamp FROM blocks ORDER BY block_index DESC LIMIT 1'
)
last_block = last_block_cursor.fetchone()
con.close()

if last_block is not None:
return {
'index': last_block[0],
'hash': last_block[1]
'hash': last_block[1],
'timestamp': last_block[2]
}
else:
return None
48 changes: 18 additions & 30 deletions app/codes/clock/global_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import time
import requests
import threading
from ...constants import BLOCK_TIME_INTERVAL_SECONDS, MAX_ALLOWED_TIME_DIFF_SECONDS, NO_RECEIPT_COMMITTEE_TIMEOUT, TIME_DIFF_WITH_GLOBAL
from ...constants import BLOCK_TIME_INTERVAL_SECONDS, MAX_ALLOWED_TIME_DIFF_SECONDS, NO_RECEIPT_COMMITTEE_TIMEOUT, TIME_DIFF_WITH_GLOBAL, TIME_DIFF_WITH_GLOBAL_FILE, TIME_MINER_BROADCAST_INTERVAL


def get_global_epoch():
Expand All @@ -18,39 +18,27 @@ def get_local_epoch():
return epoch_time


def no_receipt_timeout():
print('No receipts received. Timing out.')


def mine():
print('Mining block.')


def start_receipt_timeout():
timer = threading.Timer(NO_RECEIPT_COMMITTEE_TIMEOUT, no_receipt_timeout)
timer.start()


def start_mining_clock():
mine()
timer = threading.Timer(BLOCK_TIME_INTERVAL_SECONDS, start_mining_clock)
timer.start()


def get_time_difference():
"""Return the time difference between local and global in seconds"""
try:
with open(TIME_DIFF_WITH_GLOBAL_FILE, 'r') as f:
return int(f.read())
except:
global_epoch = get_global_epoch()
local_epoch = get_local_epoch()
diff = global_epoch - local_epoch
with open(TIME_DIFF_WITH_GLOBAL_FILE, 'w') as f:
f.write(str(diff))
return diff


def sync_timer_clock_with_global():
global_epoch = get_global_epoch()
local_epoch = get_local_epoch()
return global_epoch - local_epoch


def update_time_difference():
TIME_DIFF_WITH_GLOBAL = get_time_difference()
print('Time difference with global is ', TIME_DIFF_WITH_GLOBAL)
if TIME_DIFF_WITH_GLOBAL > MAX_ALLOWED_TIME_DIFF_SECONDS:
print('System time is not syncronised. Time difference in seconds: ', TIME_DIFF_WITH_GLOBAL)
quit()
return True
diff = global_epoch - local_epoch
with open(TIME_DIFF_WITH_GLOBAL_FILE, 'w') as f:
f.write(str(diff))
print('Synced clock. Time difference is', diff)


if __name__ == '__main__':
Expand Down
12 changes: 11 additions & 1 deletion app/codes/consensus/consensus.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from ..fs.mempool_manager import append_receipt_to_block, get_receipts_from_storage
from ...constants import MINIMUM_ACCEPTANCE_RATIO, MINIMUM_ACCEPTANCE_VOTES
from ..auth.auth import get_wallet
from ..minermanager import get_miner_for_current_block


try:
Expand Down Expand Up @@ -64,4 +65,13 @@ def check_community_consensus(block):

# if receipt_counts['postitive_receipt_count'] >= MINIMUM_ACCEPTANCE_VOTES and receipt_counts['total_receipt_count']:
# return True
return False
return False


def validate_block_miner(block):
miner_address = block['signature']['address']

expected_miner = get_miner_for_current_block()['wallet_address']

if miner_address != expected_miner:
raise Exception(f"Invalid miner {miner_address} for block {block['block_index']}. Expected {expected_miner}")
7 changes: 7 additions & 0 deletions app/codes/db_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,10 @@ def input_to_dict(ipval):
else:
callparams = ipval
return callparams


def add_miner(cur, wallet_address, network_address, broadcast_timestamp):
cur.execute('''INSERT OR REPLACE INTO miners
(id, wallet_address, network_address, last_broadcast_timestamp)
VALUES (?, ?, ?, ?)''',
(wallet_address, wallet_address, network_address, broadcast_timestamp))
3 changes: 2 additions & 1 deletion app/codes/kycwallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import base64
import sqlite3

from .utils import get_time_ms
from ..constants import TMP_PATH, NEWRL_DB
from .transactionmanager import Transactionmanager

Expand Down Expand Up @@ -113,7 +114,7 @@ def generate_wallet(kyccustodian, kycdocs, ownertype, jurisd, wallet_specific_da

def create_add_wallet_transaction(wallet):
transaction_data = {
'timestamp': str(datetime.datetime.now()),
'timestamp': get_time_ms(),
'type': 1,
'currency': 'INR',
'fee': 0.0,
Expand Down
144 changes: 144 additions & 0 deletions app/codes/minermanager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
"""Miner update functions"""
import sqlite3
import random

from .utils import get_last_block_hash
# from .p2p.outgoing import propogate_transaction_to_peers
from .p2p.utils import get_my_address
from ..constants import COMMITTEE_SIZE, IS_TEST, NEWRL_DB, TIME_MINER_BROADCAST_INTERVAL
from .auth.auth import get_wallet
from .signmanager import sign_transaction
from ..ntypes import TRANSACTION_MINER_ADDITION
from .utils import get_time_ms
from .transactionmanager import Transactionmanager
from .validator import validate


def miner_addition_transaction(wallet=None, my_address=None):
if wallet is None:
wallet = get_wallet()
if my_address is None:
my_address = get_my_address()
timestamp = get_time_ms()
transaction_data = {
'timestamp': timestamp,
'type': TRANSACTION_MINER_ADDITION,
'currency': "NWRL",
'fee': 0.0,
'descr': "Miner addition",
'valid': 1,
'block_index': 0,
'specific_data': {
'wallet_address': wallet['address'],
'network_address': my_address,
'broadcast_timestamp': timestamp
}
}

transaction_manager = Transactionmanager()
transaction_data = {'transaction': transaction_data, 'signatures': []}
transaction_manager.transactioncreator(transaction_data)
transaction = transaction_manager.get_transaction_complete()
signed_transaction = sign_transaction(wallet, transaction)
return signed_transaction


def get_miner_status(wallet_address):
con = sqlite3.connect(NEWRL_DB)
cur = con.cursor()
miner_cursor = cur.execute(
'SELECT wallet_address, network_address, last_broadcast_timestamp FROM miners WHERE wallet_address=?', (wallet_address, )).fetchone()
if miner_cursor is None:
return None
miner_info = {
'wallet_address': miner_cursor[0],
'network_address': miner_cursor[1],
'broadcast_timestamp': miner_cursor[2]
}
return miner_info


def get_my_miner_status():
wallet = get_wallet()
my_status = get_miner_status(wallet['address'])
return my_status


def broadcast_miner_update():
transaction = miner_addition_transaction()
validate(transaction)


def get_eligible_miners():
last_block = get_last_block_hash()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this function get_all_eligible_nodes()?
the get_committee_for_current_block() seems to be the right function to get the committee itself.

# last_block_epoch = 0
# try:
# # Need try catch to support older block timestamps
# last_block_epoch = int(last_block['timestamp'])
# except:
# pass
# if last_block:
# cutfoff_epoch = last_block_epoch - TIME_MINER_BROADCAST_INTERVAL
# else:
# cutfoff_epoch = 0
last_block_epoch = int(last_block['timestamp'])
cutfoff_epoch = last_block_epoch - TIME_MINER_BROADCAST_INTERVAL

con = sqlite3.connect(NEWRL_DB)
con.row_factory = sqlite3.Row
cur = con.cursor()
miner_cursor = cur.execute(
'''SELECT wallet_address, network_address, last_broadcast_timestamp
FROM miners
WHERE last_broadcast_timestamp > ?
ORDER BY wallet_address ASC''', (cutfoff_epoch, )).fetchall()
miners = [dict(m) for m in miner_cursor]
con.close()
return miners


def get_miner_for_current_block():
last_block = get_last_block_hash()

if not last_block:
return

random.seed(last_block['index'])

committee_list = get_committee_for_current_block()

return random.choice(committee_list)

# return committee_list[0]


def get_committee_for_current_block():
last_block = get_last_block_hash()

if not last_block:
return

random.seed(last_block['index'])

miners = get_eligible_miners()
committee_size = min(COMMITTEE_SIZE, len(miners))
committee = random.sample(miners, k=committee_size)
return committee


def should_i_mine():
my_wallet = get_wallet()
miner = get_miner_for_current_block()
if miner['wallet_address'] == my_wallet['address']:
return True
return False


def am_i_in_current_committee():
my_wallet_address = get_wallet()['address']
committee = get_committee_for_current_block()

found = list(filter(lambda w: w['wallet_address'] == my_wallet_address, committee))
if len(found) == 0:
return False
return True
6 changes: 5 additions & 1 deletion app/codes/p2p/outgoing.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import requests
from threading import Thread
from ...constants import NEWRL_PORT, REQUEST_TIMEOUT, TRANSPORT_SERVER
from ...constants import IS_TEST, NEWRL_PORT, REQUEST_TIMEOUT, TRANSPORT_SERVER
from ..p2p.utils import get_peers
from ..p2p.utils import is_my_address


def propogate_transaction_to_peers(transaction):
if IS_TEST:
return
peers = get_peers()

for peer in peers:
Expand All @@ -25,6 +27,8 @@ def send_request_in_thread(url, data):
thread.start()

def send_request(url, data):
if IS_TEST:
return
requests.post(url, json=data, timeout=REQUEST_TIMEOUT)

def send(payload):
Expand Down
4 changes: 3 additions & 1 deletion app/codes/p2p/sync_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from app.codes.validator import validate_block, validate_block_data, validate_receipt_signature
from app.codes.updater import broadcast_block
from app.codes.fs.temp_manager import append_receipt_to_block, append_receipt_to_block_in_storage, get_blocks_for_index_from_storage, store_block_to_temp, store_receipt_to_temp
from app.codes.consensus.consensus import check_community_consensus
from app.codes.consensus.consensus import check_community_consensus, validate_block_miner


logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -40,6 +40,8 @@ def receive_block(block):
if block_index > get_last_block_index() + 1:
sync_chain_from_peers()

validate_block_miner(block)

validate_block(block, validate_receipts=False)

# if check_community_consensus(block):
Expand Down
3 changes: 2 additions & 1 deletion app/codes/p2p/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import sqlite3
import requests
import socket

from ...constants import NEWRL_P2P_DB


Expand All @@ -22,4 +23,4 @@ def is_my_address(address):
my_address = get_my_address()
if socket.gethostbyname(address) == my_address:
return True
return False
return False
Loading