Пример #1
0
class UI:
    def __init__(self, minerNum, lock, comm):
        # the node's copy of blockchain
        self.minerNum = minerNum
        self.log = Log(lock, minerNum)
        self.transObj = Transactions(minerNum)
        self.blockchain = Blockchain(self.log, self.transObj, minerNum)
        self.comm = comm
        self.allNodes = [i + 1 for i in range(1 + self.comm.get_num_of_processes())]
        self.comm.set_ui_receive(self)
        self.stakeMoney = random.randint(150, 200)
        
        self.clientProb = 0
        self.NumForgedBlock = 0
        self.blockForged = None
        self.signingPool = []
        self.setSigningPool()
        
        self.blockLen = 0
        self.votedFor = []
        self.winner = 0

    def startUI(self):
        while True:
            sleep(random.randint(20, 30))
            if random.random() <= self.calcProbability() and self.winner ==0:
                
                self.blockForged = self.blockchain.mine()
                if self.blockForged == -2:
                    break
                self.blockForged.signer = {self.minerNum : self.stakeMoney}
                #request votes from miners
                print('Requesting Vote!!!!')
                self.sendMessage(101, 'all')
#            else:
#                print('$$$ Whats Happening $$$')
    
    def setSigningPool(self):
        self.signingPool = [i for i in self.allNodes]
        self.signingPool.remove(self.minerNum)
        random.shuffle(self.signingPool)
        
    def calcProbability(self):
        if self.blockLen == 0:
            return 0.5
        self.clientProb = 1 - (self.NumForgedBlock  / self.blockLen  )
        return self.clientProb
                  
    
    def sendMessage(self, msg_type, node, msg=None):
        #sleep(random.randint(1,4))
        if msg_type == 101:         #request vote
            self.votedFor.append(self.minerNum)
            sent_msg = {'code': 101, 'node': self.minerNum}
            
        # reply vote if not voted for anyone
        if msg_type == 102:
            if not self.votedFor:
                self.votedFor.append(node)
                sent_msg = {'code': 102, 'node': self.minerNum}
            else:
                sent_msg = {'code': -1, 'node': self.minerNum}
                    
        # notify all nodes about winner
        if msg_type == 103:
                sent_msg = {'code': 103, 'node': self.minerNum} 
                
        # send signing request to all miners
        if msg_type == 104:
                sent_msg = {'code': 104, 'node': self.minerNum, 'msg': msg} 
                
        # send signed block to winner
        if msg_type == 105:
                sent_msg = {'code': 105, 'node': self.minerNum, 'msg': msg} 
        
        # send verified block to all miners
        if msg_type == 106:
                sent_msg = {'code': 106, 'node': self.minerNum, 'msg': msg} 
                    
        # for broadcast, node == 'all' and for specific node, node= node_id        
        if node == 'all':
            for node_id in self.allNodes:
                if node_id != self.minerNum:
                    self.comm.send_msg(node_id, sent_msg)
        else:
            self.comm.send_msg(node, sent_msg)

    # converts dict chain to block chain          
    def convertToBlockChain(self, dictchain):
        blockchain = []
        for block in dictchain:
                block_ = Block(block["index"], block["transaction"], block["timestamp"], block["previous_hash"], block["validator"], block["signer"])
                block_.reward =block["reward"]
                blockchain.append(block_)
        return blockchain

    # converts dict chain to block chain          
    def convertToDictChain(self, blockchain):
        dictchain = []
        for block in blockchain:
                dictchain.append(json.dumps(block.__dict__, sort_keys=True))
        return dictchain
    
    def sendVerifiedBlock(self):
        self.winner = 0
        self.votedFor = []
        self.NumForgedBlock += 1
        
        self.setSigningPool()
        
        #add reward money to block
        self.blockForged = self.blockchain.addRewardMoney(self.blockForged)                
        print('## Winner ## Block ::: {2} ##Current Length ::: {0} ## NumBlocks ::: {1}'.format(self.blockLen +1, self.NumForgedBlock, self.blockForged.index))
        self.blockchain.appendBlockChain(self.blockForged)
        self.blockLen = self.blockchain.getChainLength()
        self.sendMessage(106, 'all', msg = self.blockForged.__dict__)
        

    def handleReceivedMessage(self, msg):
        msg_type = msg.get('code')
        sent_node = msg.get('node')
        if msg_type == 101:         #vote request from sent_node
            self.sendMessage(102, sent_node)
            print('Sending Vote to node ', sent_node)
            
        if msg_type == 102:
            # received vote reply from sent_node
            self.votedFor.append(sent_node)
            if len(self.votedFor) > (len(self.allNodes)/2) and self.winner == 0:
                self.winner = self.minerNum
                self.sendMessage(103, 'all')
                sleep(2)
                if self.blockchain.checkSigner(self.blockForged):
                    signer_node = self.signingPool[0]
                    self.signingPool.remove(signer_node)
                    self.sendMessage(104, signer_node, msg=self.blockForged.__dict__)
                else:
                    self.sendVerifiedBlock()   
                    
        if msg_type == 103:
            # notification received from winner node
            self.winner = sent_node
            #wait until block received from winner
            
        if msg_type == 104:
            #received signing request from sent_node
            dict_block = msg.get('msg')
            block = self.convertToBlockChain([dict_block])[0]
            print('Signing Block Index ::: ', block.index)
            condition, block = self.blockchain.singBlock(block, self.stakeMoney)
            if condition:
                self.sendMessage(105, sent_node, msg=self.stakeMoney)
            else:
                print('Signing Failed for Block ::: ', block.index)
                
        if msg_type == 105:
            #received signed block from sent_node
            self.blockForged.signer[sent_node] = int(msg.get('msg'))  
            if self.blockchain.checkSigner(self.blockForged):
                signer_node = self.signingPool[0]
                self.signingPool.remove(signer_node)
                self.sendMessage(104, signer_node, msg=self.blockForged.__dict__)
            else:
                self.sendVerifiedBlock()
            
            
        if msg_type == 106:
            # received block from winner to attach in chain
            dict_block = msg.get('msg')
            block = self.convertToBlockChain([dict_block])[0]            
            print('Veryfining Block Index ::: {0} from node ::: {1}'.format( block.index, sent_node))
            if self.blockchain.verifyBlock(block, 2, None):
                self.blockchain.appendBlockChain(block)
                self.winner = 0
                self.votedFor = []
                self.blockLen = self.blockchain.getChainLength()
                print('Block Verified and Added ## Current Chain Length ::: ', self.blockLen)