diff --git a/Dockerfile.electrumx b/Dockerfile.electrumx index cbfbb10..8730700 100644 --- a/Dockerfile.electrumx +++ b/Dockerfile.electrumx @@ -1,88 +1,29 @@ FROM lukechilds/electrumx -RUN python3 - <<'PY' -import pathlib -p = pathlib.Path('/usr/local/lib/python3.13/dist-packages/electrumx/lib/coins.py') -s = p.read_text(encoding='utf-8') +# Copy Palladium coin definition and patch ElectrumX +COPY electrumx-patch/coins_plm.py /tmp/coins_plm.py -# Define Palladium coin classes directly in coins.py to avoid circular imports -palladium_classes = ''' +RUN python3 - <<'PATCH' +import pathlib, re -# Palladium (PLM) - Bitcoin-based cryptocurrency -class Palladium(Bitcoin): - NAME = "Palladium" - SHORTNAME = "PLM" - NET = "mainnet" +patch = pathlib.Path('/tmp/coins_plm.py').read_text() +# Extract only class definitions (skip import lines) +classes = re.split(r'^(?=class )', patch, flags=re.MULTILINE) +classes = [c for c in classes if c.strip().startswith('class ')] +body = '\n' + '\n'.join(classes) - # Address prefixes (same as Bitcoin mainnet) - P2PKH_VERBYTE = bytes([0x00]) - P2SH_VERBYTE = bytes([0x05]) - WIF_BYTE = bytes([0x80]) +for target in [ + '/usr/local/lib/python3.13/dist-packages/electrumx/lib/coins.py', + '/electrumx/src/electrumx/lib/coins.py', +]: + p = pathlib.Path(target) + if p.exists(): + s = p.read_text() + if 'class Palladium(Bitcoin):' not in s: + p.write_text(s + body) - # Bech32 prefix - HRP = "plm" - - # Genesis hash (Bitcoin mainnet) - GENESIS_HASH = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" - - # Clear inherited checkpoints - CHECKPOINTS = [] - - # Network statistics (required by ElectrumX) - TX_COUNT = 1000 - TX_COUNT_HEIGHT = 1 - TX_PER_BLOCK = 4 - - # Default ports - RPC_PORT = 2332 - PEER_DEFAULT_PORTS = {'t': '2333', 's': '52333'} - - # Deserializer - DESERIALIZER = lib_tx.DeserializerSegWit - - -class PalladiumTestnet(Palladium): - NAME = "Palladium" - SHORTNAME = "tPLM" - NET = "testnet" - - # Testnet address prefixes - P2PKH_VERBYTE = bytes([0x7f]) # 127 decimal - addresses start with 't' - P2SH_VERBYTE = bytes([0x73]) # 115 decimal - WIF_BYTE = bytes([0xff]) # 255 decimal - - # Bech32 prefix for testnet - HRP = "tplm" - - # Genesis hash (Bitcoin testnet) - GENESIS_HASH = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" - - # Network statistics (required by ElectrumX) - TX_COUNT = 500 - TX_COUNT_HEIGHT = 1 - TX_PER_BLOCK = 2 - - # Testnet ports - RPC_PORT = 12332 - PEER_DEFAULT_PORTS = {'t': '12333', 's': '62333'} -''' - -# Add Palladium classes if not already present -if 'class Palladium(Bitcoin):' not in s: - s += palladium_classes - -p.write_text(s, encoding='utf-8') - -# Also patch the source file used by the container -p_src = pathlib.Path('/electrumx/src/electrumx/lib/coins.py') -if p_src.exists(): - s_src = p_src.read_text(encoding='utf-8') - if 'class Palladium(Bitcoin):' not in s_src: - s_src += palladium_classes - p_src.write_text(s_src, encoding='utf-8') - -print('>> Patched ElectrumX with Palladium and PalladiumTestnet coins') -PY +print('>> Patched ElectrumX with Palladium coin classes') +PATCH RUN mkdir -p /certs && \ cat >/certs/openssl.cnf <<'EOF' && \ diff --git a/electrumx-patch/coins_plm.py b/electrumx-patch/coins_plm.py index 9afd513..58a9b6d 100644 --- a/electrumx-patch/coins_plm.py +++ b/electrumx-patch/coins_plm.py @@ -21,6 +21,11 @@ class Palladium(Bitcoin): # Since we share Genesis with Bitcoin, we must clear inherited checkpoints CHECKPOINTS = [] + # === Network statistics (required by ElectrumX) === + TX_COUNT = 457478 + TX_COUNT_HEIGHT = 382404 + TX_PER_BLOCK = 2 + # === Default ports === RPC_PORT = 2332 PEER_DEFAULT_PORTS = {'t': '2333', 's': '52333'} @@ -45,6 +50,11 @@ class PalladiumTestnet(Palladium): # === Genesis hash (Bitcoin testnet) === GENESIS_HASH = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" + # === Network statistics (required by ElectrumX) === + TX_COUNT = 500 + TX_COUNT_HEIGHT = 1 + TX_PER_BLOCK = 2 + # === Testnet ports === RPC_PORT = 12332 PEER_DEFAULT_PORTS = {'t': '12333', 's': '62333'} diff --git a/entrypoint.sh b/entrypoint.sh index 02b9e23..ff62d06 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -53,5 +53,41 @@ echo "RPC Port: ${RPC_PORT}" echo "DAEMON_URL: http://${RPC_USER}:***@palladiumd:${RPC_PORT}/" echo "==========================================" +# Update TX_COUNT / TX_COUNT_HEIGHT in coins.py from the live node +echo "Fetching chain tx stats from palladiumd..." +TX_STATS=$(curl -sf --user "${RPC_USER}:${RPC_PASSWORD}" \ + --data-binary '{"jsonrpc":"1.0","method":"getchaintxstats","params":[]}' \ + -H 'Content-Type: text/plain;' \ + "http://palladiumd:${RPC_PORT}/" 2>/dev/null || true) + +if [ -n "$TX_STATS" ]; then + TX_COUNT=$(echo "$TX_STATS" | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['txcount'])" 2>/dev/null || true) + TX_HEIGHT=$(echo "$TX_STATS" | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['window_final_block_height'])" 2>/dev/null || true) + + if [ -n "$TX_COUNT" ] && [ -n "$TX_HEIGHT" ]; then + echo "Patching coins.py: TX_COUNT=${TX_COUNT}, TX_COUNT_HEIGHT=${TX_HEIGHT}" + python3 - "$TX_COUNT" "$TX_HEIGHT" <<'TXPATCH' +import sys, pathlib, re +tx_count, tx_height = sys.argv[1], sys.argv[2] +for target in [ + '/usr/local/lib/python3.13/dist-packages/electrumx/lib/coins.py', + '/electrumx/src/electrumx/lib/coins.py', +]: + p = pathlib.Path(target) + if not p.exists(): + continue + s = p.read_text() + s = re.sub(r'(class Palladium\(Bitcoin\):.*?TX_COUNT\s*=\s*)\d+', rf'\g<1>{tx_count}', s, count=1, flags=re.DOTALL) + s = re.sub(r'(class Palladium\(Bitcoin\):.*?TX_COUNT_HEIGHT\s*=\s*)\d+', rf'\g<1>{tx_height}', s, count=1, flags=re.DOTALL) + p.write_text(s) +TXPATCH + echo ">> TX stats updated from live node" + else + echo ">> Could not parse tx stats, using defaults from coins_plm.py" + fi +else + echo ">> Node not reachable yet, using defaults from coins_plm.py" +fi + # Execute the original electrumx command exec /usr/local/bin/electrumx_server