def GetTFinalSignature(self, tempo_msg, context): """Get a vote(signature) from the validator to update the t_final setting in the Aergo bridge contract """ if not self.auto_update: return Approval(error="Setting update not enabled") if tempo_msg.is_from_mainnet: current_tempo = query_tempo(self.hera2, self.oracle2, ["_sv__tFinal"]) return self.get_tempo(self.hera2, self.aergo1, self.aergo2, self.oracle2, self.id2, tempo_msg, 't_final', "F", current_tempo) else: current_tempo = query_tempo(self.hera1, self.oracle1, ["_sv__tFinal"]) return self.get_tempo(self.hera1, self.aergo2, self.aergo1, self.oracle1, self.id1, tempo_msg, 't_final', "F", current_tempo)
def monitor_settings(self): """Check if a modification of bridge settings is requested by seeing if the config file has been changed and try to update the bridge contract (gather 2/3 validators signatures). """ config_data = self.load_config_data() t_anchor, t_final = query_tempo( self.hera_to, self.oracle_to, ["_sv__tAnchor", "_sv__tFinal"]) config_t_anchor = (config_data['networks'][self.aergo_to]['bridges'] [self.aergo_from]['t_anchor']) if t_anchor != config_t_anchor: logger.info( '\"Anchoring periode update requested: %s\"', config_t_anchor) self.update_t_anchor(config_t_anchor) config_t_final = (config_data['networks'][self.aergo_to]['bridges'] [self.aergo_from]['t_final']) if t_final != config_t_final: logger.info('\"Finality update requested: %s\"', config_t_final) self.update_t_final(config_t_final) if self.oracle_update: validators = query_validators(self.hera_to, self.oracle_to) config_validators = \ [val['addr'] for val in config_data['validators']] if validators != config_validators: logger.info( '\"Validator set update requested: %s\"', config_validators ) if self.update_validators(config_validators): self.config_data = config_data self.update_validator_connections() oracle = query_oracle(self.hera_to, self.bridge_to) config_oracle = (config_data['networks'][self.aergo_to]['bridges'] [self.aergo_from]['oracle']) if oracle != config_oracle: logger.info('\"Oracle change requested: %s\"', config_oracle) self.update_oracle(config_oracle)
def __init__(self, config_file_path: str, aergo_from: str, aergo_to: str, is_from_mainnet: bool, privkey_name: str = None, privkey_pwd: str = None, anchoring_on: bool = False, auto_update: bool = False, oracle_update: bool = False, bridge_anchoring: bool = True) -> None: threading.Thread.__init__(self, name=aergo_to + " proposer") self.config_file_path = config_file_path self.config_data = self.load_config_data() self.is_from_mainnet = is_from_mainnet self.anchoring_on = anchoring_on self.auto_update = auto_update self.oracle_update = oracle_update self.bridge_anchoring = bridge_anchoring self.aergo_from = aergo_from self.aergo_to = aergo_to self.hera_from = herapy.Aergo() self.hera_to = herapy.Aergo() self.hera_from.connect(self.config_data['networks'][aergo_from]['ip']) self.hera_to.connect(self.config_data['networks'][aergo_to]['ip']) self.bridge_from = \ (self.config_data['networks'][aergo_from]['bridges'][aergo_to] ['addr']) self.bridge_to = \ (self.config_data['networks'][aergo_to]['bridges'][aergo_from] ['addr']) self.oracle_to = \ (self.config_data['networks'][aergo_to]['bridges'][aergo_from] ['oracle']) self.oracle_to_id = query_id(self.hera_to, self.oracle_to) validators = query_validators(self.hera_to, self.oracle_to) logger.info("\"%s Validators: %s\"", self.aergo_to, validators) # create all channels with validators self.channels: List[grpc._channel.Channel] = [] self.stubs: List[BridgeOperatorStub] = [] assert len(validators) == len(self.config_data['validators']), \ "Validators in config file must match bridge validators " \ "when starting (current validators connection needed to make "\ "updates).\nExpected validators: {}".format(validators) for i, validator in enumerate(self.config_data['validators']): assert validators[i] == validator['addr'], \ "Validators in config file must match bridge validators " \ "when starting (current validators connection needed to make "\ "updates).\nExpected validators: {}".format(validators) ip = validator['ip'] channel = grpc.insecure_channel(ip) stub = BridgeOperatorStub(channel) self.channels.append(channel) self.stubs.append(stub) self.pool = Pool(len(self.stubs)) # get the current t_anchor and t_final for both sides of bridge self.t_anchor, self.t_final = query_tempo( self.hera_to, self.oracle_to, ["_sv__tAnchor", "_sv__tFinal"]) logger.info("\"%s (t_final=%s) -> %s : t_anchor=%s\"", aergo_from, self.t_final, aergo_to, self.t_anchor) if not anchoring_on and not auto_update: # if anchoring and auto update are off, use proposer as monitoring # system return logger.info("\"Set Sender Account\"") if privkey_name is None: privkey_name = 'proposer' keystore_path = self.config_data['wallet'][privkey_name]['keystore'] with open(keystore_path, "r") as f: keystore = f.read() if privkey_pwd is None: while True: try: privkey_pwd = getpass("Decrypt exported private key '{}'\n" "Password: "******"\"Wrong password, try again\"") else: self.hera_to.import_account_from_keystore(keystore, privkey_pwd) logger.info("\"%s Proposer Address: %s\"", aergo_to, self.hera_to.account.address)
def __init__( self, config_file_path: str, aergo1: str, aergo2: str, privkey_name: str = None, privkey_pwd: str = None, validator_index: int = 0, anchoring_on: bool = False, auto_update: bool = False, oracle_update: bool = False, ) -> None: """ aergo1 is considered to be the mainnet side of the bridge. Proposers should set anchor.is_from_mainnet accordingly """ self.config_file_path = config_file_path config_data = self.load_config_data() self.aergo1 = aergo1 self.aergo2 = aergo2 self.hera1 = herapy.Aergo() self.hera2 = herapy.Aergo() self.anchoring_on = anchoring_on self.auto_update = auto_update self.oracle_update = oracle_update self.hera1.connect(config_data['networks'][aergo1]['ip']) self.hera2.connect(config_data['networks'][aergo2]['ip']) self.validator_index = validator_index self.bridge1 = \ config_data['networks'][aergo1]['bridges'][aergo2]['addr'] self.bridge2 = \ config_data['networks'][aergo2]['bridges'][aergo1]['addr'] self.oracle1 = \ config_data['networks'][aergo1]['bridges'][aergo2]['oracle'] self.oracle2 = \ config_data['networks'][aergo2]['bridges'][aergo1]['oracle'] self.id1 = query_id(self.hera1, self.oracle1) self.id2 = query_id(self.hera2, self.oracle2) # check validators are correct validators1 = query_validators(self.hera1, self.oracle1) validators2 = query_validators(self.hera2, self.oracle2) assert validators1 == validators2, \ "Validators should be the same on both sides of bridge" logger.info("\"Bridge validators : %s\"", validators1) # get the current t_anchor and t_final for both sides of bridge t_anchor1, t_final1 = query_tempo( self.hera1, self.oracle1, ["_sv__tAnchor", "_sv__tFinal"] ) t_anchor2, t_final2 = query_tempo( self.hera2, self.oracle2, ["_sv__tAnchor", "_sv__tFinal"] ) logger.info( "\"%s <- %s (t_final=%s) : t_anchor=%s\"", aergo1, aergo2, t_final1, t_anchor1 ) logger.info( "\"%s (t_final=%s) -> %s : t_anchor=%s\"", aergo1, t_final2, aergo2, t_anchor2 ) if auto_update: logger.warning( "\"WARNING: This validator will vote for settings update in " "config.json\"" ) if len(validators1) != len(validators2): logger.warning( "\"WARNING: different number of validators on both sides " "of the bridge\"" ) if len(config_data['validators']) != len(validators1): logger.warning( "\"WARNING: This validator is voting for a new set of %s " "validators\"", aergo1 ) if len(config_data['validators']) != len(validators2): logger.warning( "\"WARNING: This validator is voting for a new set of %s " "validators\"", aergo2 ) for i, validator in enumerate(config_data['validators']): try: if validator['addr'] != validators1[i]: logger.warning( "\"WARNING: This validator is voting for a new set" " of %s validators\"", aergo1 ) except IndexError: # new validators index larger than current validators pass try: if validator['addr'] != validators2[i]: logger.warning( "\"WARNING: This validator is voting for a new set" " of %s validators\"", aergo2 ) except IndexError: # new validators index larger than current validators pass t_anchor1_c = (config_data['networks'][aergo1] ['bridges'][aergo2]['t_anchor']) t_final1_c = (config_data['networks'][aergo1] ['bridges'][aergo2]['t_final']) t_anchor2_c = (config_data['networks'][aergo2]['bridges'] [aergo1]['t_anchor']) t_final2_c = (config_data['networks'][aergo2]['bridges'] [aergo1]['t_final']) if t_anchor1_c != t_anchor1: logger.warning( "\"WARNING: This validator is voting to update anchoring" " periode of %s on %s\"", aergo2, aergo1 ) if t_final1_c != t_final1: logger.warning( "\"WARNING: This validator is voting to update finality " " of %s on %s\"", aergo2, aergo1 ) if t_anchor2_c != t_anchor2: logger.warning( "\"WARNING: This validator is voting to update anchoring" " periode of %s on %s\"", aergo1, aergo2 ) if t_final2_c != t_final2: logger.warning( "\"WARNING: This validator is voting to update finality " " of %s on %s\"", aergo1, aergo2 ) if privkey_name is None: privkey_name = 'validator' keystore_path = config_data['wallet'][privkey_name]['keystore'] with open(keystore_path, "r") as f: keystore = f.read() if privkey_pwd is None: while True: try: privkey_pwd = getpass("Decrypt exported private key '{}'\n" "Password: "******"\"Wrong password, try again\"") else: self.hera1.import_account_from_keystore(keystore, privkey_pwd) self.hera2.import_account_from_keystore(keystore, privkey_pwd) self.address = str(self.hera1.account.address) logger.info("\"Validator Address: %s\"", self.address)
def auto_tempo_update(from_chain, to_chain, wallet): hera = herapy.Aergo() hera.connect(wallet.config_data('networks', to_chain, 'ip')) bridge = wallet.config_data('networks', to_chain, 'bridges', from_chain, 'addr') oracle = wallet.config_data('networks', to_chain, 'bridges', from_chain, 'oracle') t_anchor_before = wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_anchor') t_final_before = wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_final') t_anchor, t_final = query_tempo(hera, bridge, ["_sv__tAnchor", "_sv__tFinal"]) assert t_anchor == t_anchor_before assert t_final == t_final_before # increase tempo nonce_before = int( hera.query_sc_state(oracle, ["_sv__nonce"]).var_proofs[0].value) wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_anchor', value=t_anchor_before + 1) wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_final', value=t_final_before + 1) wallet.save_config() nonce = nonce_before while nonce <= nonce_before + 2: time.sleep(t_anchor_before) nonce = int( hera.query_sc_state(oracle, ["_sv__nonce"]).var_proofs[0].value) t_anchor, t_final = query_tempo(hera, bridge, ["_sv__tAnchor", "_sv__tFinal"]) assert t_anchor == t_anchor_before + 1 assert t_final == t_final_before + 1 # decrease tempo nonce_before = int( hera.query_sc_state(oracle, ["_sv__nonce"]).var_proofs[0].value) wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_anchor', value=t_anchor_before) wallet.config_data('networks', to_chain, 'bridges', from_chain, 't_final', value=t_final_before) wallet.save_config() nonce = nonce_before while nonce <= nonce_before + 2: time.sleep(t_anchor_before) nonce = int( hera.query_sc_state(oracle, ["_sv__nonce"]).var_proofs[0].value) t_anchor, t_final = query_tempo(hera, bridge, ["_sv__tAnchor", "_sv__tFinal"]) assert t_anchor == t_anchor_before assert t_final == t_final_before