def command_selctor(cmd): switcher = { # 0 system CC__STOP : lambda:connexion_exit(), CC__PING : lambda:ping(), CC__PONG : lambda:pong(), # 1 recieve CC__RECIEVE_ENODE : lambda:recieve_enode(), CC__RECIEVE_ADDRESS : lambda:recieve_address(), # 2 user request CC__REQUEST_SERVER_ENODE : lambda:request_server_enode(), CC__REQUEST_PEERS_ENODE : lambda:request_peers_enode(), CC__REQUEST_SERVER_ADDRESS : lambda:request_server_address(), CC__REQUEST_PEERS_ADDRESS : lambda:request_peers_address(), CC__REQUEST_CONTRACT_IM : lambda:request_contract_intervention_manager(), CC__REQUEST_CONTRACT_EIGENTRUST : lambda:request_contract_eigenTrust(), CC__REQUEST_NETWORKID : lambda:request_networkid(), CC__REQUEST_ETHER : lambda:request_ether() } function=switcher.get(cmd,lambda : unknown_command()) if ((cmd != CC__PING and cmd != CC__PONG) or tools.verbosity >= 6): console(LOG_FLAG_CC, "opCode received : 0x{:02x}".format(ord(cmd))) tools.clients[threading.currentThread().name]["timestamp"] = tools.now() return function()
def main(): print("Welcome to Sesan Blochain Client.\n") tempNodeName = "." while (bool(re.compile(r'[^a-z]').search(tempNodeName))): tempNodeName = input("Node name (ascii lowercase lettre only)(a-z) : " ) or DEFAULT_NODE_NAME #tempNodeName = DEFAULT_NODE_NAME print("Node name : " + tempNodeName) if not os.path.exists("./eth_{0}".format(tempNodeName)): console( LOG_FLAG_ERROR, "Node not initialized. Please initialize it with main_init_user.py" ) tools.init(tempNodeName) geth.run_geth_node(tools.nodeName) geth.IPC_geth_connection(tools.nodeName) geth.check_coinbase() server_contract.init_contracts()
def request_server_enode(): currentClient = tools.clients[threading.currentThread().name] enodeBytes = tools.w3.geth.admin.node_info()["enode"].encode('UTF-8') size = len(enodeBytes) currentClient["socket"].send(size.to_bytes(CC_LEN_OF_SIZE, byteorder='big')) currentClient["socket"].send(enodeBytes) console(LOG_FLAG_CC, "server enode sent")
def deploy_eigenTrust(): if (tools.eigenTrust != {}): console( LOG_FLAG_WARN, "eigenTrust contract already deployed at {}".format( tools.eigenTrust.address)) return False # kill spy tools.exit_thread("eigenTrustSpyThread") compiledEigenTrust = solcx.compile_files( [CONTRACT_SOURCES_FOLDER + CONTRACT_EIGENTRUST_SOURCES_FILENAME]) eigenTrustId, eigenTrustInterface = compiledEigenTrust.popitem() deployTransactionHash = tools.w3.eth.contract( abi=eigenTrustInterface['abi'], bytecode=eigenTrustInterface['bin']).constructor().transact() console(LOG_FLAG_INFO, "eigenTrust contract transaction sent, waiting validation") eigenTrustDeployWaitingThread = threading.Thread( target=deploy_waiting, name="eigenTrust", args=( deployTransactionHash, eigenTrustInterface['abi'], ), daemon=True) eigenTrustDeployWaitingThread.start()
def deploy_PoRX(): if (tools.PoRX != {}): console( LOG_FLAG_WARN, "PoRX contract already deployed at {}".format(tools.PoRX.address)) return False # kill spy tools.exit_thread("PoRXSpyThread") compiledPoRX = solcx.compile_files( [CONTRACT_SOURCES_FOLDER + CONTRACT_PORX_SOURCES_FILENAME]) PoRXId, PoRXInterface = compiledPoRX.popitem() deployTransactionHash = tools.w3.eth.contract( abi=PoRXInterface['abi'], bytecode=PoRXInterface['bin']).constructor().transact() console(LOG_FLAG_INFO, "PoRX contract transaction sent, waiting validation") PoRXDeployWaitingThread = threading.Thread(target=deploy_waiting, name="PoRX", args=( deployTransactionHash, PoRXInterface['abi'], ), daemon=True) PoRXDeployWaitingThread.start()
def check_coinbase(): try: print("coinbase : " + tools.w3.eth.coinbase) except ValueError: console(LOG_FLAG_ERROR, "coinbase not initialized.") if (tools.w3.eth.coinbase != tools.conf["geth"]["coinbase"]): console(LOG_FLAG_ERROR, "coinbase doesn't match with conf file") set_default_account(tools.w3.eth.coinbase) t = 3 while t>0: try: tools.coinbasePassword = input("password : "******"wrong password, {} try left".format(t)) continue console(LOG_FLAG_INFO, "valid password") lock_coinbase() return console(LOG_FLAG_ERROR, "exit after 3 tests")
def close_all_connexion(): console(LOG_FLAG_INFO, "close all connexion") temp = [] for c in tools.clients: temp.append(c) for c in temp: close_connexion(c)
def request_contract_eigenTrust(): currentClient = tools.clients[threading.currentThread().name] if (tools.eingenTrust == None): console(LOG_FLAG_WARN, "no deployed eigenTrust contract") currentClient["socket"].send(int(0).to_bytes(CC_LEN_OF_SIZE, byteorder='big')) return """
def set_default_account(address): if (address[:2] != "0x" or not tools.w3.isAddress(address)): console(LOG_FLAG_WARN, "eth.defaultAccount need valid address, eth.defaultAccount not set") return False else: tools.w3.eth.defaultAccount = address console(LOG_FLAG_INFO, "eth.defaultAccount set to {}".format(address)) return True
def recieve_enode(): currentClient = tools.clients[threading.currentThread().name] size = int.from_bytes(currentClient["socket"].recv(CC_LEN_OF_SIZE), byteorder='big') if (size == 0): server_managment.close_self_connexion("size of enode must be nonzero") return currentClient["enodeString"] = currentClient["socket"].recv(size).decode('UTF-8') currentClient["update"] = C_UPDATE_PEERABLE console(LOG_FLAG_CC, "enode received : {}...".format(currentClient["enodeString"][:32]))
def recieve_address(): currentClient = tools.clients[threading.currentThread().name] size = int.from_bytes(currentClient["socket"].recv(CC_LEN_OF_SIZE), byteorder='big') if (size != 42): server_managment.close_self_connexion("size of address must be 42 (not a joke :D)") return currentClient["addressString"] = currentClient["socket"].recv(size).decode('UTF-8') currentClient["update"] = C_UPDATE_ADDRESS console(LOG_FLAG_CC, "address received : {}".format(currentClient["addressString"]))
def close_self_connexion(message=""): if (threading.currentThread() == threading.main_thread()): raise NameError("MainThread can't close self connexion") if close_connexion(threading.currentThread().name): if (message == ""): console(LOG_FLAG_INFO, "connexion closed") else: console(LOG_FLAG_INFO, "connexion closed : {}".format(message))
def clique_discard(address): if (address[:2] != "0x" or not tools.w3.isAddress(address)): console(LOG_FLAG_WARN, "clique engine need valid address, discard not set") return False response = provider.make_request(method = "clique_discard", params = [address]) if ("error" in response.keys()): print(response) raise NameError("Bad RPC request") return (response["result"] == None and address not in clique_get_proposals())
def start_spy(): console(LOG_FLAG_INFO, "start eigenTrust spy", who="eigenTrust") events = dict() events["NewUser"] = tools.eigenTrust.events.NewUser.createFilter( fromBlock=0) events["Vote"] = tools.eigenTrust.events.Vote.createFilter(fromBlock=0) while (threading.currentThread().name == "eigenTrustSpyThread"): check_events(events) time.sleep(1) console(LOG_FLAG_INFO, "eigenTrust spy stopped", who="eigenTrust")
def clique_propose(address,vote): if (address[:2] != "0x" or not tools.w3.isAddress(address)): console(LOG_FLAG_WARN, "clique engine need valid address, propose not set") return False if (type(vote)!=bool): console(LOG_FLAG_WARN, "clique engine need boolean vote, propose not set") return False response = provider.make_request(method = "clique_propose", params = [address,vote]) if ("error" in response.keys()): print(response) raise NameError("Bad RPC request") return (response["result"] == None and clique_get_proposals()[address] == vote)
def check_events(events): # SubmitNonce event news = events["SubmitNonce"].get_new_entries() for e in news: if (e["args"]["valid"]): console(LOG_FLAG_INFO, "{0} found {1} for the block {2}".format( e["args"]["miner"], e["args"]["nonce"], e['blockNumber']), who="PoRX") else: console(LOG_FLAG_INFO, "{0} failed with {1}".format(e["args"]["miner"], e["args"]["nonce"]), who="PoRX") # MinerAdded event news = events["MinerAdded"].get_new_entries() for e in news: console(LOG_FLAG_INFO, "{0} added {1} at block {2}".format(e["args"]["authority"], e["args"]["miner"], e['blockNumber']), who="PoRX") # MinerRevoked event news = events["MinerRevoked"].get_new_entries() for e in news: console(LOG_FLAG_INFO, "{0} revoked {1} at block {2}".format(e["args"]["authority"], e["args"]["miner"], e['blockNumber']), who="PoRX")
def start_spy(): console(LOG_FLAG_INFO, "start PoRX spy", who="PoRX") events = dict() events["SubmitNonce"] = tools.PoRX.events.SubmitNonce.createFilter( fromBlock=0) events["MinerAdded"] = tools.PoRX.events.MinerAdded.createFilter( fromBlock=0) events["MinerRevoked"] = tools.PoRX.events.MinerRevoked.createFilter( fromBlock=0) while (threading.currentThread().name == "PoRXSpyThread"): check_events(events) time.sleep(1) console(LOG_FLAG_INFO, "PoRX spy stopped", who="PoRX")
def mine(status): if (status == True): th = 1 elif (type(status) == int and status >= 0): th = status elif (status == False): th = 0 else: console(LOG_FLAG_WARN, "wrong argument for mine(status), bool or positive integer") return if (th > 0): tools.w3.geth.miner.start(min(th, GETH_MAX_MINING_THREAD)) else: tools.w3.geth.miner.stop()
def client_manager(): # accept new connexion try: connexion, tsap_client = tools.serverSocket.accept() except socket.timeout: return # rename the current tread threading.currentThread().name = tools.hash(str(tsap_client)) # initialized client database server_managment.init_new_client_database(connexion, tsap_client) connexion.settimeout(CC_TIMEOUT) if (connexion.recv(1) != CC__START): server_managment.close_self_connexion( "no start opCode") ##################CLOSE return console(LOG_FLAG_INFO, "start opCode OK : New client") try: while 1: cmd = None cmd = connexion.recv(1) if (cmd == None or cmd == b''): server_managment.close_self_connexion( "connexion lost") ##################CLOSE return server_commands.command_selctor(cmd) server_managment.client_database_update() raise NameError("Inaccessible code line in waiting_client()") except socket.timeout: server_managment.close_self_connexion( "ping or pong reply timeout") ##################CLOSE return except ConnectionResetError: server_managment.close_self_connexion( "connexion reset failed") ##################CLOSE return except OSError: server_managment.close_self_connexion( "console command") ##################CLOSE return
def init_new_client_database(connexion, tsap): index = 0 while index in [tools.clients[c]["id"] for c in tools.clients]: index += 1 tools.clients[threading.currentThread().name] = dict() currentClient = tools.clients[threading.currentThread().name] currentClient["update"] = 0 currentClient["id"] = index currentClient["socket"] = connexion currentClient["timestamp"] = tools.now() currentClient["ip"] = [int(tsap[0].split('.')[x]) for x in range(4)] currentClient["pyPort"] = tsap[1] currentClient["enodeString"] = None currentClient["addressString"] = None currentClient["isValidAddress"] = False currentClient["peerable"] = False console(LOG_FLAG_INFO, "new client : database initialized")
def request_peers_enode(): currentClient = tools.clients[threading.currentThread().name] peerableClient = [c for c in tools.clients if (tools.clients[c]["peerable"] and tools.clients[c]!=currentClient)] enodeNumber = math.ceil(len(peerableClient)*GETH_PERCENT_PEER_ENODE_SENT/100) if (enodeNumber == 0): console(LOG_FLAG_WARN,"no client peerable, server enode is sending") currentClient["socket"].send(int(1).to_bytes(CC_LEN_OF_SIZE, byteorder='big')) request_server_enode() return enodeNumber = min(enodeNumber,GETH_MAX_PEER_ENODE_SENT) enodeToSend = [] while (len(enodeToSend)<enodeNumber): enodeToSend.append(tools.clients[random.choice(peerableClient)]["enodeString"]) currentClient["socket"].send(enodeNumber.to_bytes(CC_LEN_OF_SIZE, byteorder='big')) for enodeString in enodeToSend: enodeBytes = enodeString.encode('UTF-8') currentClient["socket"].send(len(enodeBytes).to_bytes(CC_LEN_OF_SIZE, byteorder='big')) currentClient["socket"].send(enodeBytes) console(LOG_FLAG_CC, "{} peers enode sent".format(enodeNumber))
def deploy_intervention_manager(): compiledInterventionManager = solcx.compile_files( [CONTRACT_SOURCES_FOLDER + CONTRACT_IM_SOURCES_FILENAME]) interventionManagerId, interventionManagerInterface = compiledInterventionManager.popitem( ) deployTransactionHash = tools.w3.eth.contract( abi=interventionManagerInterface['abi'], bytecode=interventionManagerInterface['bin']).constructor().transact() console( LOG_FLAG_INFO, "intervention manager contract transaction sent, waiting validation") interventionManagerDeployWaitingThread = threading.Thread( target=deploy_waiting, name="interventionManager", args=( deployTransactionHash, interventionManagerInterface['abi'], ), daemon=True) interventionManagerDeployWaitingThread.start()
def start_server(): tools.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tools.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tools.serverSocket.bind(('', tools.conf["server"]["port"])) tools.serverSocket.listen(1) tools.serverSocket.settimeout(1) console( LOG_FLAG_INFO, "server started, listen on {0}".format(tools.conf["server"]["port"])) #server_contract.init_contracts() #console(LOG_FLAG_INFO, "contract system initialized") nbClient = -1 while threading.currentThread().name != "exit": newThread = threading.Thread(target=client_manager, name="newClient", args=(), daemon=True) newThread.start() if (nbClient != len(tools.clients)): nbClient = len(tools.clients) console(LOG_FLAG_INFO, "active client : {}".format(nbClient)) while (newThread.is_alive() and newThread.name == "newClient"): time.sleep(0.1) threading.currentThread().name = "serverThread" server_managment.close_all_connexion() console(LOG_FLAG_INFO, "all client connexion closed") tools.serverSocket.close() console(LOG_FLAG_INFO, "server stopped")
def IPC_geth_connection(nodeName): global provider console(LOG_FLAG_INFO, "waiting IPC connection ...") while not os.path.exists("./eth_{0}/geth.ipc".format(nodeName)): time.sleep(1) time.sleep(1) provider = Web3.IPCProvider("./eth_{0}/geth.ipc".format(nodeName)) tools.w3 = Web3(provider) tools.w3.middleware_onion.inject(geth_poa_middleware, layer=0) if (tools.w3.isConnected()): console(LOG_FLAG_INFO, "IPC connection successful to {0} geth node".format(nodeName)) else: console(LOG_FLAG_ERROR, "IPC connection failed") return
def check_events(events): # NewUser event news = events["NewUser"].get_new_entries() for e in news: console(LOG_FLAG_INFO, "{0} : {1} added".format(e["args"]["index"], e["args"]["user"]), who="eigenTrust") # Vote event news = events["Vote"].get_new_entries() for e in news: if (e["args"]["vote"]): console(LOG_FLAG_INFO, "{0} vote for {1}".format(e["args"]["from"], e["args"]["to"]), who="eigenTrust") else: console(LOG_FLAG_INFO, "{0} vote against {1}".format(e["args"]["from"], e["args"]["to"]), who="eigenTrust")
def unknown_command(): console(LOG_FLAG_WARN, "unknown command, ignored")
def deploy_waiting(deployTransactionHash, abi): while True: try: address = tools.w3.eth.getTransactionReceipt( deployTransactionHash)['contractAddress'] break except: time.sleep(1) if (threading.currentThread().name == "eigenTrust"): console(LOG_FLAG_INFO, "eigenTrust transaction validated", who="EigenTrust") tools.conf["geth"]["contract"]["eigenTrust"]["address"] = address tools.conf["geth"]["contract"]["eigenTrust"]["abi"] = abi init_contracts() console(LOG_FLAG_INFO, "eigenTrust fully deployed at {}".format(address), who="EigenTrust") elif (threading.currentThread().name == "PoRX"): console(LOG_FLAG_INFO, "PoRX transaction validated", who="PoRX") tools.conf["geth"]["contract"]["PoRX"]["address"] = address tools.conf["geth"]["contract"]["PoRX"]["abi"] = abi init_contracts() console(LOG_FLAG_INFO, "PoRX fully deployed at {}".format(address), who="PoRX") elif (threading.currentThread().name == "interventionManager"): console(LOG_FLAG_INFO, "interventionManager transaction validated", who="IM contract") tools.conf["geth"]["contract"]["interventionManager"].append({ "address": address, "abi": abi }) init_contracts() number = len(tools.interventionManager) if (number % 10 == 1 and number % 100 != 11): sufixe = "st" elif (number % 10 == 2 and number % 100 != 12): sufixe = "nd" elif (number % 10 == 3 and number % 100 != 13): sufixe = "rd" else: sufixe = "th" console(LOG_FLAG_INFO, "{0}{1} interventionManager fully deployed at {2}".format( number, sufixe, address), who="IM contract") else: console(LOG_FLAG_INFO, "{} transaction validated".format(deployTransactionHash), who=threading.currentThread().name[:11]) return
def pong(): if(tools.verbosity >= 6): console(LOG_FLAG_CC,"pong reply")
def request_networkid(): currentClient = tools.clients[threading.currentThread().name] if (tools.w3.geth.admin.node_info().protocols.eth.network != tools.conf["geth"]["networkid"]): console(LOG_FLAG_ERROR, "networkid doesn't match with conf file") currentClient["socket"].send(tools.conf["geth"]["networkid"].to_bytes(CC_LEN_OF_SIZE, byteorder='big'))
def request_ether(): currentClient = tools.clients[threading.currentThread().name] size = int.from_bytes(currentClient["socket"].recv(CC_LEN_OF_SIZE), byteorder='big') weiRequest = int.from_bytes(currentClient["socket"].recv(size), byteorder='big') console(LOG_FLAG_INFO, "client want {} wei".format(weiRequest)) currentClient["socket"].send(CC__REQUEST_ETHER_AKW)