Beispiel #1
0
    def getNetworkLatestInfo(self) -> NetworkInfo:
        url = Globals.getHmyNetworkUrl()
        block_number = 0
        try:
            block_number = blockchain.get_block_number(url)
            #print(f"Block Number {block_number}")
        except Exception as ex:
            HmyBidderLog.error(
                f'Validator getNetworkLatestInfo get_block_number {ex}')

        try:
            response = staking.get_staking_network_info(url)
            #print(response)
            if response != None and not 'error' in response:
                epoch_last_block = int(response['epoch-last-block'])
                median_raw_stake = float(response['median-raw-stake']
                                         ) / Globals._oneAmountDenominator
                blocks_to_next_epoch = (epoch_last_block - block_number)
                network_info = NetworkInfo(epoch_last_block, median_raw_stake,
                                           block_number, blocks_to_next_epoch)
                return network_info
            else:
                return None
        except Exception as ex:
            HmyBidderLog.error(
                f'Validator getNetworkLatestInfo get network info {ex}')
Beispiel #2
0
 def getValidatorInfo(self, validatorAddress):
     validator_info = None
     try:
         jsonResponse = staking.get_validator_information(
             validatorAddress, Globals.getHmyNetworkUrl())
         #print(jsonResponse)
         activeStatus = ''
         if 'active-status' in jsonResponse:
             activeStatus = jsonResponse['active-status']
         eposStatus = ''
         if 'epos-status' in jsonResponse:
             eposStatus = jsonResponse['epos-status']
         totalDelegation = 0
         if 'total-delegation' in jsonResponse:
             totalDelegation = float(jsonResponse['total-delegation'])
         blsKeys = []
         if 'validator' in jsonResponse:
             if jsonResponse['validator'] != None:
                 if 'bls-public-keys' in jsonResponse['validator']:
                     for bKey in jsonResponse['validator'][
                             'bls-public-keys']:
                         sId = HmyClient.getShardForBlsKey(bKey)
                         blsKeys.append(BlsKey(bKey, sId))
         validator_info = ValidatorInfo(activeStatus, eposStatus,
                                        totalDelegation, blsKeys)
     except Exception as ex:
         HmyBidderLog.error(f'Validator getValidatorInfo {ex}')
     finally:
         return validator_info
Beispiel #3
0
 def validateONEAddress(self, oneAddress):
     valid = False
     try:
         valid = account.is_valid_address(oneAddress)
     except Exception as ex:
         HmyBidderLog.error(f'Validator validateONEAddress {ex}')
     finally:
         return valid
Beispiel #4
0
 def getCurrentEpoch(self) -> int:
     url = Globals.getHmyNetworkUrl()
     epoch_number = 0
     try:
         epoch_number = blockchain.get_current_epoch(url)
         #print(f"Block Number {block_number}")
     except Exception as ex:
         HmyBidderLog.error(
             f'Validator getCurrentEpoch get_block_number {ex}')
     finally:
         return epoch_number
Beispiel #5
0
 def getShardForBlsKey(self, key):
     shard = -1
     try:
         nodeUrl = Globals.getHmyNetworkUrl()
         response = HmyClient.__executeCommand(
             ['./hmy', '--node', nodeUrl, 'utility', 'shard-for-bls', key])
         shard = response['shard-id']
         return shard
     except Exception as ex:
         HmyBidderLog.error(f'HmyClient getShardForBlsKey {ex}')
         return shard
Beispiel #6
0
 def getMedianRawStakeSnapshot(self) -> NetworkInfo:
     url = Globals.getHmyNetworkUrl()
     median_raw_stake_snapshot = {}
     try:
         median_raw_stake_snapshot = staking.get_raw_median_stake_snapshot(
             url)
         #print(median_raw_stake_snapshot)
         if median_raw_stake_snapshot != None and not 'error' in median_raw_stake_snapshot:
             return median_raw_stake_snapshot
         else:
             return None
     except Exception as ex:
         HmyBidderLog.error(f'Validator getMedianRawStakeSnapshot {ex}')
Beispiel #7
0
 def getTotalStakedToValidator(self, validatorAddress):
     validator_info = {}
     totalDelegation = 0
     try:
         validator_info = staking.get_validator_information(
             validatorAddress, Globals.getHmyNetworkUrl())
         #print(validator_info)
         if 'total-delegation' in validator_info:
             totalDelegation = validator_info['total-delegation']
     except Exception as ex:
         HmyBidderLog.error(f'Validator getTotalStakedToValidator {ex}')
     finally:
         return (totalDelegation / Globals._oneAmountDenominator)
Beispiel #8
0
 def addBlsKey(self, bls_key):
     success = False
     try:
         response = HmyClient.__executeCommand(
             self.__getParameters(bls_key) + ["--add-bls-key", bls_key])
         #print(response)
         if 'result' in response:
             if 'transactionHash' in response['result']:
                 success = True
         return success
     except Exception as ex:
         HmyBidderLog.error(f'HmyClient addBlskey {ex}')
         return success
Beispiel #9
0
 def checkIfAccountofWalletAddressExists(self, walletAddress):
     exists = False
     try:
         nodeUrl = Globals.getHmyNetworkUrl()
         response = HmyClient.__executeCommand(
             ['./hmy', '--node', nodeUrl, 'keys', 'list'])
         print(response)
         if walletAddress in json.dumps(response):
             exists = True
         return exists
     except Exception as ex:
         if walletAddress in str(ex):
             return True
         else:
             HmyBidderLog.error(
                 f'HmyClient checkIfAccountofWalletAddressExists {ex}')
             return exists
Beispiel #10
0
def validateShardKey(shardKeys):
    valid = False
    parts = shardKeys.split(":")
    if len(parts) == 8:
        try:
            Globals._shardsKeys = {}
            for shardId in range(0, Globals._numberOfShards):
                shardKey = f'shard{shardId}'
                Globals._shardsKeys[shardKey] = []
            for f in listdir(Globals._blsdirPath):
                if isfile(join(Globals._blsdirPath, f)):
                    if f.endswith(".key"):
                        blsKey = f.replace(".key", "")
                        shard = int(HmyClient.getShardForBlsKey(blsKey))
                        if shard != -1:
                            if shard == 0:
                                if not blsKey in Globals._shardsKeys['shard0']:
                                    Globals._shardsKeys['shard0'].append(blsKey)
                            elif shard == 1:
                                if not blsKey in Globals._shardsKeys['shard1']:
                                    Globals._shardsKeys['shard1'].append(blsKey)
                            elif shard == 2:
                                if not blsKey in Globals._shardsKeys['shard2']:
                                    Globals._shardsKeys['shard2'].append(blsKey)
                            elif shard == 3:
                                if not blsKey in Globals._shardsKeys['shard3']:
                                    Globals._shardsKeys['shard3'].append(blsKey)
                        else:
                            HmyBidderLog.error(f" Error while getting the Shard for BLS Key {blsKey}")
            #print(f'{len(Globals._shardsKeys["shard0"])} - {len(Globals._shardsKeys["shard1"])} - {len(Globals._shardsKeys["shard2"])} - {len(Globals._shardsKeys["shard3"])}')
            if int(parts[1]) <= len(Globals._shardsKeys['shard0']) and int(parts[3]) <= len(Globals._shardsKeys['shard1']) and int(parts[5]) <= len(Globals._shardsKeys['shard2']) and int(parts[7]) <= len(Globals._shardsKeys['shard3']):
                valid = True
            else:
                valid = False
        except Exception as ex:
            HmyBidderLog.error(f'Hmybidder validateShardKey {ex}')
            valid = False
        finally:
            return valid        
Beispiel #11
0
def main():

    network_info = Validator.getNetworkLatestInfo()
    if network_info != None:
        dict_network_info = network_info.to_dict()
        curretEpoch = Validator.getCurrentEpoch() # Dont run the bidding process if it is been run for current epoch
        info_dict = {
            'total_delegated' : f'{Validator.getTotalStakedToValidator(Globals._walletAddress)}',
            'median_raw_stake' : dict_network_info['median_raw_staking'],
            'leverage' : Globals._leverage,
            'block_range' : f'{Globals._upperBlock}:{Globals._lowerBlock}',
            'epoch_last_block' : dict_network_info['epoch_last_block'],
            'block_number' : dict_network_info['block_number'],
            'blocks_to_next_epoch' : dict_network_info['blocks_to_next_epoch']
        }
        HmyBidderLog.info(info_dict)
        if network_info.blocks_to_next_epoch in range(Globals._lowerBlock, Globals._upperBlock) and curretEpoch != Globals._currentEpoch: # checking extra 5 block to make sure not missing the bidding process
        #if True:
            HmyBidderLog.info('Started Evaluating the BLS Keys')
            HMYBidder.startBiddingProcess(network_info)
            Globals._currentEpoch = Validator.getCurrentEpoch() # reset current epoch after running the bidding process
    if Globals._refreshInSeconds == None or Globals._refreshInSeconds <= 0:
        Globals._refreshInSeconds = 60
    threading.Timer(Globals._refreshInSeconds, main).start() #Keep running the process every N seconds
Beispiel #12
0
def getopts(argv):
    showHelp = False
    showVersion = False
    while argv:  
        try:
            if argv[0][0] == '-':
                if argv[0].lower() == '-c' or argv[0].lower() == '--config':
                    stopScript = False
                    Globals._configFile = argv[1]
                    if not exists(Globals._configFile):
                        stopScript = True
                        HmyBidderLog.error('Missing config file')

                    config = configparser.ConfigParser()
                    config.read(Globals._configFile)
                    if config.get('DEFAULT','Network') != None:
                        Globals._network_type = config.get('DEFAULT','Network')
                    if config.get('DEFAULT', 'LogFilePath') != None:
                        Globals._logFile = config.get('DEFAULT', 'LogFilePath')
                        HmyBidderLog.setLogFileLocation(Globals._logFile)
                    if config.get('DEFAULT', 'HMYDir') != None:
                        Globals._hmyDirectory = config.get('DEFAULT', 'HMYDir')
                    if config.get('DEFAULT', 'BLSDir') != None:
                        Globals._blsdirPath = config.get('DEFAULT', 'BLSDir')
                    if config.get('DEFAULT', 'ONEADDRESS') != None:
                        Globals._walletAddress = config.get('DEFAULT', 'ONEADDRESS')
                        if not Validator.validateONEAddress(Globals._walletAddress):
                            HmyBidderLog.error('Wallet Address is in wrong format, please verify')
                            stopScript = True
                        if not HmyClient.checkIfAccountofWalletAddressExists(Globals._walletAddress):
                            HmyBidderLog.error('Wallet Address is not in wallet accounts')
                            stopScript = True
                    if config.get('DEFAULT', 'Leverage') != None:
                        Globals._leverage = int(config.get('DEFAULT', 'Leverage'))
                    if config.get('DEFAULT', 'ShardKeys') != None:
                        Globals._allowedShardKeys = config.get('DEFAULT', 'ShardKeys')
                        parts = Globals._allowedShardKeys.split(":")
                        if len(parts) == 8:
                             totalAllowedKeys = int(parts[1]) + int(parts[3]) + int(parts[5]) + int(parts[7])
                             if (totalAllowedKeys <= 0):
                                HmyBidderLog.error("total allowd -shards.keys cannot be zero or below, please verify")
                                stopScript = True
                        else:
                            HmyBidderLog.error("-shards.keys format seems be wrong, please verify (ex: 0:1:1:3:2:0:3:1)")
                            stopScript = True
                        if not validateShardKey(Globals._allowedShardKeys):
                            HmyBidderLog.error("BLS Keys set on --shards.keys don't match the minimum number of keys available on --blsdir")
                            stopScript = True
                    if config.get('DEFAULT', 'PassphraseFile') != None:
                        Globals._passphraseFile = config.get('DEFAULT', 'PassphraseFile')
                    if config.get('DEFAULT', 'Slots') != None:
                        Globals._totalSlots = int(config.get('DEFAULT', 'Slots'))
                    if config.get('DEFAULT', 'BlockRange') != None:
                        blockRange = config.get('DEFAULT', 'BlockRange')
                        parts = blockRange.split(":")
                        if len(parts) == 2:
                            Globals._upperBlock = int(parts[0])
                            if Globals._upperBlock <= 0:
                                Globals._upperBlock = 50
                            Globals._lowerBlock = int(parts[1])
                            if Globals._lowerBlock <= 0:
                                Globals._lowerBlock = 30
                    if config.get('DEFAULT', 'RefreshInSeconds') != None:
                        Globals._refreshInSeconds = int(config.get('DEFAULT', 'RefreshInSeconds'))

                    if stopScript:
                        #HmyClient.stopSystemdService("hmybidder.service")
                        return False
                    return True
                elif argv[0].lower() == '-v' or argv[0].lower() == '--version':
                    showVersion = True                    
                elif argv[0].lower() == '-h' or argv[0].lower() == '--help':
                    showHelp = True
        except Exception as ex:
            print(f'Command line input error {ex}')
        finally:
            argv = argv[1:]
    
    if showHelp:
        with open('help.txt', 'r') as file:
            print(file.read())
            return False
    elif showVersion:
        print(f'Version {version}')
        return False
    elif Globals._walletAddress == '':
        with open('help.txt', 'r') as file:
            print(file.read())
        return False
    return True
Beispiel #13
0
    def startBiddingProcess(self, network_info):
        requiredBlsKeysCount = BiddingCalculator.calculateBlsKeysForNextEpoch(
            network_info)
        #print(f'numberOfBlsKeys - {requiredBlsKeysCount}')
        validator_info = Validator.getValidatorInfo(Globals._walletAddress)
        allowedKeysInAShard = int(
            (Globals._totalSlots / Globals._numberOfShards) * (2 / 3))
        if validator_info != None:
            currentBlsKeysCount = len(validator_info.blsKeys)
            HmyBidderLog.info(
                f'Current bls keys {currentBlsKeysCount} Ideal bls keys for next epoch {requiredBlsKeysCount}'
            )
            currentBlsKeys = {}
            for shardId in range(0, Globals._numberOfShards):
                shardKey = f'shard{shardId}'
                currentBlsKeys[shardKey] = []

            for blsKey in validator_info.blsKeys:
                if blsKey.shardId != None and blsKey.shardId >= 0:
                    currentBlsKeys[f'shard{blsKey.shardId}'].append(
                        blsKey.blskey)

            parts = Globals._allowedShardKeys.split(":")
            userAllowedKeysInShard = {
                'shard0': len(Globals._shardsKeys['shard0']),
                'shard1': len(Globals._shardsKeys['shard1']),
                'shard2': len(Globals._shardsKeys['shard2']),
                'shard3': len(Globals._shardsKeys['shard3'])
            }
            if len(parts) == 8:
                userAllowedKeysInShard = {
                    'shard0': int(parts[1]),
                    'shard1': int(parts[3]),
                    'shard2': int(parts[5]),
                    'shard3': int(parts[7])
                }
            arrKeysToAdd = []
            arrKeysToRemove = []
            HmyBidderLog.info(f'Shard Keys Config : {userAllowedKeysInShard}')
            HmyBidderLog.info(
                'Identifying the extra keys, if Shard Keys Config reduced number of keys allowed in each shard'
            )
            for shardId in range(0, Globals._numberOfShards):
                shardKey = f'shard{shardId}'
                while len(currentBlsKeys[shardKey]
                          ) > userAllowedKeysInShard[shardKey]:
                    key = currentBlsKeys[shardKey][0]
                    currentBlsKeys[shardKey].remove(key)
                    currentBlsKeysCount = currentBlsKeysCount - 1
                    arrKeysToRemove.append({'key': key, 'shard_key': shardKey})
            HmyBidderLog.info('Finished Identifying the extra keys')
            # Remove the keys if Shard Keys Config reduced number of keys allowed in each shard
            if currentBlsKeysCount < requiredBlsKeysCount:
                keysToAdd = requiredBlsKeysCount - currentBlsKeysCount
                if (keysToAdd - len(arrKeysToRemove)) > 0:
                    HmyBidderLog.info(
                        f'Started identifying bls keys to be added, {keysToAdd - len(arrKeysToRemove)} key(s) needs to be added'
                    )
                elif (keysToAdd - len(arrKeysToRemove)) < 0:
                    HmyBidderLog.info(
                        f'{keysToAdd - len(arrKeysToRemove)} key(s) needs to be removed, due to Shard Keys config change'
                    )
                try:
                    keysAdded = 0
                    for shardId in range(0, Globals._numberOfShards):
                        shardKey = f'shard{shardId}'
                        if shardKey in Globals._shardsKeys:
                            if len(currentBlsKeys[shardKey]) < len(
                                    Globals._shardsKeys[shardKey]):
                                for key in Globals._shardsKeys[shardKey]:
                                    if not key in currentBlsKeys[shardKey]:
                                        if len(
                                                currentBlsKeys[shardKey]
                                        ) < allowedKeysInAShard and len(
                                                currentBlsKeys[shardKey]
                                        ) < userAllowedKeysInShard[shardKey]:
                                            currentBlsKeys[shardKey].append(
                                                key)
                                            arrKeysToAdd.append({
                                                'key':
                                                key,
                                                'shard_key':
                                                shardKey
                                            })
                                            keysAdded = keysAdded + 1
                                        else:
                                            #HmyBidderLog.info(f'Shard {shardKey} already has allowed number of keys, keys allowed in shard {userAllowedKeysInShard[shardKey]} current number of keys in shard {len(currentBlsKeys[shardKey])}')
                                            break
                                    if keysToAdd == keysAdded:
                                        break
                        if keysToAdd == keysAdded:
                            break
                except Exception as ex:
                    HmyBidderLog.error(f'StartBidding Process Add Key {ex}')

            elif currentBlsKeysCount > requiredBlsKeysCount:
                keysToRemove = abs(requiredBlsKeysCount - currentBlsKeysCount)
                HmyBidderLog.info(
                    f'Started identifying bls keys to be removed, {keysToRemove} key(s) needs to be removed'
                )
                try:
                    keysRemoved = 0
                    for shardId in range(0, Globals._numberOfShards):
                        shardKey = f'shard{shardId}'
                        if len(currentBlsKeys[shardKey]) > 0:
                            for key in currentBlsKeys[shardKey]:
                                currentBlsKeys[shardKey].remove(key)
                                arrKeysToRemove.append({
                                    'key': key,
                                    'shard_key': shardKey
                                })
                                keysRemoved = keysRemoved + 1
                                if keysToRemove == keysRemoved:
                                    break
                        if keysToRemove == keysRemoved:
                            break
                except Exception as ex:
                    HmyBidderLog.error(f'StartBidding Process Remove Key {ex}')

            for dictKey in arrKeysToAdd:
                key = dictKey['key']
                shardKey = dictKey['shard_key']
                success = HmyClient.addBlsKey(key)
                if success:
                    HmyBidderLog.info(
                        f'blskey {key} added on Shard : {shardKey}')
                else:
                    HmyBidderLog.info(
                        f'Failed to add blskey {key} on Shard : {shardKey}')

            for dictKey in arrKeysToRemove:
                key = dictKey['key']
                shardKey = dictKey['shard_key']
                success = HmyClient.removeBlsKey(key)
                if success:
                    HmyBidderLog.info(
                        f'blskey {key} removed on Shard : {shardKey}')
                else:
                    HmyBidderLog.info(
                        f'Failed to remove blskey {key} on Shard : {shardKey}')

            logString = 'Blskeys : '
            for shardId in range(0, Globals._numberOfShards):
                shardKey = f'shard{shardId}'
                logString = f'{logString} {shardKey}[{len(currentBlsKeys[shardKey])}], '
            HmyBidderLog.info(logString)
Beispiel #14
0
 def stopSystemdService(self, serviceName):
     try:
         HmyClient.__executeCommand(['systemctl', 'stop', serviceName])
         HmyBidderLog.error(f'Stopping the {serviceName}')
     except Exception as ex:
         HmyBidderLog.error(f'HmyClient stopSystemService {ex}')