Skip to content

Fix JSON parameter parsing in warnet bitcoin rpc command #725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions src/warnet/bitcoin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import os
import re
import sys
Expand Down Expand Up @@ -25,7 +26,7 @@ def bitcoin():
@click.argument("method", type=str)
@click.argument("params", type=str, nargs=-1) # this will capture all remaining arguments
@click.option("--namespace", default=None, show_default=True)
def rpc(tank: str, method: str, params: str, namespace: Optional[str]):
def rpc(tank: str, method: str, params: list[str], namespace: Optional[str]):
"""
Call bitcoin-cli <method> [params] on <tank pod name>
"""
Expand All @@ -37,12 +38,53 @@ def rpc(tank: str, method: str, params: str, namespace: Optional[str]):
print(result)


def _rpc(tank: str, method: str, params: str, namespace: Optional[str] = None):
def _rpc(tank: str, method: str, params: list[str], namespace: Optional[str] = None):
# bitcoin-cli should be able to read bitcoin.conf inside the container
# so no extra args like port, chain, username or password are needed
namespace = get_default_namespace_or(namespace)

if params:
cmd = f"kubectl -n {namespace} exec {tank} --container {BITCOINCORE_CONTAINER} -- bitcoin-cli {method} {' '.join(map(str, params))}"
# Process parameters to ensure proper shell escaping
processed_params = []
for param in params:
# If the parameter looks like JSON (starts with [ or {), fix malformed patterns
if param.startswith("[") or param.startswith("{"):
# Fix common malformed JSON patterns
if '\\"' in param:
# Convert [\"value\"] to ["value"]
param = param.replace('\\"', '"')

# Try to parse as JSON to determine how to handle it
try:
parsed_json = json.loads(param)
if isinstance(parsed_json, list):
# For JSON arrays, extract elements for methods that expect individual parameters
# (like getblock, gettransaction, etc.)
# But keep as JSON for methods that expect JSON arrays (like logging)
if method in ["logging", "importdescriptors", "importmulti"]:
# These methods expect JSON arrays as-is
processed_params.append(f"'{param}'")
else:
# For single-parameter methods, only extract the first element
# For multi-parameter methods, extract all elements
if method in ["getblockhash", "getblock", "gettransaction"]:
# These methods expect a single parameter, so only take the first element
if parsed_json:
processed_params.append(str(parsed_json[0]))
else:
# Extract all array elements for other methods
for element in parsed_json:
processed_params.append(str(element))
else:
# For JSON objects, pass as-is
processed_params.append(f"'{param}'")
except json.JSONDecodeError:
# If it's not valid JSON, pass as-is
processed_params.append(param)
else:
processed_params.append(param)

cmd = f"kubectl -n {namespace} exec {tank} --container {BITCOINCORE_CONTAINER} -- bitcoin-cli {method} {' '.join(processed_params)}"
else:
cmd = f"kubectl -n {namespace} exec {tank} --container {BITCOINCORE_CONTAINER} -- bitcoin-cli {method}"
return run_command(cmd)
Expand Down
Loading