From 728fb1f264dd270230c7b0d50a5b0caf93ce7d25 Mon Sep 17 00:00:00 2001 From: g-k-s-03 <226368649+g-k-s-03@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:08:50 +0000 Subject: [PATCH 1/3] docs: update coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c41e20..a851c73 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@

-Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267% 
+Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267% 
From aa92eab6c4a5af59a9f15b2d97a4d64c41dfffe2 Mon Sep 17 00:00:00 2001 From: g-k-s-03 Date: Sat, 29 Aug 2026 20:48:19 +0530 Subject: [PATCH 2/3] fix: add --rpc-host flag so RPC server is reachable outsider --- Dockerfile | 4 ++-- main.py | 14 ++++++++++---- tests/test_cli_args.py | 27 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 tests/test_cli_args.py diff --git a/Dockerfile b/Dockerfile index 343b61b..1fd53e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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"] diff --git a/main.py b/main.py index b37fce4..7c07251 100644 --- a/main.py +++ b/main.py @@ -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) @@ -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: @@ -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( @@ -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.") diff --git a/tests/test_cli_args.py b/tests/test_cli_args.py new file mode 100644 index 0000000..07e42fb --- /dev/null +++ b/tests/test_cli_args.py @@ -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() From 15715fc8ef6fe75e8091590b7d4935e169d114f0 Mon Sep 17 00:00:00 2001 From: g-k-s-03 Date: Tue, 1 Sep 2026 11:40:10 +0530 Subject: [PATCH 3/3] docs: fix coverage badge link to point to upstream repo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a851c73..4c41e20 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@

-Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267% 
+Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267%