def block_management(): global global_best_block, global_blockchain, global_txs, global_utxos, global_difficulty while True: time.sleep(10) try: last_mined_time = global_blockchain[-1].timestamp except: last_mined_time = genesis_epoch # Auto mine # if 30 seconds has passed since last mining if (time.time() - last_mined_time > 30): # Mine block mined_block = mine_block(global_best_block, account_address) if (mined_block.coinbase.reward_address == account_address): print('[SUCCESS] You found the nonce for block {}'.format( mined_block.height)) # Broadcast block to nodes mined_block_str = json.dumps(mined_block.toJSON()) for node in global_nodes: # If node['host'] is in black list then continue if node['host'] in global_blacklisted_nodes: continue try: misocoin_cli('receive_mined_block', [mined_block_str], **node) except: pass
def send_raw_tx(tx: str): global global_best_block, global_txs, global_utxos try: # Original tx _tx_og = copy.deepcopy(tx) # Create new tx from the json dump tx = Transaction.fromJSON(json.loads(tx)) # If is new tx then add it to block if tx.txid not in global_txs: # Add tx to global best block global_best_block, global_txs, global_utxos = mutils.add_tx_to_block( tx, global_best_block, global_txs, global_utxos) print('[INFO] txid {} added to block {}'.format( tx.txid, global_best_block.height)) # Broadcast transaction to connected nodes for node in global_nodes: try: misocoin_cli('send_raw_tx', [json.dumps(tx.toJSON())], **node) except Exception as e: pass return {'txid': tx.txid} except Exception as e: return {'error': str(e)}
def sync_with_nodes(): ''' Syncs blocks with node ''' global global_nodes # Init connection for node in global_nodes: try: misocoin_cli('init_connection', [global_host, global_port], **node) except: pass # Checks every 15 seconds while True: # Checks with nodes, syncs with the one with # the longest chain longest_node = None best_height = len(global_blockchain) for node in global_nodes: # If node['host'] is in black list then continue if node['host'] in global_blacklisted_nodes: continue try: node_best_length = misocoin_cli('get_info', [], **node)['height'] if node_best_length > best_height: longest_node = node best_height = node_best_length except: pass # Syncs with that node if longest_node is not None: latest_block_dict: Dict = misocoin_cli('get_block', [best_height], **longest_node) latest_block: Block = Block.fromJSON(latest_block_dict) # Append to latest blockchain add_to_blockchain(latest_block) time.sleep(10)
#! /usr/bin/env python import requests import json import sys from functools import reduce from misocoin.sync import misocoin_cli if __name__ == "__main__": if len(sys.argv) < 2: print('Missing method') exit(0) config = filter(lambda x: x[0] is '-', sys.argv[1:]) config_kwargs = reduce(lambda x, y: {y.split( '=')[0][1:]: y.split('=')[1], **x}, config, {}) params = list(filter(lambda x: x[0] is not '-', sys.argv[1:])) result = misocoin_cli(params[0], params[1:], **config_kwargs) print(json.dumps(result))
def add_to_blockchain(block: Block): """ Helper function to update the blockchain. Also updates the utxo cache and tx cache """ global global_best_block, global_txs, global_utxos, global_difficulty # If we don't have the prev block, get it from our nodes if (block.height - 1) not in global_blockchain: for node in global_nodes: try: missing_block_dict: Dict = misocoin_cli( 'get_block', [block.height - 1], **node) missing_block: Block = Block.fromJSON(missing_block_dict) add_to_blockchain(missing_block) break except: pass # Check block hashes if len(global_blockchain) > 0: # Check hashes if block.prev_block_hash != global_blockchain[block.height - 1].block_hash: raise Exception('Block previous hash doesn\'t match') if not block.mined: raise Exception('Block hasn\'t been mined') # Add block to node if block.height not in global_blockchain: global_blockchain[block.height] = block # Add coinbase to cache if block.coinbase.txid not in global_txs: global_txs[block.coinbase.txid] = block.coinbase if block.coinbase.txid not in global_utxos: global_utxos[block.coinbase.txid] = {} global_utxos[block.coinbase.txid][0] = { 'address': block.coinbase.reward_address, 'amount': block.coinbase.reward_amount, 'spent': None } # Add tx for tx in block.transactions: if tx.txid not in global_txs: # Update utxos global_best_block, global_txs, global_utxos = mutils.add_tx_to_block( tx, global_best_block, global_txs, global_utxos) # Only ammend global_best_block if the block.height # is higher if (global_best_block.height < block.height + 1): global_best_block = Block(prev_block_hash=block.block_hash, transactions=[], height=block.height + 1, timestamp=int(time.time()), difficulty=global_difficulty, nonce=0) # Broadcast block for node in global_nodes: try: misocoin_cli('receive_mined_block', [json.dumps(block.toJSON())], **node) except: pass # Auto adjust difficulty ever 10 blocks # Should be around 300 seconds after 10 blocks last_ten_blocks = [] for i in range(max(1, global_best_block.height - 10), global_best_block.height - 1): if i in global_blockchain: last_ten_blocks.append(global_blockchain[i]) if (len(global_blockchain) % 10 == 0): lowest_timestamp = reduce(lambda x, y: min(x, y.timestamp), last_ten_blocks, int(time.time())) highest_timestamp = reduce(lambda x, y: max(x, y.timestamp), last_ten_blocks, genesis_epoch) if (highest_timestamp - lowest_timestamp < 300): global_difficulty = min(global_difficulty + 1, 64) if (highest_timestamp - lowest_timestamp > 300): global_difficulty = max(global_difficulty - 1, 1) print( '[UPDATE] Difficulty adjusted to {}'.format(global_difficulty)) print('[INFO] Received mined block {}'.format(block.height))