예제 #1
0
class SignChecker(QObject):
    validTran = pyqtSignal(str, str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.__cryptor = NooCrypto()

    @pyqtSlot(str, str)
    def checkTran(self, address, packet):
        try:
            jsonPacket = json.loads(packet)
        except json.JSONDecodeError:
            print("WRONG JSON PACKET, IN CHECKTRAN WITH 2 ARG")
            return False
        signature = jsonPacket.pop("SIGNATURE", None)
        sender = jsonPacket.get("SENDER", None)
        if signature and sender:
            if self.__cryptor.verifyMessage(
                    signature, sender,
                    json.dumps(jsonPacket, separators=(',', ':'))):
                self.validTran.emit(address, packet)
                return True
            else:
                print("WRONG SIGNATURE", self.__cryptor.getLastError())
                return False

    def checkTran(self, packet):
        try:
            jsonPacket = json.loads(packet)
        except json.JSONDecodeError:
            print("WRONG JSON PACKET, IN CHECKTRAN WITH 1 ARG")
            return False
        signature = jsonPacket.pop("SIGNATURE", None)
        sender = jsonPacket.get("SENDER", None)
        if signature and sender:

            if self.__cryptor.verifyMessage(
                    signature, sender,
                    json.dumps(jsonPacket, separators=(',', ':'))):
                return True
            else:
                print("WRONG SIGNATURE", self.__cryptor.getLastError())
                return False
예제 #2
0
class slaveWorker(QThread):
    floodPacket = pyqtSignal(str, str, int)
    sendPacket = pyqtSignal(str, str, int)
    setPurifyList = pyqtSignal(list)

    def __init__(self, myAddress: str, privateKey: str):
        super().__init__()
        self.cryptor = NooCrypto()
        self.transactionMemory = set()
        self.precommitedBlockHash = None
        self.signatureMemory = []
        self.transactionsInPBlock = set()
        self.stemAddress = None
        self.stemPublicKey = "0320ab99dee836df538e5e09a7c692c0aef02d91a11ce711992b95835f28243242"
        self.nodesCount = 0
        self.myAddress = myAddress
        self.packetStack = list()
        self.priorPacketStack = list()
        self.stackMutex = QMutex()
        self.signChecker = SignChecker()
        self.version = "0.1.0"
        self.redis_host = os.getenv("REDIS_PORT_6379_TCP_ADDR") or 'localhost'
        self.redis_port = os.getenv("REDIS_PORT_6379_TCP_PORT") or '6379'
        self.mongo_host = os.getenv("MONGO_PORT_27017_TCP_ADDR") or 'localhost'
        self.mongo_port = 27017
        self.mongo_conn = MongoClient(self.mongo_host, self.mongo_port)
        self.redis = redis.StrictRedis(self.redis_host, self.redis_port, db=1)
        self.mongo = self.mongo_conn.noosphere
        self.mongo_conn.drop_database(
            self.mongo)  # CLEAR MONGODB NOOSPHERE DATABASE

        self.lastCheckBlockBalance = 0
        self.currentTokenTypes = ["NZT"]
        self.blockReward = 10
        self.blocks_in_genesis = 10000000
        self.timeToGarbageCollector = 300 * 1000  #5 minutes
        self.MAX_TRAN_COUNT_IN_BLOCK = 9000
        self.MAX_TRAN_FOR_USER_IN_BLOCK = 9000
        self.tempMoneySum = 0
        self.updateBalanceStep = 1000
        #----------------------------------------- TOKENOMIKS BASIC
        self.voteFeeArray = {"VT": 10, "UFT": 100, "DFT": 100}
        self.allTokens = 23 * 1000 * 1000  #23 mln tokens
        self.tokensToReward = self.allTokens * 0.26  #reward tokens for 4 years
        #self.freezeToAT = 16*1000
        self.freezeToAT = 16
        self.freezeToVT = 1
        self.fee = 0
        self.freeZoneHeight = 12 * 60 * 24 * 365 * 4
        #self.freeZoneHeight = 10

        #-----------------------------------------
        #self.cryptor.generateKeys()
        print("PRIVATE KEY!", privateKey)
        self.cryptor.setPrivateKey(privateKey)
        print("PUBLIC KEY!", self.cryptor.getPublicKey())
        self.redis.flushdb()
        print(self.redis.set("VERSION", self.version))

        ##################### TEST
        #self.redis.zadd("BALANCE:NZT",10000, "0323f264fd64a684db1e36a2c97b58867e0625f797008206216576fea2114bdbca")
        #self.redis.zadd("BALANCE:NBL",10000, "027426df275f98bb0f66bb4f1a92352296be233b115415f709540e8caa80d820f2")
        #self.redis.zadd("RAW TRANSACTIONS", 1541777858, '{"TT":"ET","SENDER":"0323f264fd64a684db1e36a2c97b58867e0625f797008206216576fea2114bdbca","RECEIVER":"027426df275f98bb0f66bb4f1a92352296be233b115415f709540e8caa80d820f2","STT":"NZT","STC":"100","RTT":"NBL","RTC":"10","TST":"1541777858","SIGNATURE":"3b229fe53c21b472e82d4eec2a9bbde9c340c243b80fbd7ee1897b065708603352df740f1493d4d7215802065be5fde34fd8e0cae65afa11b5d69dc0cfd0a01a00"}')

    @staticmethod
    def isfloat(value):
        try:
            float(value)
            return True
        except:
            return False

    @pyqtSlot(str, str)
    def appendPacketToStack(self, address: str, packet: str):
        # if not self.signChecker.checkTran(packet):
        #     return
        jpacket = json.loads(packet)
        packetType = jpacket["TT"]

        self.stackMutex.lock()
        if packetType == "SG" or packetType == "CT" or packetType == "BL" or packetType == "PURIFIER":
            self.packetStack.insert(0, (address, packet))
        else:
            self.packetStack.append((address, packet))
        self.stackMutex.unlock()

    def getAnyFee(self, token_type):
        if token_type == "NZT":
            return self.fee
        else:
            return 0

    def getAnyVoteFee(self, voteType):
        if self.voteFeeArray.get(voteType) is None:
            return 0
        else:
            return self.voteFeeArray.get(voteType)

    def handler(self, address: str, packet: str):
        jpacket = json.loads(packet)

        print("RECIVE PACKET: ", jpacket["TT"])

        if jpacket["TT"] == "SG":
            if self.precommitedBlockHash == jpacket.get("HASH"):
                self.signatureMemory.append(jpacket.get("SIGNPB"))
            else:
                print("Recive old block SG - failed and return")
                return

            signNeedCount = len(set(self.signatureMemory))
            if signNeedCount >= int((2 / 3) * self.nodesCount):

                # CLEAR TRAN LIST #
                self.transactionMemory = self.transactionMemory - set(
                    self.transactionsInPBlock)
                # CLEAR TRAN LIST #

                self.cttime = 0
                print(self.signatureMemory)
                self.sendPacket.emit(
                    self.stemAddress,
                    JsonPackets.createCommitBlock(self.cryptor,
                                                  self.precommitedBlock,
                                                  self.signatureMemory), 1)
                self.transactionsInPBlock.clear()
                self.signatureMemory.clear()
            return

        if jpacket["TT"] == "CBRH":
            print("CBRH KEEP!")
            if jpacket[
                    "SENDER"] == self.stemPublicKey:  #IF SENDER IS MASTER NODE
                hash = jpacket["HASH"]

                JTPCB = json.loads(self.precommitedBlock)
                JTPCB.pop("SIGNATURE")

                if NooTree.hash(json.dumps(JTPCB,
                                           separators=(',', ':'))) != hash:
                    print("BAD HASH!!! FROM CBRH:",
                          NooTree.hash(self.precommitedBlock), "AND", hash)
                    # GIVE ME ALL SIZE BLOCK!
                    self.sendPacket.emit(
                        self.stemAddress,
                        JsonPackets.giveAllSizeBlock(self.cryptor,
                                                     jpacket["BHEIGHT"]), 1)
                    return

                block = json.loads(self.precommitedBlock)
                block.update({"STEM_SIGNATURE": jpacket["STEM_SIGNATURE"]})
                block.update({"NODE_SIGNATURES": jpacket["SIGNS"]})

                self.mongo.noochain.save(block)
                #self.redis.zadd("NOOCHAIN", block["BHEIGHT"], json.dumps(block, separators=(',', ':')))

                self.precommitedBlock = ""  # CLEAR MEMMORY AFTER SAVE BLOCK IN CHAIN
                self.checkBalance()

                # # DELETE AFTER ENDING MAIN BLOCKCHAIN EXPLORER
                # money = self.redis.zscore("MONEY MOVE", datetime.now().strftime("%Y-%m-%d"))
                #
                # if money is None:
                #     money = 0
                # else:
                #     if slaveWorker.isfloat(money):
                #         money = float(money)
                #     else:
                #         print("CLEAR MONEY BUF-BUF")
                #         money = 0
                # # DELETE AFTER ENDING MAIN BLOCKCHAIN EXPLORER

                for tran in block["TRANSACTIONS"]:

                    stran = json.dumps(tran, separators=(',', ':'))
                    print("ZREEEEEEEM:", stran,
                          self.redis.zrem("RAW TRANSACTIONS", stran))
                    self.redis.zrem("RAW TRANSACTIONS", stran)

                    if tran["TT"] == "ET":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                    if tran["TT"] == "ST":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                    if tran["TT"] == "AT":
                        sender = tran["SENDER"]
                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.zadd("APPLICANTS", int(block["BHEIGHT"]),
                                        sender)
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                    if tran["TT"] == "UAT":
                        sender = tran["SENDER"]
                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.zrem("APPLICANTS", sender)
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                    if tran["TT"] == "VT":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        votes = int(tran["VOTES"])

                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                        tempVotes = self.redis.zscore("VOTES:" + sender,
                                                      receiver)
                        if tempVotes == None:
                            tempVotes = 0
                        self.redis.zadd("VOTES:" + receiver, tempVotes + votes,
                                        sender)

                        tempUntVotes = self.redis.zscore("UNTVOTES", sender)
                        if tempUntVotes == None:
                            tempUntVotes = 0
                        self.redis.zadd("UNTVOTES", tempUntVotes + votes,
                                        sender)

                    if tran["TT"] == "UFT":  #UPFEETRAN
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        votes = int(tran["VOTES"])

                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                        tempVotes = self.redis.zscore("UFT-VOTES:" + sender,
                                                      receiver)
                        if tempVotes == None:
                            tempVotes = 0
                        self.redis.zadd("UFT-VOTES:" + sender,
                                        tempVotes + votes, receiver)

                        tempUntVotes = self.redis.zscore(
                            "UFT-UNTVOTES", sender)
                        if tempUntVotes == None:
                            tempUntVotes = 0
                        self.redis.zadd("UFT-UNTVOTES", tempUntVotes + votes,
                                        sender)

                    if tran["TT"] == "DFT":  #DOWNFEETRAN
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        votes = int(tran["VOTES"])

                        sign = tran["SIGNATURE"]
                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                        tempVotes = self.redis.zscore("DFT-VOTES:" + sender,
                                                      receiver)
                        if tempVotes == None:
                            tempVotes = 0
                        self.redis.zadd("DFT-VOTES:" + sender,
                                        tempVotes + votes, receiver)

                        tempUntVotes = self.redis.zscore(
                            "DFT-UNTVOTES", sender)
                        if tempUntVotes == None:
                            tempUntVotes = 0
                        self.redis.zadd("DFT-UNTVOTES", tempUntVotes + votes,
                                        sender)

                    if tran["TT"] == "UVT":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        sign = tran["SIGNATURE"]

                        self.redis.zadd("COMPLETE TRANSACTIONS",
                                        int(block["BHEIGHT"]),
                                        NooTree.hash(sign))
                        self.redis.zrem("VOTES:" + sender, receiver)
                        self.redis.set("TRANSACTIONS:" + NooTree.hash(sign),
                                       stran)

                #self.redis.zadd("MONEY MOVE", money, datetime.now().strftime("%Y-%m-%d"))

        if jpacket["TT"] == "CBR":
            print("CBR KEEP!")
            if jpacket[
                    "SENDER"] == self.stemPublicKey:  #IF SENDER IS MASTER NODE
                block = jpacket["BLOCK"]
                block.update({"STEM_SIGNATURE": jpacket["SIGNATURE"]})
                self.mongo.noochain.save(block)
                #self.redis.zadd("NOOCHAIN", block["BHEIGHT"], json.dumps(block, separators=(',', ':')))
                self.checkBalance()

                for tran in block["TRANSACTIONS"]:

                    self.redis.zrem("RAW TRANSACTIONS",
                                    json.dumps(tran, separators=(',', ':')))

                    if tran["TT"] == "ST":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        sign = tran["SIGNATURE"]
                        #money += float(tran["CTOKEN"])
                        self.redis.zadd(
                            "COMPLETE TRANSACTIONS", int(block["BHEIGHT"]),
                            str(sender) + str(receiver) + str(sign))

                    if tran["TT"] == "AT":
                        sender = tran["SENDER"]
                        self.redis.zadd("APPLICANTS", int(block["BHEIGHT"]),
                                        sender)

                    if tran["TT"] == "UAT":
                        sender = tran["SENDER"]
                        self.redis.zrem("APPLICANTS", sender)

                    if tran["TT"] == "VT":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        votes = tran["VOTES"]
                        self.redis.zadd("VOTES:" + sender, votes, receiver)

                        temp_votes = self.redis.zscore("UNTVOTES", sender)
                        if temp_votes is None:
                            temp_votes = 0

                        self.redis.zadd("UNTVOTES", temp_votes + votes, sender)

                    if tran["TT"] == "UVT":
                        sender = tran["SENDER"]
                        receiver = tran["RECEIVER"]
                        self.redis.zrem("VOTES:" + sender, receiver)

                        del_votes = self.redis.zscore("VOTES:" + sender,
                                                      receiver)
                        if del_votes is None:
                            del_votes = 0
                        self.redis.zrem("VOTES:" + sender, receiver)

                        temp_votes = self.redis.zscore("UNTVOTES", sender)
                        if temp_votes is None:
                            temp_votes = 0
                        self.redis.zadd("UNTVOTES", temp_votes - del_votes,
                                        sender)

                    #self.redis.zadd("MONEY MOVE", money, datetime.now().strftime("%Y-%m-%d"))

        # IF BLOCK FROM STEM NODE

        if jpacket["TT"] == "BL":
            # IF NEED SIGNATURE WORK
            transactions = jpacket["TRANSACTIONS"]
            trans = []
            for tran in transactions:
                trans.append(json.dumps(tran, separators=(',', ':')))

            unionTran = set(trans) - self.transactionMemory
            okSign = True

            if len(unionTran) != 0:  # Build block with another transactions
                for newTran in unionTran:
                    jnewTran = json.loads(newTran)
                    signature = jnewTran.pop("SIGNATURE")
                    sender = jnewTran.get("SENDER")
                    if not self.cryptor.verifyMessage(
                            signature, sender,
                            json.dumps(jpacket, separators=(',', ':'))):
                        self.sendPacket.emit(
                            address,
                            JsonPackets.createСomplaint(
                                self.cryptor, packet, newTran), 1)
                        okSign = False

            if okSign:  # Good block!
                precommitedBlock = json.dumps(jpacket, separators=(',', ':'))
                self.sendPacket.emit(
                    address,
                    JsonPackets.createSignaturePrecommitedBlock(
                        self.cryptor, precommitedBlock,
                        NooTree.hash(precommitedBlock)), 1)

            return

        if jpacket["TT"] == "CT":

            self.updateFee()
            print("RECEIVE PACKET:", packet)

            #blockchain_height = self.redis.zcard("NOOCHAIN")

            blockchain_height = self.mongo.noochain.find().count()
            # pymongo_cursor = self.mongo.noochain.find().sort("BHEIGHT", pymongo.ASCENDING).limit(1)
            # blockchain_height = dict(pymongo_cursor).get("BHEIGHT")

            if blockchain_height is None:
                blockchain_height = 0

            if blockchain_height != jpacket["NBH"]:
                print("NBH not Supported in my version BlockChain!")
                #print(blockchain_height, jpacket["NBH"])
                self.sendPacket.emit(self.stemAddress,
                                     JsonPackets.badAnswer(self.cryptor), 1)
                return False

            txmas = []
            txcount = self.redis.zcard("RAW TRANSACTIONS")
            if txcount < self.MAX_TRAN_COUNT_IN_BLOCK:
                txmas = self.redis.zrange("RAW TRANSACTIONS", 0, -1)
            else:
                txmas = self.redis.zrange("RAW TRANSACTIONS", 0,
                                          self.MAX_TRAN_COUNT_IN_BLOCK)

            tranUserCount = {}
            tempBalanceMemmory = {}
            tempDictBalanceMemmory = {}

            decodeTxmas = []

            print("TXMAS_LEN:", len(txmas))

            for tran in txmas:
                try:
                    jtran = json.loads(tran)
                except Exception:
                    print("000. GO TO HELL!", tran)
                    continue

                tokenPrefix = "NZT"

                if jtran["TT"] == "ET":
                    print("STEP 1")
                    sender = jtran["SENDER"]  # money sender
                    receiver = jtran["RECEIVER"]  # money receiver

                    stt = jtran["STT"]  # money sender token type
                    rtt = jtran["RTT"]  # money receiver token type
                    stc = jtran["STC"]  # money sender token count
                    rtc = jtran["RTC"]  # money receiver token count

                    # if jtran.get("INIT_SIGNATURE") is not None:
                    #     init_sign = jtran.pop("INIT_SIGNATURE")
                    # else:
                    #     init_sign = None
                    #
                    # sign = jtran.pop("SIGNATURE")
                    #
                    # if self.cryptor.verifyMessage(sign, sender, json.dumps(tran, separators=(',', ':'))):
                    #     tempBalance = tempBalanceMemmory.get(currentSender)

                    # CHECK DOUBLE MONEY SEND
                    tempSBalanceMemmory = tempDictBalanceMemmory.get(stt)
                    if tempSBalanceMemmory is None:
                        tempSBalanceMemmory = {}
                        tempSBalance = self.redis.zscore(
                            "BALANCE:" + stt, sender)
                    else:
                        tempSBalance = tempSBalanceMemmory.get(sender)
                        if tempSBalance is None:
                            tempSBalance = self.redis.zscore(
                                "BALANCE:" + stt, sender)

                    tempRBalanceMemmory = tempDictBalanceMemmory.get(rtt)
                    if tempRBalanceMemmory is None:
                        tempRBalanceMemmory = {}
                        tempRBalance = self.redis.zscore(
                            "BALANCE:" + rtt, receiver)
                    else:
                        tempRBalance = tempRBalanceMemmory.get(currentSender)
                        if tempRBalance is None:
                            tempRBalance = self.redis.zscore(
                                "BALANCE:" + rtt, receiver)

                    if tempSBalance is None:
                        print("1. GO TO HELL ET!")
                        self.redis.zadd("FAILED TRANSACTIONS", 1,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        continue

                    if tempRBalance is None:
                        print("1. GO TO HELL ET!")
                        self.redis.zadd("FAILED TRANSACTIONS", 1,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        continue

                    if stt == "NZT":
                        totalSBalance = tempSBalance - self.getFreezeTokens(
                            sender)
                    else:
                        totalSBalance = tempSBalance

                    if totalSBalance < (float(stc) + self.getAnyFee(stt)):
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        self.redis.zadd("FAILED TRANSACTIONS", 2,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        print("2. GO TO HELL ET!")
                        continue
                    else:
                        tempSBalance = tempSBalance - (float(stc) +
                                                       self.getAnyFee(stt))

                    if stt == "NZT":
                        totalRBalance = tempRBalance - self.getFreezeTokens(
                            receiver)
                    else:
                        totalRBalance = tempRBalance

                    if totalRBalance < (float(stc) + self.getAnyFee(rtt)):
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        self.redis.zadd("FAILED TRANSACTIONS", 2,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        print("2. GO TO HELL ET!")
                        continue
                    else:
                        tempRBalance = tempRBalance - (float(rtc) +
                                                       self.getAnyFee(rtt))

                    tempSBalanceMemmory.update({sender: tempSBalance})
                    tempRBalanceMemmory.update({receiver: tempRBalance})
                    tempDictBalanceMemmory.update({stt: tempSBalanceMemmory})
                    tempDictBalanceMemmory.update({rtt: tempRBalanceMemmory})

                    decodeTxmas.append(tran)

                if jtran["TT"] == "AT":
                    currentSender = jtran["SENDER"]

                    # CHECK DOUBLE MONEY SEND
                    tempBalanceMemmory = tempDictBalanceMemmory.get("NZT")
                    if tempBalanceMemmory is None:
                        tempBalanceMemmory = {}
                        tempBalance = self.redis.zscore(
                            "BALANCE:NZT", currentSender)
                    else:
                        tempBalance = tempBalanceMemmory.get(currentSender)
                        if tempBalance is None:
                            tempBalance = self.redis.zscore(
                                "BALANCE:NZT", currentSender)

                    if tempBalance is None:
                        print("1. GO TO HELL AT!")
                        self.redis.zadd("FAILED TRANSACTIONS", 1,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        continue

                    if (tempBalance - self.getFreezeTokens(currentSender)
                        ) < self.freezeToAT:
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        self.redis.zadd("FAILED TRANSACTIONS", 2,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        print("2. GO TO HELL AT!")
                        continue
                    else:
                        tempBalance = tempBalance - self.freezeToAT

                    tempBalanceMemmory.update({currentSender: tempBalance})
                    tempDictBalanceMemmory.update({"NZT": tempBalanceMemmory})
                    decodeTxmas.append(tran)

                if jtran["TT"] == "VT" or jtran["TT"] == "UFT" or jtran[
                        "TT"] == "DFT":  # VOTE, UPFEE, DOWNFEE
                    currentSender = jtran["SENDER"]

                    # CHECK DOUBLE MONEY SEND
                    tempBalanceMemmory = tempDictBalanceMemmory.get("NZT")
                    if tempBalanceMemmory is None:
                        tempBalanceMemmory = {}
                        tempBalance = self.redis.zscore(
                            "BALANCE:NZT", currentSender)
                    else:
                        tempBalance = tempBalanceMemmory.get(currentSender)
                        if tempBalance is None:
                            tempBalance = self.redis.zscore(
                                "BALANCE:NZT", currentSender)

                    if tempBalance is None:
                        print("1. GO TO HELL VT!")
                        self.redis.zadd("FAILED TRANSACTIONS", 1,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        continue

                    if (tempBalance - self.getFreezeTokens(currentSender)
                        ) < self.freezeToVT * int(jtran["VOTES"]):
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        self.redis.zadd("FAILED TRANSACTIONS", 2,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        print("2. GO TO HELL VT!")
                        continue
                    else:
                        if jtran["TT"] == "VT":
                            tempBalance = tempBalance - self.getAnyVoteFee(
                                jtran["TT"]) * int(jtran["VOTES"])
                        if jtran["TT"] == "UFT":
                            tempBalance = tempBalance - self.getAnyVoteFee(
                                jtran["TT"]) * int(jtran["VOTES"])
                        if jtran["TT"] == "DFT":
                            tempBalance = tempBalance - self.getAnyVoteFee(
                                jtran["TT"]) * int(jtran["VOTES"])

                    tempBalanceMemmory.update({currentSender: tempBalance})
                    tempDictBalanceMemmory.update({"NZT": tempBalanceMemmory})
                    decodeTxmas.append(tran)

                if jtran["TT"] == "ST":
                    currentSender = jtran["SENDER"]
                    # CHECK 3 TRAN FROM ONE USER
                    count = tranUserCount.get(currentSender)
                    if count is None:
                        tranUserCount.update({currentSender: 1})
                    else:
                        if count >= self.MAX_TRAN_FOR_USER_IN_BLOCK:
                            continue
                        else:
                            tranUserCount.update({currentSender: (count + 1)})

                    # CHECK DOUBLE MONEY SEND
                    tempBalanceMemmory = tempDictBalanceMemmory.get(
                        jtran["TTOKEN"])
                    if tempBalanceMemmory is None:
                        tempBalanceMemmory = {}
                        tempBalance = self.redis.zscore(
                            "BALANCE:" + jtran["TTOKEN"], currentSender)
                    else:
                        tempBalance = tempBalanceMemmory.get(currentSender)
                        if tempBalance is None:
                            tempBalance = self.redis.zscore(
                                "BALANCE:" + jtran["TTOKEN"], currentSender)

                    if tempBalance is None:
                        print("1. GO TO HELL!")
                        self.redis.zadd("FAILED TRANSACTIONS", 1,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        continue

                    if (tempBalance - self.getFreezeTokens(currentSender)) < (
                            float(jtran["CTOKEN"]) + self.fee):
                        self.redis.zrem("RAW TRANSACTIONS", tran)
                        self.redis.zadd("FAILED TRANSACTIONS", 2,
                                        NooTree.hash(jtran["SIGNATURE"]))
                        print("2. GO TO HELL!")
                        continue
                    else:
                        tempBalance = tempBalance - (float(jtran["CTOKEN"]) +
                                                     self.fee)

                    tempBalanceMemmory.update({currentSender: tempBalance})
                    tempDictBalanceMemmory.update(
                        {jtran["TTOKEN"]: tempBalanceMemmory})
                    decodeTxmas.append(tran)

            self.transactionsInPBlock = decodeTxmas
            precommitBlock = JsonPackets.createPrecommitBlock(
                self.cryptor, self.version, self.transactionsInPBlock,
                blockchain_height, self.fee)

            # CLEAR ZONE #
            self.signatureMemory.clear()
            # CLEAR ZONE #

            self.precommitedBlock = precommitBlock
            self.precommitedBlockHash = NooTree.hash(precommitBlock)
            signature = json.loads(precommitBlock).get("SIGNATURE")
            print("APPEND MY SIGNATURE!", signature)
            self.signatureMemory.append(signature)

            signNeedCount = len(set(self.signatureMemory))

            if signNeedCount >= math.ceil(
                (2 / 3) * self.nodesCount
            ):  # !!!ONLY WORK IN TESTNET WITH ONE NODE!!!
                print("SIGN COMPLETE")
                #self.transactionMemory = self.transactionMemory - self.transactionsInPBlock  # ДОБАВИТЬ ПОИСК И УДАЛЕНИЕ
                # CLEAR TRAN LIST #

                self.sendPacket.emit(
                    self.stemAddress,
                    JsonPackets.createCommitBlock(self.cryptor,
                                                  self.precommitedBlock,
                                                  self.signatureMemory), 1)

                self.transactionsInPBlock.clear()
                self.signatureMemory.clear()
            else:
                print("SIGN NOT COMPLETE")
                #print ("ZONE 2")
                self.floodPacket.emit(precommitBlock, str(), 1)
            return

        if jpacket["TT"] == "PURIFIER":
            #print("RECEIVE PACKET:", packet)
            self.updateFee()
            self.stemAddress = address

            pymongo_cursor = self.mongo.noochain.find().sort(
                "BHEIGHT", pymongo.ASCENDING).limit(1)
            blockchain_height = dict(pymongo_cursor).get("BHEIGHT")

            if blockchain_height is None:
                blockchain_height = 0

            #blockchain_height = self.redis.zcard("NOOCHAIN")

            tempList = jpacket["CLEAN_LIST"]
            tempKeyList = jpacket["CLEAN_KEY_LIST"]
            if len(tempList) != len(tempKeyList):
                print("BAD PURIFIER BLOCK! STOP WORK!")
                return

            if blockchain_height == 0 or blockchain_height % self.blocks_in_genesis == 0:
                self.mongo.noochain.save(jpacket)
                #self.redis.zadd("NOOCHAIN", jpacket["BHEIGHT"], json.dumps(jpacket, separators=(',', ':')))

            NLIST = []
            for temp in zip(tempList, tempKeyList):
                NLIST.append({
                    "ADDRESS": temp[0],
                    "TYPE": "1",
                    "PUBLICKEY": temp[1]
                })

            self.redis.set("NODES LIST",
                           json.dumps({"NLIST": NLIST}, separators=(',', ':')))

            self.nodesCount = len(tempList)
            self.setPurifyList.emit(tempList)
            return

        # if jpacket["TT"] == "BT":
        #     #print("RECEIVE BT")
        #     result = self.benchmark.benchmarkStart(jpacket["START"])
        #     packet = JsonPackets.myBenchmarkResult(self.cryptor, result, jpacket["START"])
        #     #print("SEND MBR")
        #     self.sendPacket.emit(address, packet, 1)
        #     return

        # if jpacket["TT"] == "AT":
        #     print("RECEIVE PACKET:", packet)
        #     self.transactionMemory.add(packet)
        #     self.floodPacket.emit(packet, address, 0)
        #     return

        # if jpacket["TT"] == "ST":
        #     #if  not self.checkTranForBalance(jpacket):
        #         #return
        #     self.transactionMemory.add(packet)
        #     self.floodPacket.emit(packet, address, 0)
        #     return

    def getFreezeTokens(self, wallet, token_type="NZT"):
        freezeForVotes = self.redis.zscore("UNTVOTES", wallet)
        if freezeForVotes is None:
            freezeForVotes = 0
        freezeForVotes = freezeForVotes * self.freezeToVT

        if self.redis.zscore("APPLICANTS", wallet) is None:
            freezeForApplicant = 0
        else:
            freezeForApplicant = self.freezeToAT

        return freezeForApplicant + freezeForVotes

    def garbageCollector(self):
        bheight = self.mongo.noochain.find().count()
        if bheight is None:
            bheight = 0

        endBlock = bheight - 12 * 60
        if endBlock < 0:
            endBlock = 0

        oldTxs = self.redis.zrangebyscore("COMPLETE TRANSACTIONS", '0',
                                          str(endBlock))

        for tran in oldTxs:
            print("SEARCH:", "TRANSACTIONS:" + tran.decode())
            tranbody = self.redis.get("TRANSACTIONS:" + tran.decode())

            if tranbody is None:
                continue

            jtranbody = json.loads(tranbody)
            jtranbody.update({"_id": tran.decode()})
            self.mongo.complete.save(jtranbody)
            self.redis.delete("TRANSACTIONS:" + tran.decode())
            self.redis.zrem("COMPLETE TRANSACTIONS", tran)

        oldFTxs = self.redis.zrange("FAILED TRANSACTIONS", 0, -1)
        for ftran in oldFTxs[0:int(len(oldFTxs) / 2)]:
            self.redis.zrem("FAILED TRANSACTIONS", ftran)

        return True

    def updateFee(self):
        #bheight = self.redis.zcard("NOOCHAIN")
        bheight = self.mongo.noochain.find().count()

        if bheight is None:
            bheight = 0

        TrXcount = len(
            self.redis.zrange("COMPLETE TRANSACTIONS", bheight - 1000,
                              bheight)) / 1000

        if bheight > self.freeZoneHeight:
            if TrXcount >= 10000:
                self.fee = 0.0001

            if TrXcount >= 5000 or TrXcount < 10000:
                self.fee = 0.001

            if TrXcount >= 3000 or TrXcount < 5000:
                self.fee = 0.003

            if TrXcount >= 100 or TrXcount < 3000:
                self.fee = 0.005

            if TrXcount < 100:
                self.fee = 0.01

        print("CURRENT FEE IN THIS TIME:", self.fee)
        return

    def beApplicant(self):
        if self.stemAddress is None:
            return False

        packet = JsonPackets.wantBeApplicant(self.cryptor)
        #print ("SEND BEAPP", self.stemAddress)
        self.sendPacket.emit(self.stemAddress, packet, 1)

    def checkTranForBalance(self, jtran: dict):
        sender = jtran["SENDER"]
        type = jtran["TTOKEN"]
        count = jtran["CTOKEN"]
        walletBalance = self.BALANCE.get(sender)

        if count < 0:
            return False
        if type != self.currentTokenType:
            return False
        if walletBalance is None:
            return False
        if walletBalance < count:
            return False
        return True

    def checkTranForBalanceAttrs(self, sender, type, count):
        walletBalance = self.BALANCE.get(sender)

        if count < 0:
            return False
        if type != self.currentTokenType:
            return False
        if walletBalance is None:
            return False
        if walletBalance < count:
            return False
        return True

    def sliceFloat(self, money: float):
        return "{0:.8f}".format(money)

    def balanceMainWorkRedis(self, bchain: list):
        for jblock in bchain:
            #jblock = json.loads(block)

            if jblock['TT'] == "BL":
                trans = jblock['TRANSACTIONS']
                if self.redis.zscore("BALANCE:NZT", jblock['SENDER']) is None:
                    self.redis.zadd("BALANCE:NZT", 0, jblock['SENDER'])

                blockSenderBalance = self.redis.zscore("BALANCE:NZT",
                                                       jblock['SENDER'])
                blockSenderBalance += self.blockReward
                print("BALANCE_BHEIGHT", jblock['BHEIGHT'])
                print("FREEZZE:", self.getFreezeTokens(jblock['SENDER']))
                print(
                    "ADDING BALANCE NZT TO VALIDATOR:", blockSenderBalance -
                    self.getFreezeTokens(jblock['SENDER']), jblock['SENDER'])
                self.redis.zadd("BALANCE:NZT", blockSenderBalance,
                                jblock['SENDER'])

                for tran in trans:
                    if tran["TT"] == "ST" and self.currentTokenTypes.count(
                            tran["TTOKEN"]) and float(tran["CTOKEN"]) > 0:
                        tokenPrefix = tran["TTOKEN"]
                        if tran['SENDER'] == tran['RECEIVER']:
                            continue
                        if self.redis.zscore("BALANCE:" + tokenPrefix,
                                             tran['SENDER']) is None:
                            self.redis.zadd("BALANCE:" + tokenPrefix, 0,
                                            tran['SENDER'])
                        if self.redis.zscore("BALANCE:" + tokenPrefix,
                                             tran['RECEIVER']) is None:
                            self.redis.zadd("BALANCE:" + tokenPrefix, 0,
                                            tran['RECEIVER'])
                        senderBalance = self.redis.zscore(
                            "BALANCE:" + tokenPrefix, tran['SENDER'])
                        receiverBalance = self.redis.zscore(
                            "BALANCE:" + tokenPrefix, tran["RECEIVER"])
                        senderBalance = senderBalance - float(tran["CTOKEN"])
                        receiverBalance = receiverBalance + float(
                            tran["CTOKEN"])
                        self.redis.zadd("BALANCE:" + tokenPrefix,
                                        self.sliceFloat(senderBalance),
                                        tran["SENDER"])
                        self.redis.zadd("BALANCE:" + tokenPrefix,
                                        self.sliceFloat(receiverBalance),
                                        tran["RECEIVER"])

                    if tran["TT"] == "ET" and self.currentTokenTypes.count(
                            tran["STT"]) and self.currentTokenTypes.count(
                                tran["RTT"]) and float(
                                    tran["STC"]) > 0 and float(
                                        tran["RTC"]) > 0:
                        tokenSenderPrefix = tran["STT"]
                        tokenReceiverPrefix = tran["RTT"]

                        if tran['SENDER'] == tran['RECEIVER']:
                            continue

                        #MONEY SEND
                        if self.redis.zscore("BALANCE:" + tokenSenderPrefix,
                                             tran['SENDER']) is None:
                            self.redis.zadd("BALANCE:" + tokenSenderPrefix, 0,
                                            tran['SENDER'])
                        if self.redis.zscore("BALANCE:" + tokenSenderPrefix,
                                             tran['RECEIVER']) is None:
                            self.redis.zadd("BALANCE:" + tokenSenderPrefix, 0,
                                            tran['RECEIVER'])
                        senderBalance = self.redis.zscore(
                            "BALANCE:" + tokenSenderPrefix, tran['SENDER'])
                        receiverBalance = self.redis.zscore(
                            "BALANCE:" + tokenSenderPrefix, tran["RECEIVER"])
                        senderBalance = senderBalance - float(tran["STC"])
                        receiverBalance = receiverBalance + float(tran["STC"])
                        self.redis.zadd("BALANCE:" + tokenSenderPrefix,
                                        self.sliceFloat(senderBalance),
                                        tran["SENDER"])
                        self.redis.zadd("BALANCE:" + tokenSenderPrefix,
                                        self.sliceFloat(receiverBalance),
                                        tran["RECEIVER"])

                        #GOODS SEND
                        if self.redis.zscore("BALANCE:" + tokenReceiverPrefix,
                                             tran['RECEIVER']) is None:
                            self.redis.zadd("BALANCE:" + tokenReceiverPrefix,
                                            0, tran['RECEIVER'])
                        if self.redis.zscore("BALANCE:" + tokenReceiverPrefix,
                                             tran['SENDER']) is None:
                            self.redis.zadd("BALANCE:" + tokenReceiverPrefix,
                                            0, tran['SENDER'])

                        receiverBalance = self.redis.zscore(
                            "BALANCE:" + tokenReceiverPrefix, tran['RECEIVER'])
                        senderBalance = self.redis.zscore(
                            "BALANCE:" + tokenReceiverPrefix, tran["SENDER"])
                        receiverBalance = receiverBalance - float(tran["RTC"])
                        senderBalance = senderBalance + float(tran["RTC"])

                        self.redis.zadd("BALANCE:" + tokenReceiverPrefix,
                                        self.sliceFloat(receiverBalance),
                                        tran["RECEIVER"])
                        self.redis.zadd("BALANCE:" + tokenReceiverPrefix,
                                        self.sliceFloat(senderBalance),
                                        tran["SENDER"])

    def checkBalance(self, updateLen=-1):

        #bheight = self.redis.zcard("NOOCHAIN")
        #pymongo_cursor = self.mongo.noochain.find().sort("BHEIGHT", pymongo.ASCENDING).limit(1)
        #bheight = dict(pymongo_cursor).get("BHEIGHT")
        bheight = self.mongo.noochain.find().count()

        if updateLen == -1:
            print("START:", self.lastCheckBlockBalance, "STOP:", bheight)

            bchain = list(
                self.mongo.noochain.find(
                    {"BHEIGHT": {
                        "$gte": int(self.lastCheckBlockBalance)
                    }}))
            print("BCH", bchain)

            #bchain = self.redis.zrange("NOOCHAIN", self.lastCheckBlockBalance, bheight)
            self.lastCheckBlockBalance = bheight
            self.balanceMainWorkRedis(bchain)
        else:  ### STEP MODE
            step = self.lastCheckBlockBalance

            while step < bheight:
                nextStep = step + self.updateBalanceStep
                if nextStep > bheight:
                    nextStep = bheight

                #bchain = self.redis.zrange("NOOCHAIN", step, nextStep)

                bchain = list(
                    self.mongo.noochain.find([{
                        "BHEIGHT": {
                            "$gt": step
                        }
                    }, {
                        "BHEIGHT": {
                            "$lt": nextStep
                        }
                    }]))
                step = nextStep
                self.balanceMainWorkRedis(bchain)

            self.lastCheckBlockBalance = nextStep
        return

    def run(self):
        while True:
            self.stackMutex.lock()
            if len(self.packetStack):
                packet = self.packetStack.pop(0)
            else:
                self.stackMutex.unlock()
                continue

            self.stackMutex.unlock()
            address = packet[0]
            packet = packet[1]

            #if self.signChecker.checkTran(packet): // Проверка подписи!
            self.handler(address, packet)
예제 #3
0
class FlaskWorker():
    def __init__(self):
        self.app = Flask(__name__)
        self.app.config[
            'MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 + 1  # 16 Mb - max binary content size
        self.redis_host = os.getenv("REDIS_PORT_6379_TCP_ADDR") or 'localhost'
        self.redis_port = os.getenv("REDIS_PORT_6379_TCP_PORT") or '6379'
        self.redis = redis.StrictRedis(self.redis_host, self.redis_port, db=2)
        self.cryptor = NooCrypto()
        self.cryptor.generateKeys()

        self.mongo_host = os.getenv("MONGO_PORT_27017_TCP_ADDR") or 'localhost'
        self.mongo_port = os.getenv("MONGO_PORT_27017_TCP_PORT") or 27017
        self.mongo_conn = MongoClient(self.mongo_host, self.mongo_port)
        self.mongo = self.mongo_conn.rootShard
        self.mongo_conn.drop_database(
            self.mongo)  # CLEAR MONGODB NOOSPHERE DATABASE

        @self.app.route('/img/<path:path>')
        def send_img(path):
            return send_from_directory('web/img', path)

        @self.app.route('/js/<path:path>')
        def send_js(path):
            return send_from_directory('web/js', path)

        @self.app.route('/css/<path:path>')
        def send_css(path):
            return send_from_directory('web/css', path)

        @self.app.route('/<path:path>')
        def send_html(path):
            print(path)
            return send_from_directory('web', path)

        @self.app.route('/r/testRootAPI',
                        methods=['GET',
                                 'POST'])  # TEST DB STRUCT FOR DEVELOP GO API
        def testRootAPI():
            if not request:
                abort(400)

            print(self.mongo["SHARD LIST"].save({
                "NAME":
                "SUPER SHARD",
                "OWNER":
                "SUPER OWNER",
                "INFO":
                "SUPER INFO",
                "STEMIP":
                "SUPER STEM IP ADDRESS"
            }))
            print(self.mongo["SHARD NODES LIST"].save({
                "NAME": "SUPER SHARD NODE",
                "SHARD ID": 1735262821,
                "NODE IP": "127.0.0.2",
                "NODE TYPE": "STANDART 1"
            }))
            print(self.mongo["SHARD NODES LIST"].save({
                "NAME": "SUPER SHARD NODE",
                "SHARD ID": 1735262821,
                "NODE IP": "127.0.0.3",
                "NODE TYPE": "STANDART 2"
            }))
            print(self.mongo["SHARD NODES LIST"].save({
                "NAME": "SUPER SHARD NODE",
                "SHARD ID": 1735262821,
                "NODE IP": "127.0.0.4",
                "NODE TYPE": "STANDART 2"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HEIGHT"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                254,
                "LAST HASH":
                "SUPER PUPER HASH"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                100,
                "BLOCK HASH":
                "SUPER BLOCK HASH"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                101,
                "BLOCK HASH":
                "SUPER BLOCK HASH"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                102,
                "BLOCK HASH":
                "SUPER BLOCK HASH"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                103,
                "BLOCK HASH":
                "SUPER BLOCK HASH"
            }))
            print(self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                1735262821,
                "BHEIGHT":
                104,
                "BLOCK HASH":
                "SUPER BLOCK HASH"
            }))

            return json.dumps({
                "STATUS": "OK",
                "DESCRIPTION": ""
            },
                              separators=(',', ':'))

        @self.app.route('/r/registerNewShard', methods=['POST'])
        def regNewShard():
            if not request:
                abort(400)

            jdata = json.loads(request.data)

            shardName = jdata.get('sn')
            shardSign = jdata.get('sg')  # sign(shardName) - !!! OR ANOTHER
            shardOwner = jdata.get('ow')
            shardInfo = jdata.get('si')
            shardStemIp = jdata.get('ip')

            if self.mongo["SHARD LIST"].find({"NAME": shardName}).count() != 0:
                return json.dumps(
                    {
                        "STATUS": "FAIL",
                        "DESCRIPTION": "SHARD ALREADY EXISTS"
                    },
                    separators=(',', ':'))

            # check payment for create shard
            # CHECK SIGN CORRECTLY
            print({
                "NAME": shardName,
                "OWNER": shardOwner,
                "INFO": shardInfo,
                "SIGN": shardSign,
                "STEMIP": shardStemIp
            })
            shardId = self.mongo["SHARD LIST"].save({
                "NAME": shardName,
                "OWNER": shardOwner,
                "INFO": shardInfo,
                "SIGN": shardSign,
                "STEMIP": shardStemIp
            })
            return json.dumps({
                "STATUS": "OK",
                "DESCRIPTION": str(shardId)
            },
                              separators=(',', ':'))

        @self.app.route('/r/addNode', methods=['POST'])
        def addNodeToShard():
            if not request:
                abort(400)

            jdata = json.loads(request.data)

            nodeName = jdata.get('nn')
            shardId = jdata.get('si')
            nodeIp = jdata.get('ni')
            nodePuk = jdata.get('puk')
            nodeType = jdata.get('nt')

            #CHECK NODE APP BEFORE ADDING IN LIST (PING NODE)
            if self.mongo["SHARD LIST"].find({
                    "_id": ObjectId(shardId)
            }).count() != 1:
                return json.dumps(
                    {
                        "STATUS": "FAIL",
                        "DESCRIPTION": "SHARD NO EXIST"
                    },
                    separators=(',', ':'))

            signature = jdata.pop("sg")
            puk = self.mongo["SHARD LIST"].find_one({
                "_id": ObjectId(shardId)
            }).get("OWNER")

            if not self.cryptor.verifyMessage(
                    signature, puk, json.dumps(jdata, separators=(',', ':'))):
                return json.dumps(
                    {
                        "STATUS": "FAIL",
                        "DESCRIPTION": "SIGNATURE VERIFY IS FAILED"
                    },
                    separators=(',', ':'))

            if self.mongo["SHARD NODES LIST"].find({
                    "SHARD ID": shardId,
                    "NODE IP": nodeIp
            }).count() != 0:
                print(3)
                return json.dumps(
                    {
                        "STATUS":
                        "FAIL",
                        "DESCRIPTION":
                        "NODE WITH THIS IP ALREADY EXISTS, YOU HAVE TO DELETE IT BEFORE"
                    },
                    separators=(',', ':'))
            shardId = self.mongo["SHARD NODES LIST"].save({
                "NAME": nodeName,
                "SHARD ID": shardId,
                "NODE IP": nodeIp,
                "NODE PKEY": nodePuk,
                "NODE TYPE": nodeType
            })
            return json.dumps({
                "STATUS": "OK",
                "DESCRIPTION": str(shardId)
            },
                              separators=(',', ':'))

        @self.app.route('/r/saveBlockHash', methods=['POST'])
        def saveBlockHash():
            if not request:
                abort(400)

            jdata = json.loads(request.data)

            bheight = jdata.get('bh')
            hash = jdata.get('ha')
            shardId = jdata.get('si')
            signature = jdata.pop('sg')
            if self.mongo["SHARD LIST"].find({
                    "_id": ObjectId(shardId)
            }).count() == 0:
                return json.dumps(
                    {
                        "STATUS": "FAIL",
                        "DESCRIPTION": "SHARD NO EXIST"
                    },
                    separators=(',', ':'))
            puk = self.mongo["SHARD LIST"].find_one({
                "_id": ObjectId(shardId)
            }).get("OWNER")
            if not self.cryptor.verifyMessage(
                    signature, puk, json.dumps(jdata, separators=(',', ':'))):
                return json.dumps(
                    {
                        "STATUS": "FAIL",
                        "DESCRIPTION": "SIGNATURE VERIFY IS FAILED"
                    },
                    separators=(',', ':'))
            blockId = self.mongo["SHARD BLOCKCHAIN HASH LIST"].save({
                "SHARD ID":
                shardId,
                "BHEIGHT":
                bheight,
                "BLOCK HASH":
                hash
            })
            return json.dumps({
                "STATUS": "OK",
                "DESCRIPTION": str(blockId)
            },
                              separators=(',', ':'))

        @self.app.route('/r/saveMapElement', methods=['GET', 'POST'])
        def saveMapElement():
            if not request:
                abort(400)

            name = request.args.get('name')
            nsource = request.args.get('nsource')
            address = request.args.get('address')
            refresh = request.args.get('refresh')
            dtype = request.args.get('dtype')
            costway = request.args.get('costway')
            countway = request.args.get('countway')
            keyway = request.args.get('keyway')

            if costway == "":
                costway = []
            else:
                costway = costway.split(",")

            if countway == "":
                countway = []
            else:
                countway = countway.split(",")

            if keyway == "":
                keyway = []
            else:
                keyway = keyway.split(",")

            data = json.loads(self.redis.get("RATE SOURCES LIST"))["DATA"]
            data.append({
                "NAME": name,
                "REFRESH": refresh,
                "SOURCE_NAME": nsource,
                "ADDR": address,
                "DATA_TYPE": dtype,
                "COST_WAY": costway,
                "COUNT_WAY": countway,
                "WAY_TO_KEY_LIST": keyway
            })
            print(data)
            self.redis.set("RATE SOURCES LIST",
                           json.dumps({"DATA": data}, separators=(',', ':')))

            return json.dumps({"STATUS": "OK"}, separators=(',', ':'))

        @self.app.route('/r/getDataMap', methods=['GET', 'POST'])
        def getDataMap():
            if not request:
                abort(400)
            data = self.redis.get("RATE SOURCES LIST")
            if data is None:
                data = json.dumps({"DATA": "[]"})
            return data

        @self.app.route('/r/testUserName', methods=['GET', 'POST'])
        def testUserName():
            if not request:
                abort(400)
            uname = request.args.get('uname')
            data = self.redis.zscore("USER LIST", uname)
            if data is None:
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": True
                },
                                  separators=(',', ':'))
            else:
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": False
                },
                                  separators=(',', ':'))
            return data

        @self.app.route('/r/getOsStat', methods=['GET', 'POST'])
        def getOsStat():
            if not request:
                abort(400)

            cpu = psutil.cpu_percent(interval=0.1)

            memt = psutil.virtual_memory().total / (1024**3)
            memu = psutil.virtual_memory().used / (1024**3)
            memf = psutil.virtual_memory().free / (1024**3)
            memp = psutil.virtual_memory().percent

            swapt = psutil.swap_memory().total / (1024**3)
            swapu = psutil.swap_memory().used / (1024**3)
            swapf = psutil.swap_memory().free / (1024**3)
            swapp = psutil.swap_memory().percent

            data = json.dumps(
                {
                    "CPU": cpu,
                    "MEM": {
                        "TOTAL": round(memt, 2),
                        "USED": round(memu, 2),
                        "FREE": round(memf, 2),
                        "PERCENT": memp
                    },
                    "SWAP": {
                        "TOTAL": round(swapt, 2),
                        "USED": round(swapu, 2),
                        "FREE": round(swapf, 2),
                        "PERCENT": swapp
                    }
                },
                separators=(',', ':'))
            return data

        @self.app.route('/shardDsgn/createShard', methods=['POST'])
        def createShard():

            if not request:
                abort(400)

            uniqueName = str(uuid.uuid4())
            work_folder = 'shardDesigner/' + uniqueName
            node_folder = 'shardDesigner/' + uniqueName + '/shardNodeDir'
            stem_folder = 'shardDesigner/' + uniqueName + '/shardStemDir'
            binary_folder = 'shardDesigner/' + uniqueName + '/shardNodeDir'
            if not os.path.exists(work_folder):
                shutil.copytree("shardDesigner/shardTemplateDir", work_folder)

            name = request.args.get('name')
            hashType = request.args.get('hash')
            signType = request.args.get('sign')
            freq = request.args.get('freq')
            ipaddr = request.args.get('ipaddr')
            elipad = request.args.get('elipad')
            stempk = request.args.get('stempk')
            command = request.args.get('command')
            fields = request.args.get('fields')
            fieldsMas = "[\"" + fields.replace(",", "\",\"") + "\"]"

            data = ""

            file = request.files['binary']
            binaryName = secure_filename(file.filename)

            file.save(os.path.join(binary_folder, "NODE_BINARY"))

            # !!! CHANGE NODES SCRIPTS !!!

            # 1. CHANGE START NODE SCRIPTS
            command = command.replace(binaryName, "NODE_BINARY")
            print("CHANGE FILE:", "NODE BINARY")

            # 2. CHANGE MRKL SCRIPT
            way = binary_folder + "/crypto/mrkl.py"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%HASH_TYPE%>", hashType)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND MRKL SCRIPT"
                    },
                    separators=(',', ':'))
                return data

            # 3. CHANGE NOOCRYPTO SCRIPT
            way = binary_folder + "/crypto/nooCrypto.py"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%SIGN_TYPE%>", signType)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND NOOCRYPTO SCRIPT"
                    },
                    separators=(',', ':'))
                return data

            # 4. CHANGE SLAVE NODE SCRIPT
            way = binary_folder + "/slaveNode.py"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace(
                    "<%FIELDS%>",
                    fieldsMas).replace("<%STEMIP%>",
                                       ipaddr).replace("<%STEMPK%>", stempk)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND SLAVE NODE SCRIPT"
                    },
                    separators=(',', ':'))
                return data

            # 5. CHANGE SLAVE NODE SCRIPT
            way = binary_folder + "/static/index.html"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%SHARD NAME%>", name)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND INDEX PAGE"
                    },
                    separators=(',', ':'))
                return data

            # 6. CHANGE SLAVE NODE SCRIPT
            way = binary_folder + "/starterFlask.py"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%START BINARY COMMAND%>",
                                                    command)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND INDEX PAGE"
                    },
                    separators=(',', ':'))
                return data

            # !!! CHANGE STEM SCRIPTS !!!

            # 5. CHANGE STEM NODE SCRIPT
            way = stem_folder + "/static/index.html"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%SHARD NAME%>",
                                                    name + "(STEM)")
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND INDEX PAGE"
                    },
                    separators=(',', ':'))
                return data

            # 6. CHANGE STEM NODE SCRIPT ELASTIC
            way = stem_folder + "/log/elast.py"
            print("CHANGE FILE:", way)
            if os.path.exists(way):
                fnode = open(way, "r")
                internalText = fnode.read()
                fnode.close()

                fnode = open(way, "w")
                internalText = internalText.replace("<%ELASTICIP%>", elipad)
                fnode.write(internalText)
                fnode.close()
            else:
                data = json.dumps(
                    {
                        "STATUS": False,
                        "DESCR": "INTERNAL ERROR, NOT FOUND INDEX PAGE"
                    },
                    separators=(',', ':'))
                return data

            # PY COMPILE
            #py_compile.compile(node_folder + "/slaveNode.py", cfile=node_folder + "/nodeApp.pyx")
            #py_compile.compile(node_folder + "/starterFlask.py", cfile=node_folder + "/starterApp.pyx")

            print("START ZIP!")

            # ZIP AND SEND FILES!
            zipfNode = zipfile.ZipFile(work_folder + '/nodeApp.zip', 'w',
                                       zipfile.ZIP_DEFLATED)
            FlaskWorker.zipDir(node_folder, zipfNode)
            zipfNode.close()
            print("NEXT ZIP!")
            zipfStem = zipfile.ZipFile(work_folder + '/stemApp.zip', 'w',
                                       zipfile.ZIP_DEFLATED)
            FlaskWorker.zipDir(node_folder, zipfStem)
            zipfStem.close()
            # ZIP AND SEND FILES!
            print("END ZIP!")

            # REGISTRY NEW SHARD IN ROOT MONGO DATABASE
            print("REGISTRY NEW SHARD IN ROOT MONGO DATABASE")
            shardId = self.mongo["SHARD LIST"].save({
                "NAME": name,
                "OWNER": stempk,
                "INFO": "",
                "SIGN": "",
                "STEMIP": ipaddr
            })
            # REGISTRY NEW SHARD IN ROOT MONGO DATABASE

            data = json.dumps(
                {
                    "STATUS": True,
                    "RESULT": uniqueName,
                    "SHARDID": shardId
                },
                separators=(',', ':'))

            return data

        @self.app.route('/r/newUser', methods=['GET', 'POST'])
        def newUser():
            if not request:
                abort(400)
            fname = request.args.get('fname')
            lname = request.args.get('lname')
            uname = request.args.get('uname')
            email = request.args.get('email')
            address = request.args.get('address')
            address2 = request.args.get('address2')

            if fname == "":
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": "FNAME not valid"
                },
                                  separators=(',', ':'))
                return data

            if lname == "":
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": "LNAME not valid"
                },
                                  separators=(',', ':'))
                return data

            if uname == "":
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": "UNAME not valid"
                },
                                  separators=(',', ':'))
                return data

            if email == "":
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": "EMAIL not valid"
                },
                                  separators=(',', ':'))
                return data

            if address == "":
                data = json.dumps(
                    {
                        "STATUS": True,
                        "RESULT": "ADDRESS not valid"
                    },
                    separators=(',', ':'))
                return data

            list = self.redis.get("USER:"******"USER:"******"fname": fname,
                            "lname": lname,
                            "uname": uname,
                            "email": email,
                            "address": address,
                            "address2": address2
                        },
                        separators=(',', ':')))
            else:
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": "UNAME is USED"
                },
                                  separators=(',', ':'))
                return data

            if data is None:
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": True
                },
                                  separators=(',', ':'))
            else:
                data = json.dumps({
                    "STATUS": True,
                    "RESULT": False
                },
                                  separators=(',', ':'))
            return data

        @self.app.route('/getNodeAppZip')
        def send_nodeAppZip():
            uuid = request.args.get('uuid')
            return send_from_directory("shardDesigner/" + uuid, "nodeApp.zip")

        @self.app.route('/getStemAppZip')
        def send_stemAppZip():
            uuid = request.args.get('uuid')
            return send_from_directory("shardDesigner/" + uuid, "stemApp.zip")

    @staticmethod
    def zipDir(path, ziph):
        for root, dirs, files in os.walk(path):
            for file in files:
                ziph.write(os.path.join(root, file))

    def run(self):
        self.app.run(host='0.0.0.0', port=5005)