# -*- coding: utf-8 -*- """Eddycoin chain selection - ONE place that decides which chain the wallet and the miners talk to. The programs read eddycoin_chain.json next to themselves (Mac app: in the data folder). If the file is missing or broken, the built-in PENDING profile below is used: the new chain is not activated yet, so the programs make NO network calls to any real server (the placeholder host *.invalid can never resolve). To switch every kit to the new chain once it is activated, change only eddycoin_chain.json: {"chain": "", "server": "https://", "pool": "https://", "explorer": "https:///eddycoin.html"} Optional "servers": ["https://", "http://:8773", ...] = more nodes of the same chain for automatic failover (the programs always add the local node http://127.0.0.1:8773 at the end of the list). """ import json, os, sys PENDING = {"chain": "eddycoin-mainnet-pending", "label": "Eddycoin (new chain - not live yet)", "server": "", "pool": "", "explorer": "", "active": False} PLACEHOLDER_SERVER = "https://new-chain-not-active.invalid" # RFC 2606: never resolves, so nothing is contacted NODE_PORT = 8773 # default port of an Eddycoin mainnet node (eddycoin-node/2.x) LOCAL_NODE = "http://127.0.0.1:%d" % NODE_PORT # Eddycoin Node running on this computer (last failover choice) def _dirs(): out = [] try: out.append(os.path.dirname(os.path.abspath(sys.executable if getattr(sys, "frozen", False) else sys.argv[0]))) except Exception: pass out.append(os.path.dirname(os.path.abspath(__file__))) if os.environ.get("EDDY_DATA_DIR"): out.insert(0, os.environ["EDDY_DATA_DIR"]) return out def load(): c = dict(PENDING) for d in _dirs(): p = os.path.join(d, "eddycoin_chain.json") if os.path.isfile(p): try: with open(p, encoding="utf-8") as f: j = json.load(f) if isinstance(j, dict): c.update({k: j[k] for k in ("chain", "label", "server", "pool", "explorer") if isinstance(j.get(k), str)}) if isinstance(j.get("servers"), list): c["servers"] = [s for s in j["servers"] if isinstance(s, str) and s.strip()] c["source"] = p break except Exception: pass c["server"] = c["server"].strip().rstrip("/"); c["pool"] = c["pool"].strip().rstrip("/") # mainnet build: a testnet id (eddycoin-testnet*) or an empty id can never activate the miners c["active"] = bool(c["server"]) and bool(c["chain"]) and c["chain"] != PENDING["chain"] and not c["chain"].lower().startswith("eddycoin-testnet") if not c["active"]: c["server"] = PLACEHOLDER_SERVER; c["pool"] = "" # failover list: main server first, then the extra nodes from chain.json, then a node on this computer lst = [] for s in ([c["server"]] + list(c.get("servers") or []) + [LOCAL_NODE]) if c["active"] else [c["server"]]: s = s.strip().rstrip("/") if s and s not in lst and s != c["pool"]: lst.append(s) c["servers"] = lst return c CHAIN = load() NETWORK = CHAIN["chain"] # mainnet chain id (GENESIS_DESIGN.md): block headers start with EDDY1--BLOCK (replay protection vs the old testnet's EDDY--BLOCK) CHAIN_ID = "EDDY1" ACTIVE = CHAIN["active"] SERVER = CHAIN["server"] POOL = CHAIN["pool"] or None SERVERS = list(CHAIN["servers"]) # failover order (solo nodes only, never the pool) EXPLORER = CHAIN["explorer"] or ((SERVER + "/eddycoin.html") if ACTIVE else "") LABEL = CHAIN.get("label") or NETWORK def network_ok(name): """a server/node answer belongs to the configured chain: EXACT match with the network id in eddycoin_chain.json (no prefix match, so no eddycoin-testnet* server is ever accepted)""" return ACTIVE and isinstance(name, str) and name == NETWORK