def get_matchmaking_config() -> dict: """Return the endpoint for a particular dragonchain Args: dragonchain_id: dragonchain id to fetch the endpoint Returns: String of dragonchain endpoint """ config = { "level": int(os.environ["LEVEL"]), "url": os.environ["DRAGONCHAIN_ENDPOINT"], "scheme": os.environ.get("PROOF_SCHEME") or "trust", "hashAlgo": os.environ["HASH"], "version": os.environ["DRAGONCHAIN_VERSION"], "encryptionAlgo": os.environ["ENCRYPTION"], } if os.environ["LEVEL"] == "5": client = interchain_dao.get_default_interchain_client() network_extra = "" if client.blockchain == "ethereum": client = cast("eth.EthereumNetwork", client) network_extra += f" network_id {client.chain_id}" elif client.blockchain == "bitcoin": client = cast("btc.BitcoinNetwork", client) network_extra += f" {'testnet3' if client.testnet else 'mainnet'}" config["network"] = f"{client.blockchain}{network_extra}" config["funded"] = bool(redis.get_sync("dc:isFunded", decode=False)) config["broadcastInterval"] = float(os.environ.get("BROADCAST_INTERVAL") or "2") config["interchainWallet"] = client.address return config
def get_matchmaking_config() -> dict: """Return the endpoint for a particular dragonchain Args: dragonchain_id: dragonchain id to fetch the endpoint Returns: String of dragonchain endpoint """ config = { "level": int(os.environ["LEVEL"]), "url": os.environ["DRAGONCHAIN_ENDPOINT"], "scheme": os.environ.get("PROOF_SCHEME") or "trust", "hashAlgo": os.environ["HASH"], "version": os.environ["DRAGONCHAIN_VERSION"], "encryptionAlgo": os.environ["ENCRYPTION"], } if os.environ["LEVEL"] == "5": try: client = interchain_dao.get_default_interchain_client() config["network"] = client.get_network_string() config["interchainWallet"] = client.address except exceptions.NotFound: _log.warning( "L5 chain does not have a default interchain network set") config["funded"] = bool(redis.get_sync("dc:isFunded", decode=False)) config["broadcastInterval"] = float( os.environ.get("BROADCAST_INTERVAL") or "2") return config
def get_current_block_level_sync(block_id: str) -> int: """Get the current level of verifications that a particular block is accepting right now (sync) Args: block_id: block_id to fetch the current level Returns: Int of the level of verifications that this block is accepting """ return int(redis.get_sync(state_key(block_id), decode=False) or -1)
def signature_is_replay(request_signature: str) -> bool: """Check if a request signature is new, and add also mark it as used (if it is new) Args: request_signature: string of the request id to check Returns: boolean true if this signature is a replay, false if not """ redis_key = f"{REQUEST_PREFIX_KEY}{request_signature}" if redis.get_sync(redis_key, decode=False): # If key exists in redis, we return True return True # Set this new request_signature in redis (value doesn't matter) and return False # Set additional 60 seconds from timeout just as a safety in case the chain's clock re-adjusts slightly (NTP) redis.set_sync(redis_key, "a", ex=60) return False
def increment_storage_error_sync(block_id: str, current_level: int) -> None: """When getting a storage error/inconsistency between redis/storage, this should be called This will roll-back a block to a previous level for verifications if FAULT_TOLERATION is surpassed for a block Basically, the state in redis can be a mis-representation of what's in actual storage, and if this occurs, we need to roll back the block verifications state and remove any bogus verifications from redis that aren't truly saved in storage, which happens on occasion Args: block_id: the block_id to increment a storage error current_level: the current block verification level state (should be in broadcast:block:state) """ # Don't do anything if at or below level two because no verifications are required yet if current_level <= 2: return error_key = storage_error_key(block_id) current_count = int(redis.get_sync(error_key, decode=False) or 0) if current_count < FAULT_TOLERATION: redis.set_sync(error_key, str(current_count + 1)) return # Beyond fault toleration, we must rollback this block # First find all verifications actually in storage prefix = f"BLOCK/{block_id}-l{current_level - 1}" good_verifications = set() for key in storage.list_objects(prefix): good_verifications.add(re.search(f"^{prefix}-(.*)", key).group(1)) # noqa: T484 # Now find all verifications the system thinks we have in redis redis_verifications_key = verifications_key(block_id, current_level - 1) all_verifications = redis.smembers_sync(redis_verifications_key) # Remove all bad verifications recorded in redis that aren't in storage, and demote block to previous level p = redis.pipeline_sync() p.srem(redis_verifications_key, *all_verifications.difference(good_verifications)) p.delete(error_key) p.set(state_key(block_id), str(current_level - 1)) p.execute()
def get_matchmaking_config() -> dict: """Return the endpoint for a particular dragonchain Args: dragonchain_id: dragonchain id to fetch the endpoint Returns: String of dragonchain endpoint """ config = { "level": int(os.environ["LEVEL"]), "url": os.environ["DRAGONCHAIN_ENDPOINT"], "scheme": os.environ.get("PROOF_SCHEME") or "trust", "hashAlgo": os.environ["HASH"], "version": os.environ["DRAGONCHAIN_VERSION"], "encryptionAlgo": os.environ["ENCRYPTION"], } if os.environ["LEVEL"] == "5": config["network"] = os.environ["NETWORK"] interchain_interface = interchain.InterchainInterface(cast(str, config["network"])) config["funded"] = bool(redis.get_sync("dc:isFunded", decode=False)) config["broadcastInterval"] = float(os.environ.get("BROADCAST_INTERVAL") or "2") config["interchainWallet"] = interchain_interface.client.interchain_address return config
def get_matchmaking_key() -> Optional[str]: """Retrieve the auth key to use for hmac with matchmaking Returns: The base64 encoded auth key string (None if not found) """ return redis.get_sync(MATCHMAKING_KEY_LOCATION)
def item_is_expired(item_as_bytes: bytes) -> bool: """Check to see if the redis-key has expired yet. If so, this returns True.""" return not redis.get_sync(get_deadline_key(item_as_bytes), decode=False)
def renew_registration_if_necessary() -> None: """Check and renew matchmaking registration if it's time""" if not redis.get_sync(REREGISTER_TIMING_KEY): register()
def test_get_sync(self): redis.get_sync("banana") redis.redis_client.get.assert_called_once_with("banana")