예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
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