Esempio n. 1
0
 def recursiveValidate(self, blockerror, address=None):
     index = blockerror.index - 1
     pblock = sqldb.dbtoBlock(sqldb.blockQuery(['',
                                                index]))  # previous block
     trials = 3
     while index and trials:
         logging.debug('validating index %s' % index)
         chainnew = self.reqBlocks(index + 1, index + 1, address)
         new = chainnew[0]
         new = sqldb.dbtoBlock(new)
         print('NEW ID ON RECURSIVE', new.index)
         print('NEW ON RECURSIVE', new.hash)
         #print("NEW", new.index)
         if new and validations.validateBlockHeader(new):
             sqldb.writeBlock(new)
             if validations.validateBlock(
                     new, pblock) and validations.validateChallenge(
                         new, self.stake):
                 logging.debug('returning')
                 #print('FORK', new.index)
                 return new
             else:
                 index -= 1
                 pblock = sqldb.dbtoBlock(sqldb.blockQuery(['', index]))
                 #print("PBLOCK", pblock.index)
         else:
             trials -= 1
     return new
Esempio n. 2
0
 def recursiveValidate(self, blockerror):
     index = blockerror.index - 1
     pblock = sqldb.dbtoBlock(sqldb.blockQuery(['',
                                                index]))  # previous block
     tries = 3
     while index and tries:
         logging.debug('validating index %s' % index)
         new = self.reqBlock(index)
         if new and consensus.validateBlockHeader(new):
             sqldb.writeBlock(new)
             if consensus.validateBlock(new, pblock):
                 logging.debug('returning')
                 return new
             else:
                 index -= 1
                 pblock = sqldb.dbtoBlock(sqldb.blockQuery(['', index]))
         else:
             tries -= 1
     return new
Esempio n. 3
0
def handleMessages(bc, messages):
    cmd = messages[0] if isinstance(messages, list) else str(messages)
    cmd = cmd.lower()
    if cmd == MSG_LASTBLOCK:
        return bc.getLastBlock()
    elif cmd == MSG_HELLO:
        return MSG_HELLO
    elif cmd == MSG_BLOCKS:
        return sqldb.blocksQuery(messages)
    elif cmd == MSG_BLOCK:
        return sqldb.blockQuery(messages)
    else:
        return None
 def rpcServer(self, ip='127.0.0.1', port=9999):
     self.bind(self.rpcsocket, ip, port)
     time.sleep(1)
     while True:
         try:
             messages = self.rpcsocket.recv_multipart()
         except zmq.ContextTerminated:
             break
         time.sleep(1)
         cmd = messages[0].lower()
         if cmd == rpc.MSG_LASTBLOCK:
             b = self.bchain.getLastBlock()
             self.rpcsocket.send(b.blockInfo())
         elif cmd == rpc.MSG_BLOCKCHAIN:
             b = self.bchain.Info()
             self.rpcsocket.send(b)
         elif cmd == rpc.MSG_BLOCK:
             b = sqldb.dbtoBlock(sqldb.blockQuery(messages))
             self.rpcsocket.send(b.blockInfo() if b else 'error')
         elif cmd == rpc.MSG_BLOCKS:
             # TODO add SQL query BETWEEN
             l = sqldb.blocksListQuery(messages)
             blocks = []
             for b in l:
                 # test if error
                 blocks.append(sqldb.dbtoBlock(b).blockInfo())
             self.rpcsocket.send_pyobj(blocks)
         elif cmd == rpc.MSG_ADD:
             m = self.addPeer(messages[1])
             self.rpcsocket.send_string(m)
         elif cmd == rpc.MSG_REMOVE:
             m = self.removePeer(messages[1])
             self.rpcsocket.send_string(m)
         elif cmd == rpc.MSG_PEERS:
             self.rpcsocket.send_pyobj(self.getPeers())
         elif cmd == rpc.MSG_START:
             self.rpcsocket.send_string('Starting mining...')
             self.start.set()
             self.f.set()
         elif cmd == rpc.MSG_STOP:
             self.start.clear()
             self.rpcsocket.send_string('Stopping mining...')
         elif cmd == rpc.MSG_EXIT:
             self.rpcsocket.send_string('Exiting...')
             raise StopException
         else:
             self.rpcsocket.send_string('Command unknown')
             logging.warning('Command unknown')
Esempio n. 5
0
    def rpcServer(self, ip='127.0.0.1', port=9999):
        """ RPC-like server to interact with rpcclient.py """
        self.bind(self.rpcsocket, ip, port)
        time.sleep(1)
        while True:
            try:
                messages = self.rpcsocket.recv_multipart()
            except zmq.ContextTerminated:
                break
            time.sleep(1)
            cmd = messages[0].lower()
            if cmd == rpc.MSG_LASTBLOCK:
                b = self.bchain.getLastBlock()
                self.rpcsocket.send(b.blockInfo())
            elif cmd == rpc.MSG_BLOCKCHAIN:
                b = self.bchain.Info()
                self.rpcsocket.send(b)
            elif cmd == rpc.MSG_BLOCK:
                b = sqldb.dbtoBlock(sqldb.blockQuery(messages))
                self.rpcsocket.send(b.blockInfo() if b else 'error')
            elif cmd == rpc.MSG_BLOCKS:
                l = sqldb.blocksListQuery(messages)
                blocks = []
                for b in l:
                    blocks.append(sqldb.dbtoBlock(b).blockInfo())
                self.rpcsocket.send_pyobj(blocks)
            elif cmd == rpc.MSG_ADD:
                m = self.addPeer(messages[1])
                self.rpcsocket.send_string(m)
            elif cmd == rpc.MSG_REMOVE:
                m = self.removePeer(messages[1])
                self.rpcsocket.send_string(m)
            elif cmd == rpc.MSG_PEERS:
                self.rpcsocket.send_pyobj(self.getPeers())
            elif cmd == rpc.MSG_START:
                self.rpcsocket.send_string('Starting mining...')
                self.start.set()
                self.f.set()
            elif cmd == rpc.MSG_STOP:
                self.start.clear()
                self.f.clear()
                self.e.set()
                self.rpcsocket.send_string('Stopping mining...')
            elif cmd == rpc.MSG_EXIT:
                self.rpcsocket.send_string('Exiting...')
                raise StopException
            elif cmd == rpc.MSG_BALANCE:
                self.addBalance(int(messages[1]))
                self.rpcsocket.send_string('Node Balance is ' +
                                           str(self.balance))
            elif cmd == rpc.MSG_ADDBLOCK:
                l = []
                for i in messages[1:]:
                    l.append(i)
                last_hash = sqldb.dbtoBlock(
                    sqldb.blockQuery(['', str(int(l[0]) - 1)])).hash
                hash_node = hashlib.sha256(self.ipaddr).hexdigest()
                time_create = int(
                    time.mktime(datetime.datetime.now().timetuple()))
                c_header = str(last_hash) + str(l[1]) + str(hash_node)
                hash = hashlib.sha256(c_header).hexdigest()
                b = block.Block(int(l[0]), last_hash, int(l[1]), hash_node,
                                time_create, hash)
                sqldb.writeBlock(b)
                #sqldb.writeChain(b)
                self.bchain.addBlocktoBlockchain(b)
                self.rpcsocket.send_string('Block created ' +
                                           str(b.blockInfo()))

                self.psocket.send_multipart(
                    [consensus.MSG_BLOCK, self.ipaddr,
                     pickle.dumps(b, 2)])
            else:
                self.rpcsocket.send_string('Command unknown')
                logging.warning('Command unknown')
Esempio n. 6
0
    def sync(self, rBlock=None, address=None):
        """ Syncronize with peers and validate chain
        rBlock -- can be passed as argument to sync based on that block index instead of requesting
        address -- try to force requests to use this ip address
        """
        logging.debug('syncing...')
        # Request before sync
        if not rBlock:
            rBlock = self.bchain.getLastBlock()
            # limit number of peers request
            for i in xrange(0, min(len(self.peers), 3)):
                i += 1
                logging.debug('request #%d' % i)
                b, ip = self.reqLastBlock()
                if b:
                    logging.debug('Block index %s' % b.index)
                if (b and (b.index > rBlock.index)):
                    rBlock = b
                    address = ip
                    logging.debug('Best index %s with ip %s' % (b.index, ip))
        last = self.bchain.getLastBlock()
        #print('INDEX BLOCK', last.index)
        #print('LAST BLOCK ON SYNC FUNCTION', last.hash)
        #print('rBLOCK', rBlock.index)
        # Sync based on rBlock
        if (rBlock.index > last.index):
            #print("RBLOCK", rBlock.index)
            if (rBlock.index - last.index == 1):

                if (validations.validateBlockHeader(rBlock)
                        and validations.validateChallenge(rBlock, self.stake)
                        and validations.validateExpectedRound(rBlock, last)):
                    if (validations.validateBlock(rBlock, last)):
                        #print('SYNC-BLOCO CADEIA ATUAL')
                        logging.debug('valid block')
                        sqldb.writeBlock(rBlock)
                        sqldb.writeChain(rBlock)
                        self.bchain.addBlocktoBlockchain(rBlock)
                    else:
                        #print('SYNC-BLOCO OUTRA CADEIA')
                        sqldb.writeBlock(rBlock)
                        # trying to solve and pick a fork
                        n = self.recursiveValidate(rBlock, address)
                        #print('B_ERROR', b_error.index)
                        #print("PONTO DO FORK:", n.index)
                        if n:
                            fork = n
                            #print('BLOCO EM FORK', fork.index)
                            #print('BLOCO EM FORK - HASH', fork.index)
                            #self.bchain.chain.clear() # TODO change this and refactor
                            #remove all blocks after fork point
                            for i in xrange(n.index, last.index + 1):
                                self.bchain.chain.popleft()

                            teste = self.bchain.getLastBlock()
                            #print('ULTIMO BLOCO DEPOIS DE REMOVER BLOCO DO FORK', teste.index)
                            #print('ULTIMO BLOCO DEPOIS DE REMOVER BLOCO DO FORK - HASH', teste.hash)

                            #insert new blocks starting on n block
                            for i in xrange(last.index + 1, n.index - 1, -1):
                                logging.debug('updating chain')
                                if i == 1:
                                    sqldb.replaceChain(n)
                                    self.bchain.addBlocktoBlockchain(n)
                                else:
                                    if (i == rBlock.index):
                                        #print('INSERIR rBLock', rBlock.index)
                                        sqldb.writeChain(rBlock)
                                    else:
                                        lastBlock = sqldb.dbtoBlock(
                                            sqldb.blockQuery(['', i + 1]))
                                        actualBlock = sqldb.dbtoBlock(
                                            sqldb.blockQuery(['', i]))
                                        #print('LAST BLOCK INDEX', lastBlock.index)
                                        #print('LAST BLOCK PREV_HASH', lastBlock.prev_hash)
                                        #print('ACTUAL BLOCK INDEX', actualBlock.index)
                                        #print('ACTUAL BLOCK CHAIN', actualBlock.hash)
                                        if (lastBlock.prev_hash !=
                                                actualBlock.hash):
                                            search = sqldb.blockQueryFork(
                                                ['', i])
                                            for j in search:
                                                value = sqldb.dbtoBlock(j)
                                                if (value.hash ==
                                                        lastBlock.prev_hash):
                                                    sqldb.replaceChain(j)
                            for i in xrange(n.index, last.index + 2):
                                block = sqldb.dbtoBlock(
                                    sqldb.blockQuery(['', i]))
                                self.bchain.addBlocktoBlockchain(block)

                                #n = sqldb.forkUpdate(i)
                                #if(i == rBlock.index-1):
                                #   fork = sqldb.dbtoBlock(sqldb.blockQuery(['',i]))
                                #   print('SUBSTITUINDO O FORK')
                                #   print('FORK HASH', fork.hash)
                                #   print('rBlock PREV HASH', rBlock.prev_hash)
                                #   if(fork.hash != rBlock.prev_hash):
                                #       print('SUBSTITUIR')
                                #       n = sqldb.blockQueryFork(['',i])
                                #       for j in n:
                                #           value = sqldb.dbtoBlock(j)
                                #           if (value.hash == rBlock.prev_hash):
                                #               sqldb.replaceChain(j)
                                #               self.bchain.addBlocktoBlockchain(sqldb.dbtoBlock(j))
                                #   else:
                                #       print('NAO SUBSTITUIR')
                                #       self.bchain.addBlocktoBlockchain(fork)
                                #else:
                                #    sqldb.replaceChain(n)
                                #   self.bchain.addBlocktoBlockchain(sqldb.dbtoBlock(n))

                    teste = self.bchain.getLastBlock()
                    #print('ULTIMO BLOCO DEPOIS DE INSERIR OS BLOCOS DA NOVA CADEIA', teste.index)
                    self.synced = True

            else:
                if (validations.validateBlockHeader(rBlock)
                        and validations.validateChallenge(rBlock, self.stake)):
                    print('BLOCO RECEBIDO > 1 ON SYNC FUNCTION')
                    chain = self.reqBlocks(last.index + 1, rBlock.index,
                                           address)
                    if chain:
                        # validate and write
                        b_error, h_error = validations.validateChain(
                            self.bchain, chain, self.stake)
                        # update last block
                        last = self.bchain.getLastBlock()
                        print('LAST BLOCK ON LOCAL CHAIN', last.index)
                        # if b_error is diffent to None
                        if b_error:
                            print('b_error', b_error.index)
                            # TODO review from next line, because it is strange
                            # if h_error is false and block index equal last block index plus one
                            if not h_error and b_error.index == last.index + 1:
                                print('FORK')
                                sqldb.writeBlock(b_error)
                                # trying to solve and pick a fork
                                n = self.recursiveValidate(b_error, address)
                                print('B_ERROR', b_error.index)
                                print("PONTO DO FORK:", n.index)
                                if n:
                                    #self.bchain.chain.clear() # TODO change this and refactor
                                    #remove all blocks after fork point
                                    teste = self.bchain.getLastBlock()
                                    print('BCHAIN BEFORE POPLEFT', teste.index)
                                    for i in xrange(n.index, last.index + 1):
                                        self.bchain.chain.popleft()

                                    teste = self.bchain.getLastBlock()
                                    print('BCHAIN AFTER POPLEFT', teste.index)
                                    #insert new blocks starting on n block
                                    for i in xrange(last.index + 1,
                                                    n.index - 1, -1):
                                        logging.debug('updating chain')
                                        if i == 1:
                                            sqldb.replaceChain(n)
                                            self.bchain.addBlocktoBlockchain(n)
                                        else:
                                            if (i == b_error.index):
                                                print('INSERIR b_error',
                                                      b_error.index)
                                                sqldb.writeChain(b_error)
                                            else:
                                                lastBlock = sqldb.dbtoBlock(
                                                    sqldb.blockQuery(
                                                        ['', i + 1]))
                                                actualBlock = sqldb.dbtoBlock(
                                                    sqldb.blockQuery(['', i]))
                                                if (lastBlock.prev_hash !=
                                                        actualBlock.hash):
                                                    search = sqldb.blockQueryFork(
                                                        ['', i])
                                                    for j in search:
                                                        value = sqldb.dbtoBlock(
                                                            j)
                                                        if (value.hash ==
                                                                lastBlock.
                                                                prev_hash):
                                                            sqldb.replaceChain(
                                                                j)
                                    for i in xrange(n.index, last.index + 2):
                                        block = sqldb.dbtoBlock(
                                            sqldb.blockQuery(['', i]))
                                        self.bchain.addBlocktoBlockchain(block)

                                    #for i in xrange(n.index,last.index+1):
                                    #      logging.debug('updating chain')
                                    #      if i == 1:
                                    #          sqldb.replaceChain(n)
                                    #          self.bchain.addBlocktoBlockchain(n)
                                    #      else:
                                    #          n = sqldb.forkUpdate(i)
                                    #          sqldb.replaceChain(n)
                                    #          self.bchain.addBlocktoBlockchain(sqldb.dbtoBlock(n))
                                    #validations.validateChain(self.bchain, chain, self.stake)
                                self.synced = True
                            else:
                                logging.debug('invalid')  # request again
                                chainnew = self.reqBlocks(
                                    b_error.index, b_error.index, address)
                                new = chainnew[0]
                                new = sqldb.dbtoBlock(new)
                                #print('NEW RETURN SYNC', new.index)
                                self.sync(new)
                        else:
                            self.synced = True
        else:
            self.synced = True
        logging.debug('synced')
Esempio n. 7
0
    def listen(self):
        """ Listen to block messages in a SUB socket
            Message frames: [ 'block', ip, block data ]
        """
        self.bind(self.psocket)
        while True and not self.k.is_set():
            try:
                msg, ip, block_recv = self.subsocket.recv_multipart()
                self.f.clear()
                newChain = False
                # serialize
                b = pickle.loads(block_recv)
                logging.info("Got block %s miner %s" % (b.hash, ip))
                b.arrive_time = int(
                    time.mktime(datetime.datetime.now().timetuple()))
                # Verify block
                if validations.validateBlockHeader(b):
                    logging.debug('valid block header')
                    lb = self.bchain.getLastBlock()

                    if (b.index - lb.index == 1):
                        print('BLOCK', b.index)
                        print('VALIDATEBLOCK',
                              validations.validateBlock(b, lb))
                        print('VALIDATEROUND',
                              validations.validateRound(b, self.bchain))
                        print('VALIDATECHALLENGE',
                              validations.validateChallenge(b, self.stake))
                        self.e.set()
                        if (validations.validateBlock(b, lb)):
                            if (validations.validateRound(b, self.bchain)
                                    and validations.validateChallenge(
                                        b, self.stake)
                                    and validations.validateExpectedRound(
                                        b, lb)):
                                #print('NOVO BLOCO RECEBIDO---ACEITO SEM PROBLEMAS')
                                self.bchain.addBlocktoBlockchain(b)
                                sqldb.writeBlock(b)
                                sqldb.writeChain(b)
                        else:
                            if (validations.validateRound(b, self.bchain)
                                    and validations.validateChallenge(
                                        b, self.stake)
                                    and validations.validateExpectedRound(
                                        b, lb)):
                                print('BLOCO RECEBIDO APOS O FORK-', b.index)
                                self.synced = False
                                self.sync(b, ip)

                    # rebroadcast
                        logging.debug('rebroadcast')
                        self.psocket.send_multipart(
                            [consensus.MSG_BLOCK, ip,
                             pickle.dumps(b, 2)])
                        #self.e.clear()

                    elif b.index - lb.index > 1:
                        print('BLOCO RECEBIDO INDEX MAIOR QUE 1', b.index)
                        self.e.set()
                        self.synced = False
                        self.sync(b, ip)
                        self.e.clear()

                    elif b.index == lb.index:
                        if b.hash == lb.hash:
                            logging.debug('retransmission')
                        else:
                            if (b.round == lb.round):
                                logging.debug('possible fork')
                                pre_block = sqldb.dbtoBlock(
                                    sqldb.blockQuery([
                                        '', lb.index - 1
                                    ]))  #get the block that b and lb point.

                                if (validations.validateBlock(b, pre_block)
                                        and validations.validateChallenge(
                                            b, self.stake)
                                        and validations.validateExpectedRound(
                                            b, pre_block)):
                                    # double entry
                                    sqldb.writeBlock(b)
                    else:
                        # ignore old block
                        logging.debug('old')
                else:
                    logging.debug('invalid block')
                #
                self.f.set()
            except (zmq.ContextTerminated):
                break