Skip to content
Open
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ RUN useradd --create-home --uid 1000 minichain \
&& chown -R minichain:minichain /app
USER minichain

EXPOSE 9000
EXPOSE 9000 8545

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import socket; socket.create_connection(('127.0.0.1', 8545), timeout=3)"

ENTRYPOINT ["python", "main.py"]
CMD ["--host", "0.0.0.0", "--port", "9000"]
CMD ["--host", "0.0.0.0", "--rpc-host", "0.0.0.0", "--port", "9000"]
14 changes: 10 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ def print_prompt_info(current_pk):
# Main entry point
# ──────────────────────────────────────────────

async def run_node(port: int, host: str, connect_to: str | None, fund: int, datadir: str | None):
async def run_node(port: int, host: str, connect_to: str | None, fund: int, datadir: str | None, rpc_host: str = "127.0.0.1"):
"""Boot the node, optionally connect to a peer, then enter the CLI."""
sk, pk = load_or_create_wallet(datadir)

Expand Down Expand Up @@ -656,7 +656,7 @@ async def on_peer_connected(writer):

# Start RPC server on a port correlated to the node port (e.g. 8545 if P2P is 9000)
rpc_port = 8545 + (port - 9000)
await rpc_server.start(host="127.0.0.1", port=rpc_port)
await rpc_server.start(host=rpc_host, port=rpc_port)

# Fund this node's wallet so it can transact in the demo
if fund > 0:
Expand All @@ -683,13 +683,19 @@ async def on_peer_connected(writer):
await network.stop()


def main():
def build_arg_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="MiniChain Node — Testnet Demo")
parser.add_argument("--host", type=str, default="127.0.0.1", help="Host/IP to bind the P2P server (default: 127.0.0.1)")
parser.add_argument("--rpc-host", type=str, default="127.0.0.1", help="Host/IP to bind the RPC server (default: 127.0.0.1)")
parser.add_argument("--port", type=int, default=9000, help="TCP port to listen on (default: 9000)")
parser.add_argument("--connect", type=str, default=None, help="Peer address to connect to (multiaddr)")
parser.add_argument("--fund", type=int, default=100, help="Initial coins to fund this wallet (default: 100)")
parser.add_argument("--datadir", type=str, default=".minichain", help="Directory to save/load blockchain state (enables persistence)")
return parser


def main():
parser = build_arg_parser()
args = parser.parse_args()

logging.basicConfig(
Expand All @@ -699,7 +705,7 @@ def main():
)

try:
asyncio.run(run_node(args.port, args.host, args.connect, args.fund, args.datadir))
asyncio.run(run_node(args.port, args.host, args.connect, args.fund, args.datadir, args.rpc_host))
except KeyboardInterrupt:
print("\nNode shut down.")

Expand Down
27 changes: 27 additions & 0 deletions tests/test_cli_args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import unittest

import main


class TestCliArgs(unittest.TestCase):
def test_rpc_host_defaults_to_loopback(self):
"""Bare-metal behavior is unchanged unless --rpc-host is passed."""
args = main.build_arg_parser().parse_args([])
self.assertEqual(args.rpc_host, "127.0.0.1")
self.assertEqual(args.host, "127.0.0.1")

def test_rpc_host_can_be_overridden(self):
"""--rpc-host lets the RPC server bind independently of --host."""
args = main.build_arg_parser().parse_args(["--rpc-host", "0.0.0.0"])
self.assertEqual(args.rpc_host, "0.0.0.0")

def test_host_and_rpc_host_are_independent(self):
args = main.build_arg_parser().parse_args(
["--host", "0.0.0.0", "--rpc-host", "127.0.0.1"]
)
self.assertEqual(args.host, "0.0.0.0")
self.assertEqual(args.rpc_host, "127.0.0.1")


if __name__ == "__main__":
unittest.main()
Loading