Exemple #1
0
    def getAllKeys(self, params):
        wal = 'unidentified'
        try:
            wal = params['wallet']
            pattern = re.compile(regexWallet)
            if not pattern.match(wal):
                return errMsg("Invalid wallet name.")

            cmd = "SELECT"
            sel = False
            if "py" in params['sel']:
                cmd = cmd + " 'pubkey:' || pubKey,"
                sel = True

            if "ay" in params['sel']:
                cmd = cmd + " 'addr:' || address,"
                sel = True

            if "ny" in params['sel']:
                cmd = cmd + " 'name:' || KName"
                sel = True

            if sel is False:
                cmd = cmd + " pubKey, address, KName"
            else:
                if cmd.endswith(","):
                    cmd = cmd[0:-1]

            cmd = cmd + " FROM Wallet WHERE WName='" + wal + "'"
            return setOK({"keyList": self.doSelect(cmd)})

        except Exception:
            return errMsg("Collecting keys for wallet " + wal + " failed.")
Exemple #2
0
    def createKeys(self, data):
        wal = data['name']
        if not self.hasWallet(wal):
            return errMsg("Wallet '" + wal + "' not found.")
        cmd = "SELECT DISTINCT KName from Wallet WHERE User='******'user'] + "' AND WName='" + wal + "' AND ("
        knames = ""
        pattern = re.compile(regexWallet)
        for idx in range(0, data['numKeys']):
            if len(data['keyNames']) > idx:
                if len(knames) > 0:
                    knames = knames + " OR "
                if not pattern.match(data['keyNames'][idx]):
                    return errMsg(
                        "Invalid key name, use a-z, aA-Z and numbers only.")
                knames = knames + "KName='" + data['keyNames'][idx] + "'"
        if len(knames) > 0:
            cmd = cmd + knames + ")"
            rpl = self.doSelect(cmd)
            if len(rpl) > 0:
                cmd = "Duplicate name(s):"
                for nam in rpl:
                    cmd = cmd + nam + ","
                return errMsg(cmd + " no key(s) generated")

        return self.addKeysToWallet(data, wal)
Exemple #3
0
 def getKeyBalance(self, params):
     keys = self.getDataFor([params['sel'], params['key']],
                            params['wallet'], "", params['user'])
     if len(keys) > 4:
         respText, respCode = self.collectKeyBalance(keys[4])
         if respCode == 200:
             return setOK(respText)
         else:
             return errMsg(respText['errorMsg'], respCode)
     return errMsg("Invalid parameters provided")
Exemple #4
0
    def getTXForHash(self, hash):
        if (len(hash) != len(defHash)):
            return errMsg("Invalid Hash Len")
        response = self.getPendTXByHash(hash)
        # if a given hash is found already, no other exists, else keep searching
        if (len(hash) == 0) or (len(response) == 0):
            response.extend(self.getConfirmedTXByHash(hash))
        if (len(response) > 0):
            return setOK(response)

        return errMsg("No transactions found for: " + hash, 404)
Exemple #5
0
    def setID(self, data):
        if m_data['chainRef'] != "":
            return errMsg("Current chainRef set: " + m_data['chainRef'])

        if project.classes.c_walletInterface.hasWallet(
                'genesis' + data['chainRef']) is True:
            return errMsg("Wallet reference already exists")

        m_data.clear()
        m_data.update(deepcopy(m_dataInit))
        m_data['chainRef'] = data['chainRef']
        return setOK("chain ID set to: " + data['chainRef'])
Exemple #6
0
    def getMinerCandidate(self, minerAddress):
        #TODO share same block for different miner later on to save memory
        if m_cfg['chainLoaded'] is False:
            sleep(1)
            return errMsg("No chain loaded yet, retry ....")
        err = verifyAddr(minerAddress)
        if len(err) > 0:
            return errMsg(err)
        if minerAddress in m_BufferMinerCandidates:
            cand = m_BufferMinerCandidates[minerAddress]['mineCandidate']
            if cand['index'] == m_candidateBlock['index']:
                if m_BufferMinerCandidates[minerAddress]['minerBlock']['blockDataHash'] == m_candidateBlock['blockDataHash']:
                    return setOK(cand)  # if nothing has changed, return same block
        # as candidate blocks change with every new TX and different miners might deal
        # with different blocks, we must keep the miner specific block in case a miner succeeds
        #if 'prevBlockHash' not in m_candidateBlock:
        self.c_blockchainHandler.prepareNewCandidateBlock()
        minerSpecificBlock = deepcopy(m_candidateBlock)
        # TODO need house-keeping if miners disappear and don't come back,
        # else we get a queue overflow attack by fake miners
        candidateMiner = deepcopy(m_candidateMiner)
        candidateMiner['rewardAddress'] = minerAddress
        minerSpecificBlock['minedBy'] = minerAddress
        fees = minBlockReward
        bindex = len(m_Blocks)
        for tx in m_candidateBlock['transactions']:
            if len(tx) > 0:    #otherwise it is empty coinbase
                fees = fees + tx['fee']
            else:
                if fees != minBlockReward:
                    return errMsg("Invalid minimum CoinBase fee TX in block", 404)
        coinBase = deepcopy(m_coinBase)
        candidateMiner['index'] = bindex
        coinBase['minedInBlockIndex'] = bindex
        minerSpecificBlock['index'] = candidateMiner['index']
        candidateMiner['expectedReward'] = fees
        coinBase['value'] = fees
        coinBase['to'] = minerAddress
        coinBase['dateCreated'] = getTime()
        coinBase['transactionDataHash'] = sha256ToHex(m_transaction_order, coinBase)
        minerSpecificBlock['transactions'].insert(0, coinBase)
        candidateMiner['transactionsIncluded'] = len(minerSpecificBlock['transactions']) #inlcudes coinbase

        # now the block is done, hash it for miner
        # need to calculate now the hash for this specific miner based candidateBlock
        # the hash for the miner has to be in specific order of data
        candidateMiner['blockDataHash'] = makeBlockDataHash(m_candidateBlock, False)
        print("Generate new candidate for miner: " + minerAddress + " with Hash: " + candidateMiner['blockDataHash'] + " reward: " + str(fees))
        m_BufferMinerCandidates[minerAddress] = {}
        m_BufferMinerCandidates[minerAddress]['mineCandidate'] = deepcopy(candidateMiner)
        m_BufferMinerCandidates[minerAddress]['minerBlock'] = minerSpecificBlock
        return setOK(candidateMiner)
Exemple #7
0
 def updGX(self, data):
     if m_data['chainRef'] == "":
         return errMsg("Missing chainRef ")
     if data['chainRef'] != m_data['chainRef']:
         return errMsg("Current chainRef not matching: " +
                       m_data['chainRef'])
     for jtx in data['TXList']:
         if jtx['chainRef'] != m_data['chainRef']:
             return errMsg("One of the TX has invalid chainRef: " +
                           jtx['chainRef'])
     m_data.clear()
     m_data.update(data)
     return setOK("Data updated without major verifications")
Exemple #8
0
 def getAllBalance(self, params):
     try:
         user = params['user']
         bal = deepcopy(m_balanceData)
         for key in self.doSelect(
                 "SELECT DISTINCT address FROM Wallet WHERE User='******'"):
             val, respCode = self.collectKeyBalance(key)
             if respCode == 200:
                 self.sumBalance(bal, val)
             else:
                 return errMsg(val, respCode)
         return setOK(bal)
     except Exception:
         return errMsg("Seems to have peer issues....")
Exemple #9
0
def genesis_POST():
    linkInfo = {}
    try:
        values = request.get_json()
    except Exception:
        return errMsg("JSON not decodeable")
    return c_MainIntf.nodeSpecificPOST(request.path, linkInfo, values, request)
Exemple #10
0
    def loadSys(self,sysIn):
        self.c_blockchainHandler.clearChainLoadGenesis()
        myUrl = m_info['nodeUrl']
        myNodeID = m_info['nodeId']
        m_info.clear()
        m_info.update(sysIn['m_info'])
        m_info["nodeUrl"] = myUrl
        m_info["nodeId"] = myNodeID
        m_cfg.clear()
        m_cfg.update(sysIn['m_cfg'])
        m_peerInfo.clear()
        m_peerInfo.update(sysIn['m_peerInfo'])
        m_Blocks.clear()
        for block in sysIn['m_Blocks']:
            if (len(m_Blocks) == 0):
                # TODO verify all fields are the same not only there!!!
                m, l, f = checkRequiredFields(block, m_genesisSet[0], [], False)
                if (len(m) == 0):
                    # TODO revert if loading failed!?!?!
                    m_Blocks.append(block)
                    continue
            else:
                ret = self.c_blockchainHandler.verifyThenAddBlock(block)
                if (len(ret) > 0):
                    # TODO revert if loading failed!?!?!
                    return errMsg(ret)

        m_pendingTX.update(sysIn['m_pendingTX'])
        m_BufferMinerCandidates.update(sysIn['m_BufferMinerCandidates'])
        m_stats.update(sysIn['m_stats'])
Exemple #11
0
def mining_submitBlock():
    linkInfo = {}
    try:
        values = request.get_json()
    except Exception:
        return errMsg("JSON not decodable")
    return c_MainIntf.nodeSpecificPOST(request.path, linkInfo, values, request)
Exemple #12
0
def peers_connect():
    try:
        values = request.get_json()
        pt = request.path
        return c_peer.peersConnect(request.host, values, "dis" not in pt)
    except Exception:
        return errMsg("JSON not decodeable")
Exemple #13
0
    def nodeSpecificPOSTNow(self, url, linkInfo, json, request):
        # linkInfo is a json object containing the information from the URL

        if url == "/genFaucet":
            return c_genesisInterface.genFaucet(json)
        elif url == "/useTX":
            return c_genesisInterface.useTX(json)
        elif url == "/genTX":
            return c_genesisInterface.genTX(json)
        elif url == "/genGX":
            return c_genesisInterface.genGX(json)
        elif url == "/updGX":
            return c_genesisInterface.updGX(json)
        elif url == "/viewGX":
            return c_genesisInterface.viewGX(json)
        elif url == "/setID":
            return c_genesisInterface.setID(json)


        #json contains the json object submitted during the POST
        response = {
            'NodeType': m_info['type'],
            'info': "This API is not (yet) implemented...."
        }
        ## put your logic here and create the reply as next line
        return errMsg(response)
Exemple #14
0
 def nodeSpecificPOSTNow(self, url, linkInfo, json, request):
     if url == "/wallet/transfer":
         mes = c_faucetInterface.checkLimit(json)
         if len(mes) > 0:
             return errMsg(mes)
     return wall.walletInterface.nodeSpecificPOSTNow(
         self, url, linkInfo, json, request)
Exemple #15
0
 def handleChainBackTracking(self, peer):
     try:
         ret = self.handleBackTracking(peer)
     except Exception:
         d("Major issue in backtracking, stopped back tracking")
         ret = errMsg("Exception raised, invalid peer claim")
     m_cfg['checkingChain'] = False
     return ret
Exemple #16
0
 def genTX(self, data):
     ret = self.checkTX(data)
     if len(ret) > 0:
         return errMsg(ret)
     m_data['TXList'].append(data)
     return setOK(
         str(len(m_data['TXList'])) +
         " TXs registered. Most recent type: creating TX")
Exemple #17
0
def receivedNewTransaction(trans, share):
    # Checks for missing / invalid fields / invalid field values
    colErr = verifyBasicTX(
        trans, False, m_transaction)  # such can never be coinbase, so False!

    if colErr == "":
        trx = deepcopy(trans)
        passOn = deepcopy(trans)
        del trx["senderSignature"]  # this must be excluded from the hash
        hash = sha256ToHex(m_transaction_order, trx)

        #TODO Validates the transaction public key, validates the signature
        trans["transactionDataHash"] = hash

        # Checks for collisions -> duplicated transactions are skipped
        if hash in m_pendingTX:
            return errMsg("TX is duplicate of in pending TX")

        if isUniqueTXInBlocks(hash) is False:
            return errMsg("TX is duplicate of TX in existing block")
        if ('transferSuccessful'
                not in trans) or (trans['transferSuccessful'] is True):
            tmpBal = getBalance(trans['from'])
            if tmpBal['confirmedBalance'] + tmpBal['pendingBalance'] < trans[
                    'value'] + trans['fee']:
                return errMsg("Not enough balance")

        # Puts the transaction in the "pending transactions" pool
        m_pendingTX.update({trans['transactionDataHash']: deepcopy(trans)})
        if "transferSuccessful" not in trans:
            trans["transferSuccessful"] = True
        trans["minedInBlockIndex"] = len(m_Blocks)
        m_candidateBlock['transactions'].append(deepcopy(trans))
        m_info['pendingTransactions'] = len(m_pendingTX)
        response = {"transactionDataHash": hash}

        m_BufferMinerCandidates.clear()
        if share is True:
            # Sends the transaction to all peer nodes through the REST API
            # It goes from peer to peer until it reaches the entire network
            #TODO do we still need this 'fromPeer'?
            c_peer.sendAsynchPOSTToPeers("/transactions/send", passOn)
            return setOK(response, 201)  #201 as per slide 38
        return  # nothing returned, nothing sent
    return errMsg(colErr)
Exemple #18
0
 def getBlockHash(self, params):
     try:
         hfrom = +params['from']
         hto = +params['to']
         hlength = +params['cnt']
         if (hfrom < 0) or (hfrom >= len(m_Blocks)) or (hto < hfrom) or \
                 (hlength < 0) or (hlength > len(defHash)):
             return errMsg("Inconsistent request")
         repl = []
         if hlength == 0:
             hlength = len(defHash)
         for x in range(hfrom, hto+1):
             if x >= len(m_Blocks):
                 break
             repl.append([x, m_Blocks[x]['blockHash'][0:hlength]])
         return setOK(repl)
     except Exception:
         return errMsg("Invalid parameters")
Exemple #19
0
    def getAllKeys(self, params):
        wal = 'unidentified'
        try:
            wal = params['wallet']
            pattern = re.compile(regexWallet)
            if not pattern.match(wal):
                return errMsg("Invalid wallet name.")

            cmd = "SELECT"
            sel = False
            if "py" in params['sel']:
                cmd = cmd + " 'pubkey:' || pubKey,"
                sel = True

            if "ay" in params['sel']:
                cmd = cmd + " 'addr:' || address,"
                sel = True

            if "ny" in params['sel']:
                cmd = cmd + " 'name:' || KName"
                sel = True

            if sel is False:
                cmd = cmd + " pubKey, address, KName"
            else:
                if cmd.endswith(","):
                    cmd = cmd[0:-1]

            cmd = cmd + " FROM Wallet WHERE WName='" + wal + "'"
            ret = project.classes.c_walletInterface.doSelect(cmd)
            repl = []
            for k in ret:
                if k.startswith("addr"):
                    repl.append(k)
                else:
                    if k[-1] == "#":
                        repl.append(k + "no")
                    else:
                        repl.append(k[0:k.rindex("#")] + "#yes")

            return setOK({"keyList": repl})

        except Exception:
            return errMsg("Collecting keys for wallet " + wal + " failed.")
Exemple #20
0
    def receivedBlockNotificationFromPeer(self, blockInfo):
        #TODO do we want to check if NodeUrl and real sender are identical??
        try:
            m, l, f = checkRequiredFields(blockInfo, m_informsPeerNewBlock, [], False)
            if (len(m) == 0) and (l == 0):
                return self.checkChainSituation('notification', blockInfo)
        except Exception:
            i=0

        return errMsg("Invalid block structure")
Exemple #21
0
def visualRelease(idx):
    try:
        found = False
        rel = {}
        for item in m_Delay:
            if ('releaseID' in item) and (item['releaseID'] == idx):
                rel = item
                found = True
                break
        if found is True:
            m_Delay.remove(rel)
            if rel['asynchPOST'] is True:
                requests.post(url=rel['url'],
                              json=rel['json'],
                              headers={'accept': 'application/json'})
            return setOK(rel)
        return errMsg("Unexpected Release for " + str(id))
    except Exception:
        print("visualRelease Failed")
    return errMsg("Request failed")
Exemple #22
0
 def getAllTX(self, params):
     try:
         user = params['user']
         typep = int(params['type'])
         return self.filterTX(
             typep,
             self.doSelect(
                 "SELECT address, KName, pubKey FROM Wallet WHERE User='******'"))
     except Exception:
         return errMsg("Seems to have peer issues....")
Exemple #23
0
    def peersConnect(self, source, values, isConnect):
        m, l, f = checkRequiredFields(['peerUrl'], values, [], False)
        if len(m) > 0:
            return errMsg("Missing field 'peerUrl' ")
        url = values['peerUrl']
        newURL = getValidURL(url, True)
        if newURL == "":
            return errMsg("Invalid URL: " + url)

        if isConnect:
            err = self.addPeerOption(url, source)
            if len(err) == 0:
                return setOK("Connection to peer registered")
            if err.startswith("Already connected"):
                return errMsg("Already connected to peer: " + url, 409)
        else:
            err = self.removePeerOption(url)
            if len(err) == 0:
                return setOK("Connection to peer removed")

        return errMsg(err)
Exemple #24
0
    def getTXForAddress(self, address):
        #TODO move to models
        reply = {"address": "undefined", "transactions": []}
        if (len(address) != len(defAdr)):
            errMsg("Inavlid Address Len")
        response = self.getPendTXByAddress(
            address
        )  #order not clearly defined in slide29, pending more important
        # if a given hash is found already, no other exists, else keep searching
        #there is no pending, so return all
        # if (len(hash) == 0) or (len(response) == 0):
        response.extend(self.getConfirmedTXByAddress(address))

        if (len(response) > 0):
            reply['address'] = address
            #we must sort the list by date time in ascending order
            reply['transactions'] = sorted(response,
                                           key=lambda k: k['dateCreated'])
            return setOK(reply)

        return errMsg("No transactions found for: " + address, 404)
Exemple #25
0
def visualCfg():
    try:
        values = request.get_json()
        if values['active'] is True:
            pattern = re.compile(values['pattern'])
            m_visualCFG['active'] = True
            m_visualCFG['pattern'] = pattern
            return setOK(values)
        m_visualCFG['active'] = False
        m_Delay.clear()
        return setOK("Tracking switched off")
    except Exception:
        return errMsg("JSON not decodeable or missing item")
Exemple #26
0
    def nodeSpecificGET(self, url, linkInfo):
        ret = {
            'NodeType': m_info['type'],
            'info': "This URL/API is not available/broken"
        }
        try:
            if self.permittedURLGET(url) is False:
                return errMsg("This URL/API is invalid or not available. " +
                              url)
            if "chainInit" not in m_cfg:
                m_cfg['chainInit'] = False  # backward compatible
            maxWait = 12
            while (len(m_isPOST) > 0) or (m_cfg['chainInit'] is True):
                if url == "/info":  # this is needed for peers to cross reference each other
                    break
                if url.startswith(
                        "/blockBalances"
                ):  # this is needed for peers to cross reference each other
                    break
                if self.delay(url, 1) is False:
                    break  # for some reason we decide to ignore the lock
                maxWait = maxWait - 1
                if maxWait < 0:
                    print(
                        "Console maxwait for chain update reached, just go ahead now ...."
                    )
                    break

            m_simpleLock.append(url)
            if isBCNode():
                ret = self.c_blockInterface.nodeSpecificGETNow(url, linkInfo)
            elif isWallet():
                ret = self.c_walletInterface.nodeSpecificGETNow(url, linkInfo)
            elif isFaucet():
                ret = self.c_faucetInterface.nodeSpecificGETNow(url, linkInfo)
            elif isGenesis():
                ret = self.c_genesisInterface.nodeSpecificGETNow(url, linkInfo)
        except Exception:
            d("*********************************************")
            d("*********************************************")
            print("GET exception caught, isPoststack " + str(len(m_isPOST)))
            d("*********************************************")
            d("*********************************************")

        if url in m_simpleLock:
            m_simpleLock.remove(
                url
            )  # maybe need to check for being there, then need to add random to URL
        return ret
Exemple #27
0
    def nodeSpecificGETNow(self, url, linkInfo):
        urlID = url[1:5]
        if url == "/viewGX":
            return c_genesisInterface.viewGX()

            #return send()
        # identify your url and then proceed
        #linkInfo is a json object containing the information from the URL
        response = {
            'NodeType': m_info['type'],
            'info': "This API is not yet implemented....",
            'requestedUrl': url,
            'linkInfo': linkInfo
        }
        ## put your logic here and create the reply as next line
        return errMsg(response)
Exemple #28
0
 def getWalletBalance(self, params):
     try:
         wal = params['wallet']
         user = params['user']
         bal = deepcopy(m_balanceData)
         for key in self.doSelect(
                 "SELECT address FROM Wallet WHERE WName='" + wal +
                 "' AND User='******'"):
             val, respCode = self.collectKeyBalance(key)
             if respCode == 200:
                 self.sumBalance(bal, val)
         w_cfg["lastBal"] = "" + str(bal['confirmedBalance']) + "/ " + str(
             bal['pendingBalance'])
         return setOK(bal)
     except Exception:
         return errMsg("Seems to have peer issues....")
Exemple #29
0
    def nodeSpecificGETNow(self, url, linkInfo):
        urlID = url[1:5]
        #if (urlID == 'send'):
        #    return send()
        if urlID == 'info':
            infow = {
                'about': m_info['about'],
                'database': m_db['DATABASE'],
                'chainID': m_info['chainId'],
                'nodeUrl': m_info['nodeUrl'],
                'nodeId': m_info['nodeId']
            }
            return setOK(infow)

        if urlID == 'wall':
            if url.startswith("/wallet/list/wallet"):
                return c_walletInterface.getAllWallets(linkInfo['user'])
            elif url.startswith("/wallet/list/keys/s"):
                return c_walletInterface.getAllKeys(linkInfo)
            elif url.startswith("/wallet/list/balance"):
                return c_walletInterface.getKeyBalance(linkInfo)
            elif url.startswith("/wallet/list/allbalances"):
                return c_walletInterface.getAllBalance(linkInfo)
            elif url.startswith("/wallet/list/allbalance"):
                return c_walletInterface.getWalletBalance(linkInfo)
            elif url.startswith("/wallet/list/allkeybalance"):
                return c_walletInterface.getWalletKeyBalance(linkInfo)
            elif url.startswith("/wallet/list/allTXs/"):
                return c_walletInterface.getAllTX(linkInfo)
            elif url.startswith("/wallet/list/allTX/"):
                return c_walletInterface.getWalletTX(linkInfo)

        if urlID == 'addr':
            return setOK(linkInfo)

            #return send()
        # identify your url and then proceed
        #linkInfo is a json object containing the information from the URL
        response = {
            'NodeType': m_info['type'],
            'info': "This API is not yet implemented....",
            'requestedUrl': url,
            'linkInfo': linkInfo
        }
        ## put your logic here and create the reply as next line
        return errMsg(response)
Exemple #30
0
 def getWalletKeyBalance(self, params):
     try:
         wal = params['wallet']
         user = params['user']
         bal = {}
         for addr in self.doSelect(
                 "SELECT address FROM Wallet WHERE WName='" + wal +
                 "' AND User='******'"):
             val, respCode = self.collectKeyBalance(addr)
             if respCode == 200:
                 bal2 = deepcopy(m_balanceData)
                 bal2['confirmedBalance'] = val['confirmedBalance']
                 bal2['pendingBalance'] = val['pendingBalance']
                 bal[addr] = bal2
         return setOK(bal)
     except Exception:
         return errMsg("Seems to have peer issues....")