Use coins_plm.py as single source of truth for ElectrumX patch

- Remove inline Palladium coin definition from Dockerfile.electrumx
  and COPY coins_plm.py instead, reducing duplication
- Add TX_COUNT/TX_COUNT_HEIGHT/TX_PER_BLOCK to coins_plm.py with
  real chain data (457478 txs at height 382404)
- Update entrypoint.sh to fetch live TX stats from palladiumd at
  container startup, keeping sync estimates accurate automatically
This commit is contained in:
2026-02-13 00:50:41 +01:00
parent 8131d7048e
commit 5cc3dcacc8
3 changed files with 66 additions and 79 deletions

View File

@@ -1,88 +1,29 @@
FROM lukechilds/electrumx FROM lukechilds/electrumx
RUN python3 - <<'PY' # Copy Palladium coin definition and patch ElectrumX
import pathlib COPY electrumx-patch/coins_plm.py /tmp/coins_plm.py
p = pathlib.Path('/usr/local/lib/python3.13/dist-packages/electrumx/lib/coins.py')
s = p.read_text(encoding='utf-8')
# Define Palladium coin classes directly in coins.py to avoid circular imports RUN python3 - <<'PATCH'
palladium_classes = ''' import pathlib, re
# Palladium (PLM) - Bitcoin-based cryptocurrency patch = pathlib.Path('/tmp/coins_plm.py').read_text()
class Palladium(Bitcoin): # Extract only class definitions (skip import lines)
NAME = "Palladium" classes = re.split(r'^(?=class )', patch, flags=re.MULTILINE)
SHORTNAME = "PLM" classes = [c for c in classes if c.strip().startswith('class ')]
NET = "mainnet" body = '\n' + '\n'.join(classes)
# Address prefixes (same as Bitcoin mainnet) for target in [
P2PKH_VERBYTE = bytes([0x00]) '/usr/local/lib/python3.13/dist-packages/electrumx/lib/coins.py',
P2SH_VERBYTE = bytes([0x05]) '/electrumx/src/electrumx/lib/coins.py',
WIF_BYTE = bytes([0x80]) ]:
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 print('>> Patched ElectrumX with Palladium coin classes')
HRP = "plm" PATCH
# 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
RUN mkdir -p /certs && \ RUN mkdir -p /certs && \
cat >/certs/openssl.cnf <<'EOF' && \ cat >/certs/openssl.cnf <<'EOF' && \

View File

@@ -21,6 +21,11 @@ class Palladium(Bitcoin):
# Since we share Genesis with Bitcoin, we must clear inherited checkpoints # Since we share Genesis with Bitcoin, we must clear inherited checkpoints
CHECKPOINTS = [] CHECKPOINTS = []
# === Network statistics (required by ElectrumX) ===
TX_COUNT = 457478
TX_COUNT_HEIGHT = 382404
TX_PER_BLOCK = 2
# === Default ports === # === Default ports ===
RPC_PORT = 2332 RPC_PORT = 2332
PEER_DEFAULT_PORTS = {'t': '2333', 's': '52333'} PEER_DEFAULT_PORTS = {'t': '2333', 's': '52333'}
@@ -45,6 +50,11 @@ class PalladiumTestnet(Palladium):
# === Genesis hash (Bitcoin testnet) === # === Genesis hash (Bitcoin testnet) ===
GENESIS_HASH = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" GENESIS_HASH = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
# === Network statistics (required by ElectrumX) ===
TX_COUNT = 500
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 2
# === Testnet ports === # === Testnet ports ===
RPC_PORT = 12332 RPC_PORT = 12332
PEER_DEFAULT_PORTS = {'t': '12333', 's': '62333'} PEER_DEFAULT_PORTS = {'t': '12333', 's': '62333'}

View File

@@ -53,5 +53,41 @@ echo "RPC Port: ${RPC_PORT}"
echo "DAEMON_URL: http://${RPC_USER}:***@palladiumd:${RPC_PORT}/" echo "DAEMON_URL: http://${RPC_USER}:***@palladiumd:${RPC_PORT}/"
echo "==========================================" 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 # Execute the original electrumx command
exec /usr/local/bin/electrumx_server exec /usr/local/bin/electrumx_server