From 03dfd883f157a59689b9247ea07f9c29b73f55ef Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 09:09:31 +0000 Subject: [PATCH 1/6] Fix timestamp validation vulnerability in blockchain --- minichain/chain.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/minichain/chain.py b/minichain/chain.py index b65d575..52224f9 100644 --- a/minichain/chain.py +++ b/minichain/chain.py @@ -3,6 +3,7 @@ from .pow import calculate_hash import logging import threading +import time logger = logging.getLogger(__name__) @@ -51,7 +52,7 @@ def last_block(self): """ Returns the most recent block in the chain. """ - with self._lock: # Acquire lock for thread-safe access + with self._lock: return self.chain[-1] def add_block(self, block): @@ -67,18 +68,42 @@ def add_block(self, block): logger.warning("Block %s rejected: %s", block.index, exc) return False - # Validate transactions on a temporary state copy + previous_block = self.last_block + + # Timestamp Validation + + if block.timestamp <= previous_block.timestamp: + logger.warning( + "Block %s rejected: timestamp older than previous block", + block.index, + ) + return False + + current_time = int(time.time() * 1000) + + if block.timestamp > current_time + 60000: + logger.warning( + "Block %s rejected: timestamp too far in future", + block.index, + ) + return False + + # Transaction Validation + temp_state = self.state.copy() for tx in block.transactions: result = temp_state.validate_and_apply(tx) - # Reject block if any transaction fails if not result: - logger.warning("Block %s rejected: Transaction failed validation", block.index) + logger.warning( + "Block %s rejected: Transaction failed validation", + block.index, + ) return False - # All transactions valid → commit state and append block + # Commit state self.state = temp_state self.chain.append(block) - return True + + return True \ No newline at end of file From 20745aa6537e1a0ce745f5db780489877cea1b9c Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 09:14:54 +0000 Subject: [PATCH 2/6] Fix lint errors --- conftest.py | 4 +- main.py | 107 +++++++-- minichain/__init__.py | 10 +- minichain/block.py | 21 +- minichain/chain.py | 19 +- minichain/contract.py | 57 +++-- minichain/mempool.py | 19 +- minichain/p2p.py | 8 +- minichain/persistence.py | 18 +- minichain/pow.py | 10 +- minichain/serialization.py | 4 +- minichain/state.py | 72 +++--- minichain/transaction.py | 18 +- package-lock.json | 6 + reproduce_timestamp_bug.py | 67 ++++++ setup.py | 4 +- tests/test_contract.py | 11 +- tests/test_core.py | 36 +-- tests/test_persistence.py | 6 +- tests/test_protocol_hardening.py | 27 ++- tests/test_transaction_signing.py | 53 +++-- venv/bin/Activate.ps1 | 247 ++++++++++++++++++++ venv/bin/activate | 70 ++++++ venv/bin/activate.csh | 27 +++ venv/bin/activate.fish | 69 ++++++ venv/bin/base58 | 6 + venv/bin/chat-demo | 6 + venv/bin/circuit-relay-demo | 6 + venv/bin/echo-demo | 6 + venv/bin/echo-quic-demo | 6 + venv/bin/floodsub-demo | 6 + venv/bin/identify-demo | 6 + venv/bin/identify-push-demo | 6 + venv/bin/identify-push-listener-dialer-demo | 6 + venv/bin/mdns-demo | 6 + venv/bin/netaddr | 6 + venv/bin/ping-demo | 6 + venv/bin/pip | 8 + venv/bin/pip3 | 8 + venv/bin/protoc-gen-mypy | 6 + venv/bin/protoc-gen-mypy_grpc | 6 + venv/bin/pubsub-demo | 6 + venv/bin/python | 1 + venv/bin/python3 | 1 + venv/lib64 | 1 + venv/pyvenv.cfg | 5 + 46 files changed, 911 insertions(+), 193 deletions(-) create mode 100644 package-lock.json create mode 100644 reproduce_timestamp_bug.py create mode 100644 venv/bin/Activate.ps1 create mode 100644 venv/bin/activate create mode 100644 venv/bin/activate.csh create mode 100644 venv/bin/activate.fish create mode 100755 venv/bin/base58 create mode 100755 venv/bin/chat-demo create mode 100755 venv/bin/circuit-relay-demo create mode 100755 venv/bin/echo-demo create mode 100755 venv/bin/echo-quic-demo create mode 100755 venv/bin/floodsub-demo create mode 100755 venv/bin/identify-demo create mode 100755 venv/bin/identify-push-demo create mode 100755 venv/bin/identify-push-listener-dialer-demo create mode 100755 venv/bin/mdns-demo create mode 100755 venv/bin/netaddr create mode 100755 venv/bin/ping-demo create mode 100755 venv/bin/pip create mode 100755 venv/bin/pip3 create mode 100755 venv/bin/protoc-gen-mypy create mode 100755 venv/bin/protoc-gen-mypy_grpc create mode 100755 venv/bin/pubsub-demo create mode 120000 venv/bin/python create mode 120000 venv/bin/python3 create mode 120000 venv/lib64 create mode 100644 venv/pyvenv.cfg diff --git a/conftest.py b/conftest.py index 0d6b08e..2ca7a99 100644 --- a/conftest.py +++ b/conftest.py @@ -1,4 +1,4 @@ -import sys import os +import sys -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) \ No newline at end of file +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) diff --git a/main.py b/main.py index e1edc51..a925b26 100644 --- a/main.py +++ b/main.py @@ -23,13 +23,13 @@ import re import sys -from nacl.signing import SigningKey from nacl.encoding import HexEncoder +from nacl.signing import SigningKey -from minichain import Transaction, Blockchain, Block, State, Mempool, P2PNetwork, mine_block +from minichain import (Block, Blockchain, Mempool, P2PNetwork, State, + Transaction, mine_block) from minichain.validators import is_valid_receiver - logger = logging.getLogger(__name__) BURN_ADDRESS = "0" * 40 @@ -41,6 +41,7 @@ # Wallet helpers # ────────────────────────────────────────────── + def create_wallet(): sk = SigningKey.generate() pk = sk.verify_key.encode(encoder=HexEncoder).decode() @@ -51,6 +52,7 @@ def create_wallet(): # Block mining # ────────────────────────────────────────────── + def mine_and_process_block(chain, mempool, miner_pk): """Mine pending transactions into a new block.""" pending_txs = mempool.get_transactions_for_block() @@ -86,7 +88,11 @@ def mine_and_process_block(chain, mempool, miner_pk): mined_block = mine_block(block) if chain.add_block(mined_block): - logger.info("✅ Block #%d mined and added (%d txs)", mined_block.index, len(mineable_txs)) + logger.info( + "✅ Block #%d mined and added (%d txs)", + mined_block.index, + len(mineable_txs), + ) mempool.remove_transactions(mineable_txs) chain.state.credit_mining_reward(miner_pk) return mined_block @@ -96,7 +102,9 @@ def mine_and_process_block(chain, mempool, miner_pk): for tx in pending_txs: if mempool.add_transaction(tx): restored += 1 - logger.info("Mempool: Restored %d/%d txs after rejection", restored, len(pending_txs)) + logger.info( + "Mempool: Restored %d/%d txs after rejection", restored, len(pending_txs) + ) return None @@ -104,6 +112,7 @@ def mine_and_process_block(chain, mempool, miner_pk): # Network message handler # ────────────────────────────────────────────── + def make_network_handler(chain, mempool): """Return an async callback that processes incoming P2P messages.""" @@ -122,24 +131,40 @@ async def handler(data): return # Merge remote state into local state (for accounts we don't have yet) - remote_accounts = payload.get("accounts") if isinstance(payload, dict) else None + remote_accounts = ( + payload.get("accounts") if isinstance(payload, dict) else None + ) if not isinstance(remote_accounts, dict): - logger.warning("🔒 Rejected sync from %s with invalid accounts payload", peer_addr) + logger.warning( + "🔒 Rejected sync from %s with invalid accounts payload", peer_addr + ) return for addr, acc in remote_accounts.items(): if not isinstance(acc, dict): - logger.warning("🔒 Skipping malformed account %r from %s", addr, peer_addr) + logger.warning( + "🔒 Skipping malformed account %r from %s", addr, peer_addr + ) continue if addr not in chain.state.accounts: chain.state.accounts[addr] = acc - logger.info("🔄 Synced account %s... (balance=%d)", addr[:12], acc.get("balance", 0)) - logger.info("🔄 Accepted state sync from %s — %d accounts", peer_addr, len(chain.state.accounts)) + logger.info( + "🔄 Synced account %s... (balance=%d)", + addr[:12], + acc.get("balance", 0), + ) + logger.info( + "🔄 Accepted state sync from %s — %d accounts", + peer_addr, + len(chain.state.accounts), + ) elif msg_type == "tx": tx = Transaction.from_dict(payload) if mempool.add_transaction(tx): - logger.info("📥 Received tx from %s... (amount=%s)", tx.sender[:8], tx.amount) + logger.info( + "📥 Received tx from %s... (amount=%s)", tx.sender[:8], tx.amount + ) elif msg_type == "block": block = Block.from_dict(payload) @@ -204,7 +229,9 @@ async def cli_loop(sk, pk, chain, mempool, network): print(" (no accounts yet)") for addr, acc in accounts.items(): tag = " (you)" if addr == pk else "" - print(f" {addr[:12]}... balance={acc['balance']} nonce={acc['nonce']}{tag}") + print( + f" {addr[:12]}... balance={acc['balance']} nonce={acc['nonce']}{tag}" + ) # ── send ── elif cmd == "send": @@ -232,7 +259,9 @@ async def cli_loop(sk, pk, chain, mempool, network): await network.broadcast_transaction(tx) print(f" ✅ Tx sent: {amount} coins → {receiver[:12]}...") else: - print(" ❌ Transaction rejected (invalid sig, duplicate, or mempool full).") + print( + " ❌ Transaction rejected (invalid sig, duplicate, or mempool full)." + ) # ── mine ── elif cmd == "mine": @@ -288,7 +317,10 @@ async def cli_loop(sk, pk, chain, mempool, network): # 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 +): """Boot the node, optionally connect to a peer, then enter the CLI.""" sk, pk = create_wallet() @@ -297,6 +329,7 @@ async def run_node(port: int, host: str, connect_to: str | None, fund: int, data if datadir and os.path.exists(os.path.join(datadir, "data.json")): try: from minichain.persistence import load + chain = load(datadir) logger.info("Restored chain from '%s'", datadir) except FileNotFoundError as e: @@ -318,10 +351,11 @@ async def run_node(port: int, host: str, connect_to: str | None, fund: int, data # When a new peer connects, send our state so they can sync async def on_peer_connected(writer): import json as _json - sync_msg = _json.dumps({ - "type": "sync", - "data": {"accounts": chain.state.accounts} - }) + "\n" + + sync_msg = ( + _json.dumps({"type": "sync", "data": {"accounts": chain.state.accounts}}) + + "\n" + ) writer.write(sync_msg.encode()) await writer.drain() logger.info("🔄 Sent state sync to new peer") @@ -350,6 +384,7 @@ async def on_peer_connected(writer): if datadir: try: from minichain.persistence import save + save(chain, datadir) logger.info("Chain saved to '%s'", datadir) except Exception as e: @@ -359,11 +394,33 @@ async def on_peer_connected(writer): def main(): 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("--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 (host:port)") - parser.add_argument("--fund", type=int, default=100, help="Initial coins to fund this wallet (default: 100)") - parser.add_argument("--datadir", type=str, default=None, help="Directory to save/load blockchain state (enables persistence)") + 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( + "--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 (host:port)", + ) + parser.add_argument( + "--fund", + type=int, + default=100, + help="Initial coins to fund this wallet (default: 100)", + ) + parser.add_argument( + "--datadir", + type=str, + default=None, + help="Directory to save/load blockchain state (enables persistence)", + ) args = parser.parse_args() logging.basicConfig( @@ -373,7 +430,9 @@ 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) + ) except KeyboardInterrupt: print("\nNode shut down.") diff --git a/minichain/__init__.py b/minichain/__init__.py index ae52604..0fc5fe4 100644 --- a/minichain/__init__.py +++ b/minichain/__init__.py @@ -1,12 +1,12 @@ -from .pow import mine_block, calculate_hash, MiningExceededError from .block import Block from .chain import Blockchain -from .transaction import Transaction -from .state import State from .contract import ContractMachine -from .p2p import P2PNetwork from .mempool import Mempool -from .persistence import save, load +from .p2p import P2PNetwork +from .persistence import load, save +from .pow import MiningExceededError, calculate_hash, mine_block +from .state import State +from .transaction import Transaction __all__ = [ "mine_block", diff --git a/minichain/block.py b/minichain/block.py index 9854cf4..ccef1f0 100644 --- a/minichain/block.py +++ b/minichain/block.py @@ -1,8 +1,10 @@ -import time import hashlib +import time from typing import List, Optional -from .transaction import Transaction + from .serialization import canonical_json_hash +from .transaction import Transaction + def _sha256(data: str) -> str: return hashlib.sha256(data.encode()).hexdigest() @@ -13,10 +15,7 @@ def _calculate_merkle_root(transactions: List[Transaction]) -> Optional[str]: return None # Hash each transaction deterministically - tx_hashes = [ - tx.tx_id - for tx in transactions - ] + tx_hashes = [tx.tx_id for tx in transactions] # Build Merkle tree while len(tx_hashes) > 1: @@ -48,9 +47,7 @@ def __init__( # Deterministic timestamp (ms) self.timestamp: int = ( - round(time.time() * 1000) - if timestamp is None - else int(timestamp) + round(time.time() * 1000) if timestamp is None else int(timestamp) ) self.difficulty: Optional[int] = difficulty @@ -77,11 +74,7 @@ def to_header_dict(self): # BODY (transactions only) # ------------------------- def to_body_dict(self): - return { - "transactions": [ - tx.to_dict() for tx in self.transactions - ] - } + return {"transactions": [tx.to_dict() for tx in self.transactions]} # ------------------------- # FULL BLOCK diff --git a/minichain/chain.py b/minichain/chain.py index 52224f9..a98bbb7 100644 --- a/minichain/chain.py +++ b/minichain/chain.py @@ -1,10 +1,11 @@ -from .block import Block -from .state import State -from .pow import calculate_hash import logging import threading import time +from .block import Block +from .pow import calculate_hash +from .state import State + logger = logging.getLogger(__name__) @@ -15,9 +16,7 @@ def validate_block_link_and_hash(previous_block, block): ) if block.index != previous_block.index + 1: - raise ValueError( - f"invalid index {block.index} != {previous_block.index + 1}" - ) + raise ValueError(f"invalid index {block.index} != {previous_block.index + 1}") expected_hash = calculate_hash(block.to_header_dict()) if block.hash != expected_hash: @@ -39,11 +38,7 @@ def _create_genesis_block(self): """ Creates the genesis block with a fixed hash. """ - genesis_block = Block( - index=0, - previous_hash="0", - transactions=[] - ) + genesis_block = Block(index=0, previous_hash="0", transactions=[]) genesis_block.hash = "0" * 64 self.chain.append(genesis_block) @@ -106,4 +101,4 @@ def add_block(self, block): self.state = temp_state self.chain.append(block) - return True \ No newline at end of file + return True diff --git a/minichain/contract.py b/minichain/contract.py index c88a20f..19c9f09 100644 --- a/minichain/contract.py +++ b/minichain/contract.py @@ -1,10 +1,11 @@ +import ast +import json # Moved to module-level import import logging import multiprocessing -import ast -import json # Moved to module-level import logger = logging.getLogger(__name__) + def _safe_exec_worker(code, globals_dict, context_dict, result_queue): """ Worker function to execute contract code in a separate process. @@ -13,11 +14,18 @@ def _safe_exec_worker(code, globals_dict, context_dict, result_queue): # Attempt to set resource limits (Unix only) try: import resource + # Limit CPU time (seconds) and memory (bytes) - example values - resource.setrlimit(resource.RLIMIT_CPU, (2, 2)) # Align with p.join timeout (2 seconds) - resource.setrlimit(resource.RLIMIT_AS, (100 * 1024 * 1024, 100 * 1024 * 1024)) + resource.setrlimit( + resource.RLIMIT_CPU, (2, 2) + ) # Align with p.join timeout (2 seconds) + resource.setrlimit( + resource.RLIMIT_AS, (100 * 1024 * 1024, 100 * 1024 * 1024) + ) except ImportError: - logger.warning("Resource module not available. Contract will run without OS-level resource limits.") + logger.warning( + "Resource module not available. Contract will run without OS-level resource limits." + ) except (OSError, ValueError) as e: logger.warning("Failed to set resource limits: %s", e) @@ -27,6 +35,7 @@ def _safe_exec_worker(code, globals_dict, context_dict, result_queue): except Exception as e: result_queue.put({"status": "error", "error": str(e)}) + class ContractMachine: """ A minimal execution environment for Python-based smart contracts. @@ -67,19 +76,17 @@ def execute(self, contract_address, sender_address, payload, amount): "min": min, "max": max, "abs": abs, - "str": str, # Keeping str for basic functionality, relying on AST checks for safety + "str": str, # Keeping str for basic functionality, relying on AST checks for safety "bool": bool, "float": float, "list": list, "dict": dict, "tuple": tuple, "sum": sum, - "Exception": Exception, # Added to allow contracts to raise exceptions + "Exception": Exception, # Added to allow contracts to raise exceptions } - globals_for_exec = { - "__builtins__": safe_builtins - } + globals_for_exec = {"__builtins__": safe_builtins} # Execution context (locals) context = { @@ -96,8 +103,7 @@ def execute(self, contract_address, sender_address, payload, amount): # Execute in a subprocess with timeout queue = multiprocessing.Queue() p = multiprocessing.Process( - target=_safe_exec_worker, - args=(code, globals_for_exec, context, queue) + target=_safe_exec_worker, args=(code, globals_for_exec, context, queue) ) p.start() p.join(timeout=2) # 2 second timeout @@ -125,10 +131,7 @@ def execute(self, contract_address, sender_address, payload, amount): return False # Commit updated storage only after successful execution - self.state.update_contract_storage( - contract_address, - result["storage"] - ) + self.state.update_contract_storage(contract_address, result["storage"]) return True @@ -142,26 +145,36 @@ def _validate_code_ast(self, code): tree = ast.parse(code) for node in ast.walk(tree): if isinstance(node, ast.Attribute) and node.attr.startswith("__"): - logger.warning("Rejected contract code with double-underscore attribute access.") + logger.warning( + "Rejected contract code with double-underscore attribute access." + ) return False if isinstance(node, ast.Name) and node.id.startswith("__"): - logger.warning("Rejected contract code with double-underscore name.") + logger.warning( + "Rejected contract code with double-underscore name." + ) return False if isinstance(node, (ast.Import, ast.ImportFrom)): logger.warning("Rejected contract code with import statement.") return False if isinstance(node, ast.Call): - if isinstance(node.func, ast.Name) and node.func.id == 'type': + if isinstance(node.func, ast.Name) and node.func.id == "type": logger.warning("Rejected type() call.") return False - if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id in {"getattr", "setattr", "delattr"}: + if ( + isinstance(node, ast.Call) + and isinstance(node.func, ast.Name) + and node.func.id in {"getattr", "setattr", "delattr"} + ): logger.warning(f"Rejected direct call to {node.func.id}.") return False if isinstance(node, ast.Constant) and isinstance(node.value, str): if "__" in node.value: - logger.warning("Rejected string literal with double-underscore.") + logger.warning( + "Rejected string literal with double-underscore." + ) return False - if isinstance(node, ast.JoinedStr): # f-strings + if isinstance(node, ast.JoinedStr): # f-strings logger.warning("Rejected f-string usage.") return False return True diff --git a/minichain/mempool.py b/minichain/mempool.py index 4b71e08..3272465 100644 --- a/minichain/mempool.py +++ b/minichain/mempool.py @@ -3,6 +3,7 @@ logger = logging.getLogger(__name__) + class Mempool: def __init__(self, max_size=1000, transactions_per_block=100): self._pool = {} @@ -21,14 +22,16 @@ def add_transaction(self, tx): if existing: if existing.tx_id == tx.tx_id: - logger.warning("Mempool: Duplicate transaction rejected %s", tx.tx_id) + logger.warning( + "Mempool: Duplicate transaction rejected %s", tx.tx_id + ) return False # Fix: Guard against older replacements (e.g. rejected block restore) # Only allow overwrite if it's a genuinely newer replacement if tx.timestamp <= existing.timestamp: logger.warning("Mempool: Ignoring older replacement %s", tx.tx_id) return False - + else: if self._size >= self.max_size: logger.warning("Mempool: Full, rejecting transaction") @@ -48,16 +51,20 @@ def get_transactions_for_block(self): while len(selected) < self.transactions_per_block: best_tx = None best_sender = None - + for sender, txs in snapshot.items(): if txs: - if best_tx is None or (txs[0].timestamp, sender, txs[0].nonce) < (best_tx.timestamp, best_sender, best_tx.nonce): + if best_tx is None or (txs[0].timestamp, sender, txs[0].nonce) < ( + best_tx.timestamp, + best_sender, + best_tx.nonce, + ): best_tx = txs[0] best_sender = sender - + if not best_tx: break - + selected.append(best_tx) snapshot[best_sender].pop(0) diff --git a/minichain/p2p.py b/minichain/p2p.py index 3271598..3a0d12a 100644 --- a/minichain/p2p.py +++ b/minichain/p2p.py @@ -58,9 +58,7 @@ async def _notify_peer_connected(self, writer, error_message): async def start(self, port: int = 9000, host: str = "127.0.0.1"): """Start listening for incoming peer connections on the given port.""" self._port = port - self._server = await asyncio.start_server( - self._handle_incoming, host, port - ) + self._server = await asyncio.start_server(self._handle_incoming, host, port) logger.info("Network: Listening on %s:%d", host, port) async def stop(self): @@ -92,7 +90,9 @@ async def connect_to_peer(self, host: str, port: int) -> bool: self._listen_to_peer(reader, writer, f"{host}:{port}") ) self._listen_tasks.append(task) - await self._notify_peer_connected(writer, "Network: Error during outbound peer sync") + await self._notify_peer_connected( + writer, "Network: Error during outbound peer sync" + ) logger.info("Network: Connected to peer %s:%d", host, port) return True except Exception as exc: diff --git a/minichain/persistence.py b/minichain/persistence.py index b49f307..86ad759 100644 --- a/minichain/persistence.py +++ b/minichain/persistence.py @@ -15,11 +15,11 @@ blockchain = load(path="data/") """ +import copy import json +import logging import os import tempfile -import logging -import copy from .block import Block from .chain import Blockchain, validate_block_link_and_hash @@ -33,6 +33,7 @@ # Public API # --------------------------------------------------------------------------- + def save(blockchain: Blockchain, path: str = ".") -> None: """ Persist the blockchain and account state to a JSON file inside *path*. @@ -47,10 +48,7 @@ def save(blockchain: Blockchain, path: str = ".") -> None: chain_data = [block.to_dict() for block in blockchain.chain] state_data = copy.deepcopy(blockchain.state.accounts) - snapshot = { - "chain": chain_data, - "state": state_data - } + snapshot = {"chain": chain_data, "state": state_data} _atomic_write_json(os.path.join(path, _DATA_FILE), snapshot) @@ -95,8 +93,8 @@ def load(path: str = ".") -> Blockchain: _verify_chain_integrity(blocks) # --- Rebuild blockchain properly (no __new__ hack) --- - blockchain = Blockchain() # creates genesis + fresh state - blockchain.chain = blocks # replace with loaded chain + blockchain = Blockchain() # creates genesis + fresh state + blockchain.chain = blocks # replace with loaded chain # Restore state blockchain.state.accounts = raw_accounts @@ -114,6 +112,7 @@ def load(path: str = ".") -> Blockchain: # Integrity verification # --------------------------------------------------------------------------- + def _verify_chain_integrity(blocks: list) -> None: """Verify genesis, hash linkage, and block hashes.""" # Check genesis @@ -135,6 +134,7 @@ def _verify_chain_integrity(blocks: list) -> None: # Helpers # --------------------------------------------------------------------------- + def _atomic_write_json(filepath: str, data) -> None: """Write JSON atomically with fsync for durability.""" dir_name = os.path.dirname(filepath) or "." @@ -144,7 +144,7 @@ def _atomic_write_json(filepath: str, data) -> None: json.dump(data, f, indent=2) f.flush() os.fsync(f.fileno()) # Ensure data is on disk - os.replace(tmp_path, filepath) # Atomic rename + os.replace(tmp_path, filepath) # Atomic rename # Attempt to fsync the directory so the rename is durable if hasattr(os, "O_DIRECTORY"): diff --git a/minichain/pow.py b/minichain/pow.py index 40503a5..8591715 100644 --- a/minichain/pow.py +++ b/minichain/pow.py @@ -1,4 +1,5 @@ import time + from .serialization import canonical_json_hash @@ -17,7 +18,7 @@ def mine_block( max_nonce=10_000_000, timeout_seconds=None, logger=None, - progress_callback=None + progress_callback=None, ): """Mines a block using Proof-of-Work without mutating input block until success.""" @@ -26,7 +27,7 @@ def mine_block( target = "0" * difficulty local_nonce = 0 - header_dict = block.to_header_dict() # Construct header dict once outside loop + header_dict = block.to_header_dict() # Construct header dict once outside loop start_time = time.monotonic() if logger: @@ -45,7 +46,10 @@ def mine_block( raise MiningExceededError("Mining failed: max_nonce exceeded") # Enforce timeout if specified - if timeout_seconds is not None and (time.monotonic() - start_time) > timeout_seconds: + if ( + timeout_seconds is not None + and (time.monotonic() - start_time) > timeout_seconds + ): if logger: logger.warning("Mining timeout exceeded.") raise MiningExceededError("Mining failed: timeout exceeded") diff --git a/minichain/serialization.py b/minichain/serialization.py index 46741f0..4f8a5d0 100644 --- a/minichain/serialization.py +++ b/minichain/serialization.py @@ -4,7 +4,9 @@ def canonical_json_dumps(payload) -> str: """Serialize payloads deterministically for signing and hashing.""" - return json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False) + return json.dumps( + payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False + ) def canonical_json_bytes(payload) -> bytes: diff --git a/minichain/state.py b/minichain/state.py index ce9a6f0..adab04c 100644 --- a/minichain/state.py +++ b/minichain/state.py @@ -1,9 +1,11 @@ -from nacl.hash import sha256 -from nacl.encoding import HexEncoder -from .contract import ContractMachine import copy import logging +from nacl.encoding import HexEncoder +from nacl.hash import sha256 + +from .contract import ContractMachine + logger = logging.getLogger(__name__) @@ -18,10 +20,10 @@ def __init__(self): def get_account(self, address): if address not in self.accounts: self.accounts[address] = { - 'balance': 0, - 'nonce': 0, - 'code': None, - 'storage': {} + "balance": 0, + "nonce": 0, + "code": None, + "storage": {}, } return self.accounts[address] @@ -32,12 +34,14 @@ def verify_transaction_logic(self, tx): sender_acc = self.get_account(tx.sender) - if sender_acc['balance'] < tx.amount: + if sender_acc["balance"] < tx.amount: logger.error(f"Error: Insufficient balance for {tx.sender[:8]}...") return False - if sender_acc['nonce'] != tx.nonce: - logger.error(f"Error: Invalid nonce. Expected {sender_acc['nonce']}, got {tx.nonce}") + if sender_acc["nonce"] != tx.nonce: + logger.error( + f"Error: Invalid nonce. Expected {sender_acc['nonce']}, got {tx.nonce}" + ) return False return True @@ -47,7 +51,9 @@ def copy(self): Return an independent copy of state for transactional validation. """ new_state = copy.deepcopy(self) - new_state.contract_machine = ContractMachine(new_state) # Reinitialize contract_machine + new_state.contract_machine = ContractMachine( + new_state + ) # Reinitialize contract_machine return new_state def validate_and_apply(self, tx): @@ -77,8 +83,8 @@ def apply_transaction(self, tx): sender = self.accounts[tx.sender] # Deduct funds and increment nonce - sender['balance'] -= tx.amount - sender['nonce'] += 1 + sender["balance"] -= tx.amount + sender["nonce"] += 1 # LOGIC BRANCH 1: Contract Deployment if tx.receiver is None or tx.receiver == "": @@ -88,11 +94,13 @@ def apply_transaction(self, tx): existing = self.accounts.get(contract_address) if existing and existing.get("code"): # Restore sender state on failure - sender['balance'] += tx.amount - sender['nonce'] -= 1 + sender["balance"] += tx.amount + sender["nonce"] -= 1 return False - return self.create_contract(contract_address, tx.data, initial_balance=tx.amount) + return self.create_contract( + contract_address, tx.data, initial_balance=tx.amount + ) # LOGIC BRANCH 2: Contract Call # If data is provided (non-empty), treat as contract call @@ -102,32 +110,32 @@ def apply_transaction(self, tx): # Fail if contract does not exist or has no code if not receiver or not receiver.get("code"): # Rollback sender balance and nonce on failure - sender['balance'] += tx.amount # Refund amount - sender['nonce'] -= 1 + sender["balance"] += tx.amount # Refund amount + sender["nonce"] -= 1 return False # Credit contract balance - receiver['balance'] += tx.amount + receiver["balance"] += tx.amount success = self.contract_machine.execute( - contract_address=tx.receiver, # Pass receiver as contract_address + contract_address=tx.receiver, # Pass receiver as contract_address sender_address=tx.sender, payload=tx.data, - amount=tx.amount + amount=tx.amount, ) if not success: # Rollback transfer and nonce if execution fails - receiver['balance'] -= tx.amount - sender['balance'] += tx.amount # Refund amount - sender['nonce'] -= 1 + receiver["balance"] -= tx.amount + sender["balance"] += tx.amount # Refund amount + sender["nonce"] -= 1 return False return True # LOGIC BRANCH 3: Regular Transfer receiver = self.get_account(tx.receiver) - receiver['balance'] += tx.amount + receiver["balance"] += tx.amount return True def derive_contract_address(self, sender, nonce): @@ -136,16 +144,16 @@ def derive_contract_address(self, sender, nonce): def create_contract(self, contract_address, code, initial_balance=0): self.accounts[contract_address] = { - 'balance': initial_balance, - 'nonce': 0, - 'code': code, - 'storage': {} + "balance": initial_balance, + "nonce": 0, + "code": code, + "storage": {}, } return contract_address def update_contract_storage(self, address, new_storage): if address in self.accounts: - self.accounts[address]['storage'] = new_storage + self.accounts[address]["storage"] = new_storage else: raise KeyError(f"Contract address not found: {address}") @@ -153,11 +161,11 @@ def update_contract_storage_partial(self, address, updates): if address not in self.accounts: raise KeyError(f"Contract address not found: {address}") if isinstance(updates, dict): - self.accounts[address]['storage'].update(updates) + self.accounts[address]["storage"].update(updates) else: raise ValueError("Updates must be a dictionary") def credit_mining_reward(self, miner_address, reward=None): reward = reward if reward is not None else self.DEFAULT_MINING_REWARD account = self.get_account(miner_address) - account['balance'] += reward + account["balance"] += reward diff --git a/minichain/transaction.py b/minichain/transaction.py index 27f41f3..ecd04a9 100644 --- a/minichain/transaction.py +++ b/minichain/transaction.py @@ -1,23 +1,27 @@ import time -from nacl.signing import SigningKey, VerifyKey + from nacl.encoding import HexEncoder from nacl.exceptions import BadSignatureError, CryptoError +from nacl.signing import SigningKey, VerifyKey + from .serialization import canonical_json_bytes, canonical_json_hash class Transaction: - def __init__(self, sender, receiver, amount, nonce, data=None, signature=None, timestamp=None): - self.sender = sender # Public key (Hex str) - self.receiver = receiver # Public key (Hex str) or None for Deploy + def __init__( + self, sender, receiver, amount, nonce, data=None, signature=None, timestamp=None + ): + self.sender = sender # Public key (Hex str) + self.receiver = receiver # Public key (Hex str) or None for Deploy self.amount = amount self.nonce = nonce - self.data = data # Preserve None (do NOT normalize to "") + self.data = data # Preserve None (do NOT normalize to "") if timestamp is None: self.timestamp = round(time.time() * 1000) # New tx: seconds → ms elif timestamp > 1e12: - self.timestamp = int(timestamp) # Already in ms (from network) + self.timestamp = int(timestamp) # Already in ms (from network) else: - self.timestamp = round(timestamp * 1000) # Seconds → ms + self.timestamp = round(timestamp * 1000) # Seconds → ms self.signature = signature # Hex str def to_dict(self): diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a52dbf2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "MiniChain", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/reproduce_timestamp_bug.py b/reproduce_timestamp_bug.py new file mode 100644 index 0000000..2170cd8 --- /dev/null +++ b/reproduce_timestamp_bug.py @@ -0,0 +1,67 @@ +from minichain.block import Block +from minichain.chain import Blockchain + +print("\nInitializing Blockchain...") + +blockchain = Blockchain() + +genesis = blockchain.last_block + +print("\nGenesis Block Created") +print("Genesis Index:", genesis.index) +print("Genesis Timestamp:", genesis.timestamp) +print("Genesis Hash:", genesis.hash) + +print("\n--- Current Blockchain ---") +for block in blockchain.chain: + print(f"Index: {block.index}, Timestamp: {block.timestamp}, Hash: {block.hash}") +print("--------------------------") + +# ------------------------- +# PAST TIMESTAMP BLOCK +# ------------------------- + +print("\nCreating malicious block with PAST timestamp...") + +past_block = Block(index=1, previous_hash=genesis.hash, transactions=[], timestamp=0) + +past_block.hash = past_block.compute_hash() + +result1 = blockchain.add_block(past_block) + +print("\nPast Block Added:", result1) +print("Past Block Timestamp:", past_block.timestamp) + +print("\n--- Current Blockchain ---") +for block in blockchain.chain: + print(f"Index: {block.index}, Timestamp: {block.timestamp}, Hash: {block.hash}") +print("--------------------------") + +# ------------------------- +# FUTURE TIMESTAMP BLOCK +# ------------------------- + +print("\nCreating malicious block with FUTURE timestamp...") + +future_block = Block( + index=2, previous_hash=past_block.hash, transactions=[], timestamp=9999999999999 +) + +future_block.hash = future_block.compute_hash() + +result2 = blockchain.add_block(future_block) + +print("\nFuture Block Added:", result2) +print("Future Block Timestamp:", future_block.timestamp) + +print("\n--- Current Blockchain ---") +for block in blockchain.chain: + print(f"Index: {block.index}, Timestamp: {block.timestamp}, Hash: {block.hash}") +print("--------------------------") + +print("\nFinal Blockchain Length:", len(blockchain.chain)) + +if result1 and result2: + print("\nVULNERABILITY CONFIRMED") + print("Blockchain accepts miner-controlled timestamps") + print("No timestamp validation in chain.py") diff --git a/setup.py b/setup.py index 1edff7b..afce5f7 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages +from setuptools import find_packages, setup setup( name="minichain", @@ -7,7 +7,7 @@ py_modules=["main"], install_requires=[ "PyNaCl>=1.5.0", - "libp2p>=0.5.0", # Correct PyPI package name + "libp2p>=0.5.0", # Correct PyPI package name ], entry_points={ "console_scripts": [ diff --git a/tests/test_contract.py b/tests/test_contract.py index 2ac6e9f..3766e95 100644 --- a/tests/test_contract.py +++ b/tests/test_contract.py @@ -1,10 +1,11 @@ -import unittest -import sys import os +import sys +import unittest -from minichain import State, Transaction -from nacl.signing import SigningKey from nacl.encoding import HexEncoder +from nacl.signing import SigningKey + +from minichain import State, Transaction class TestSmartContract(unittest.TestCase): @@ -125,7 +126,7 @@ def test_balance_and_nonce_updates(self): tx_deploy.sign(self.sk) # Corrected typo: contract_add_ to contract_addr - contract_addr = self.state.apply_transaction(tx_deploy) + contract_addr = self.state.apply_transaction(tx_deploy) self.assertTrue(isinstance(contract_addr, str)) # Verify balance and nonce after deploy diff --git a/tests/test_core.py b/tests/test_core.py index 0a818ed..31b69f0 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,18 +1,20 @@ import unittest -from nacl.signing import SigningKey + from nacl.encoding import HexEncoder +from nacl.signing import SigningKey + +from minichain import Blockchain, State, Transaction # Removed unused imports -from minichain import Transaction, Blockchain, State # Removed unused imports class TestCore(unittest.TestCase): def setUp(self): self.state = State() self.chain = Blockchain() - + # Setup Alice self.alice_sk = SigningKey.generate() self.alice_pk = self.alice_sk.verify_key.encode(encoder=HexEncoder).decode() - + # Setup Bob self.bob_sk = SigningKey.generate() self.bob_pk = self.bob_sk.verify_key.encode(encoder=HexEncoder).decode() @@ -37,39 +39,39 @@ def test_state_transfer(self): """Test simple balance transfer.""" # 1. Credit Alice self.state.credit_mining_reward(self.alice_pk, 100) - + # 2. Transfer tx = Transaction(self.alice_pk, self.bob_pk, 40, 0) tx.sign(self.alice_sk) - + result = self.state.apply_transaction(tx) self.assertTrue(result) - + # 3. Check Balances - self.assertEqual(self.state.get_account(self.alice_pk)['balance'], 60) - self.assertEqual(self.state.get_account(self.bob_pk)['balance'], 40) + self.assertEqual(self.state.get_account(self.alice_pk)["balance"], 60) + self.assertEqual(self.state.get_account(self.bob_pk)["balance"], 40) def test_insufficient_funds(self): """Test that you cannot spend more than you have.""" self.state.credit_mining_reward(self.alice_pk, 10) - + tx = Transaction(self.alice_pk, self.bob_pk, 50, 0) tx.sign(self.alice_sk) - + result = self.state.apply_transaction(tx) self.assertFalse(result) - - self.assertEqual(self.state.get_account(self.alice_pk)['balance'], 10) - self.assertEqual(self.state.get_account(self.bob_pk)['balance'], 0) + + self.assertEqual(self.state.get_account(self.alice_pk)["balance"], 10) + self.assertEqual(self.state.get_account(self.bob_pk)["balance"], 0) def test_transaction_wrong_signer(self): """Test that a transaction signed with the wrong key is invalid.""" - tx = Transaction(self.alice_pk, self.bob_pk, 10, 0) # Alice is sender + tx = Transaction(self.alice_pk, self.bob_pk, 10, 0) # Alice is sender # Attempt to sign with Bob's key, which should raise ValueError with self.assertRaises(ValueError) as cm: tx.sign(self.bob_sk) self.assertIn("Signing key does not match sender", str(cm.exception)) -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_persistence.py b/tests/test_persistence.py index e758227..a66ea21 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -8,11 +8,11 @@ import tempfile import unittest -from nacl.signing import SigningKey from nacl.encoding import HexEncoder +from nacl.signing import SigningKey -from minichain import Blockchain, Transaction, Block, mine_block -from minichain.persistence import save, load +from minichain import Block, Blockchain, Transaction, mine_block +from minichain.persistence import load, save def _make_keypair(): diff --git a/tests/test_protocol_hardening.py b/tests/test_protocol_hardening.py index 6b169e7..ea5ed4a 100644 --- a/tests/test_protocol_hardening.py +++ b/tests/test_protocol_hardening.py @@ -3,7 +3,8 @@ from nacl.encoding import HexEncoder from nacl.signing import SigningKey -from minichain import Block, Mempool, P2PNetwork, State, Transaction, calculate_hash +from minichain import (Block, Mempool, P2PNetwork, State, Transaction, + calculate_hash) from minichain.serialization import canonical_json_dumps @@ -16,7 +17,9 @@ def test_canonical_json_is_order_independent(self): self.assertEqual(calculate_hash(left), calculate_hash(right)) def test_block_hash_matches_compute_hash(self): - block = Block(index=1, previous_hash="abc", transactions=[], timestamp=1234567890) + block = Block( + index=1, previous_hash="abc", transactions=[], timestamp=1234567890 + ) block.difficulty = 2 block.nonce = 7 @@ -28,7 +31,9 @@ def setUp(self): self.state = State() self.sender_sk = SigningKey.generate() self.sender_pk = self.sender_sk.verify_key.encode(encoder=HexEncoder).decode() - self.receiver_pk = SigningKey.generate().verify_key.encode(encoder=HexEncoder).decode() + self.receiver_pk = ( + SigningKey.generate().verify_key.encode(encoder=HexEncoder).decode() + ) self.state.credit_mining_reward(self.sender_pk, 100) def _signed_tx(self, nonce, amount=1, timestamp=None) -> Transaction: @@ -45,7 +50,9 @@ def _signed_tx(self, nonce, amount=1, timestamp=None) -> Transaction: def test_transactions_for_block_are_sorted_and_capped(self): mempool = Mempool() for nonce in range(mempool.transactions_per_block + 5): - self.assertTrue(mempool.add_transaction(self._signed_tx(nonce, timestamp=5000 + nonce))) + self.assertTrue( + mempool.add_transaction(self._signed_tx(nonce, timestamp=5000 + nonce)) + ) selected = mempool.get_transactions_for_block() @@ -103,12 +110,20 @@ async def test_invalid_message_schema_is_rejected(self): async def test_block_schema_accepts_current_block_wire_format(self): sender_sk = SigningKey.generate() sender_pk = sender_sk.verify_key.encode(encoder=HexEncoder).decode() - receiver_pk = SigningKey.generate().verify_key.encode(encoder=HexEncoder).decode() + receiver_pk = ( + SigningKey.generate().verify_key.encode(encoder=HexEncoder).decode() + ) tx = Transaction(sender_pk, receiver_pk, 1, 0, timestamp=123) tx.sign(sender_sk) - block = Block(index=1, previous_hash="0" * 64, transactions=[tx], timestamp=456, difficulty=2) + block = Block( + index=1, + previous_hash="0" * 64, + transactions=[tx], + timestamp=456, + difficulty=2, + ) block.nonce = 9 block.hash = block.compute_hash() diff --git a/tests/test_transaction_signing.py b/tests/test_transaction_signing.py index 05b79d0..4e74de8 100644 --- a/tests/test_transaction_signing.py +++ b/tests/test_transaction_signing.py @@ -13,16 +13,16 @@ """ import pytest -from nacl.signing import SigningKey from nacl.encoding import HexEncoder +from nacl.signing import SigningKey -from minichain import Transaction, State - +from minichain import State, Transaction # ------------------------------------------------------------------ # Fixtures # ------------------------------------------------------------------ + @pytest.fixture def alice(): sk = SigningKey.generate() @@ -49,6 +49,7 @@ def funded_state(alice): # 1. Valid transaction # ------------------------------------------------------------------ + def test_valid_signature_verifies(alice, bob): """A properly signed transaction must pass signature verification.""" alice_sk, alice_pk = alice @@ -64,6 +65,7 @@ def test_valid_signature_verifies(alice, bob): # 2. Modified transaction data # ------------------------------------------------------------------ + def test_tampered_amount_fails_verification(alice, bob): """Changing `amount` after signing must invalidate the signature.""" alice_sk, alice_pk = alice @@ -106,6 +108,7 @@ def test_tampered_nonce_fails_verification(alice, bob): # 3. Invalid public key # ------------------------------------------------------------------ + def test_wrong_sender_key_raises(alice, bob): """Signing with a key that doesn't match sender must raise ValueError.""" _, alice_pk = alice @@ -144,6 +147,7 @@ def test_unsigned_transaction_fails_verification(alice, bob): # 4. Replay protection # ------------------------------------------------------------------ + def test_replay_attack_same_nonce_rejected(alice, bob, funded_state): """Replaying the same transaction must be rejected the second time.""" alice_sk, alice_pk = alice @@ -153,12 +157,16 @@ def test_replay_attack_same_nonce_rejected(alice, bob, funded_state): tx.sign(alice_sk) assert funded_state.apply_transaction(tx), "First submission must succeed." - assert not funded_state.apply_transaction(tx), "Replayed transaction must be rejected." + assert not funded_state.apply_transaction( + tx + ), "Replayed transaction must be rejected." # Ensure the rejected replay did not mutate the ledger - assert funded_state.get_account(alice_pk)["balance"] == 90, \ - "Alice's balance must not change after a rejected replay." - assert funded_state.get_account(alice_pk)["nonce"] == 1, \ - "Alice's nonce must not advance after a rejected replay." + assert ( + funded_state.get_account(alice_pk)["balance"] == 90 + ), "Alice's balance must not change after a rejected replay." + assert ( + funded_state.get_account(alice_pk)["nonce"] == 1 + ), "Alice's nonce must not advance after a rejected replay." def test_out_of_order_nonce_rejected(alice, bob, funded_state): @@ -169,12 +177,16 @@ def test_out_of_order_nonce_rejected(alice, bob, funded_state): tx = Transaction(alice_pk, bob_pk, 10, nonce=5) tx.sign(alice_sk) - assert not funded_state.apply_transaction(tx), "A transaction with a skipped nonce must be rejected." + assert not funded_state.apply_transaction( + tx + ), "A transaction with a skipped nonce must be rejected." # Ensure the rejected transaction did not mutate the ledger - assert funded_state.get_account(alice_pk)["balance"] == 100, \ - "Alice's balance must remain unchanged after a rejected transaction." - assert funded_state.get_account(alice_pk)["nonce"] == 0, \ - "Alice's nonce must remain unchanged after a rejected transaction." + assert ( + funded_state.get_account(alice_pk)["balance"] == 100 + ), "Alice's balance must remain unchanged after a rejected transaction." + assert ( + funded_state.get_account(alice_pk)["nonce"] == 0 + ), "Alice's nonce must remain unchanged after a rejected transaction." def test_sequential_nonces_accepted(alice, bob, funded_state): @@ -190,9 +202,12 @@ def test_sequential_nonces_accepted(alice, bob, funded_state): tx1.sign(alice_sk) assert funded_state.apply_transaction(tx1) - assert funded_state.get_account(alice_pk)["nonce"] == 2, \ - "Alice's nonce should advance to 2 after two accepted transactions." - assert funded_state.get_account(alice_pk)["balance"] == 80, \ - "Alice's balance should be 80 after two 10-coin transfers." - assert funded_state.get_account(bob_pk)["balance"] == 20, \ - "Bob's balance should be 20 after receiving two transfers." \ No newline at end of file + assert ( + funded_state.get_account(alice_pk)["nonce"] == 2 + ), "Alice's nonce should advance to 2 after two accepted transactions." + assert ( + funded_state.get_account(alice_pk)["balance"] == 80 + ), "Alice's balance should be 80 after two 10-coin transfers." + assert ( + funded_state.get_account(bob_pk)["balance"] == 20 + ), "Bob's balance should be 20 after receiving two transfers." diff --git a/venv/bin/Activate.ps1 b/venv/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/venv/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/venv/bin/activate b/venv/bin/activate new file mode 100644 index 0000000..878ba41 --- /dev/null +++ b/venv/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath /home/moksha/MiniChain/venv) +else + # use the path as-is + export VIRTUAL_ENV=/home/moksha/MiniChain/venv +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/"bin":$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1='(venv) '"${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT='(venv) ' + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh new file mode 100644 index 0000000..61a754b --- /dev/null +++ b/venv/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV /home/moksha/MiniChain/venv + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/"bin":$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = '(venv) '"$prompt" + setenv VIRTUAL_ENV_PROMPT '(venv) ' +endif + +alias pydoc python -m pydoc + +rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish new file mode 100644 index 0000000..81cc92f --- /dev/null +++ b/venv/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV /home/moksha/MiniChain/venv + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/"bin $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT '(venv) ' +end diff --git a/venv/bin/base58 b/venv/bin/base58 new file mode 100755 index 0000000..30d5f80 --- /dev/null +++ b/venv/bin/base58 @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from base58.__main__ import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/chat-demo b/venv/bin/chat-demo new file mode 100755 index 0000000..89db539 --- /dev/null +++ b/venv/bin/chat-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.chat.chat import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/circuit-relay-demo b/venv/bin/circuit-relay-demo new file mode 100755 index 0000000..6911b6e --- /dev/null +++ b/venv/bin/circuit-relay-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.circuit_relay.relay_example import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/echo-demo b/venv/bin/echo-demo new file mode 100755 index 0000000..2cf7e20 --- /dev/null +++ b/venv/bin/echo-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.echo.echo import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/echo-quic-demo b/venv/bin/echo-quic-demo new file mode 100755 index 0000000..7c968f0 --- /dev/null +++ b/venv/bin/echo-quic-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.echo.echo_quic import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/floodsub-demo b/venv/bin/floodsub-demo new file mode 100755 index 0000000..8509928 --- /dev/null +++ b/venv/bin/floodsub-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.pubsub.floodsub import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/identify-demo b/venv/bin/identify-demo new file mode 100755 index 0000000..23ae6e1 --- /dev/null +++ b/venv/bin/identify-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.identify.identify import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/identify-push-demo b/venv/bin/identify-push-demo new file mode 100755 index 0000000..10fbd2f --- /dev/null +++ b/venv/bin/identify-push-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.identify_push.identify_push_demo import run_main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(run_main()) diff --git a/venv/bin/identify-push-listener-dialer-demo b/venv/bin/identify-push-listener-dialer-demo new file mode 100755 index 0000000..2dc08f6 --- /dev/null +++ b/venv/bin/identify-push-listener-dialer-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.identify_push.identify_push_listener_dialer import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/mdns-demo b/venv/bin/mdns-demo new file mode 100755 index 0000000..6a9936b --- /dev/null +++ b/venv/bin/mdns-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.mDNS.mDNS import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/netaddr b/venv/bin/netaddr new file mode 100755 index 0000000..fb72dd4 --- /dev/null +++ b/venv/bin/netaddr @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from netaddr.cli import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/ping-demo b/venv/bin/ping-demo new file mode 100755 index 0000000..e1a0c7b --- /dev/null +++ b/venv/bin/ping-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.ping.ping import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/pip b/venv/bin/pip new file mode 100755 index 0000000..7221cb7 --- /dev/null +++ b/venv/bin/pip @@ -0,0 +1,8 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 new file mode 100755 index 0000000..7221cb7 --- /dev/null +++ b/venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/protoc-gen-mypy b/venv/bin/protoc-gen-mypy new file mode 100755 index 0000000..687496b --- /dev/null +++ b/venv/bin/protoc-gen-mypy @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from mypy_protobuf.main import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/protoc-gen-mypy_grpc b/venv/bin/protoc-gen-mypy_grpc new file mode 100755 index 0000000..b2ff489 --- /dev/null +++ b/venv/bin/protoc-gen-mypy_grpc @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from mypy_protobuf.main import grpc +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(grpc()) diff --git a/venv/bin/pubsub-demo b/venv/bin/pubsub-demo new file mode 100755 index 0000000..7e64649 --- /dev/null +++ b/venv/bin/pubsub-demo @@ -0,0 +1,6 @@ +#!/home/moksha/MiniChain/venv/bin/python3 +import sys +from examples.pubsub.pubsub import main +if __name__ == '__main__': + sys.argv[0] = sys.argv[0].removesuffix('.exe') + sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/venv/bin/python3 b/venv/bin/python3 new file mode 120000 index 0000000..ae65fda --- /dev/null +++ b/venv/bin/python3 @@ -0,0 +1 @@ +/usr/bin/python3 \ No newline at end of file diff --git a/venv/lib64 b/venv/lib64 new file mode 120000 index 0000000..7951405 --- /dev/null +++ b/venv/lib64 @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg new file mode 100644 index 0000000..75270de --- /dev/null +++ b/venv/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /usr/bin +include-system-site-packages = false +version = 3.12.3 +executable = /usr/bin/python3.12 +command = /usr/bin/python3 -m venv /home/moksha/MiniChain/venv From 951933f51b06abc3246bd00502dde9748656d607 Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 09:26:29 +0000 Subject: [PATCH 3/6] Removed venv from tracking --- .gitignore | 2 + venv/bin/Activate.ps1 | 247 -------------------- venv/bin/activate | 70 ------ venv/bin/activate.csh | 27 --- venv/bin/activate.fish | 69 ------ venv/bin/base58 | 6 - venv/bin/chat-demo | 6 - venv/bin/circuit-relay-demo | 6 - venv/bin/echo-demo | 6 - venv/bin/echo-quic-demo | 6 - venv/bin/floodsub-demo | 6 - venv/bin/identify-demo | 6 - venv/bin/identify-push-demo | 6 - venv/bin/identify-push-listener-dialer-demo | 6 - venv/bin/mdns-demo | 6 - venv/bin/netaddr | 6 - venv/bin/ping-demo | 6 - venv/bin/pip | 8 - venv/bin/pip3 | 8 - venv/bin/protoc-gen-mypy | 6 - venv/bin/protoc-gen-mypy_grpc | 6 - venv/bin/pubsub-demo | 6 - venv/bin/python | 1 - venv/bin/python3 | 1 - venv/lib64 | 1 - venv/pyvenv.cfg | 5 - 26 files changed, 2 insertions(+), 527 deletions(-) delete mode 100644 venv/bin/Activate.ps1 delete mode 100644 venv/bin/activate delete mode 100644 venv/bin/activate.csh delete mode 100644 venv/bin/activate.fish delete mode 100755 venv/bin/base58 delete mode 100755 venv/bin/chat-demo delete mode 100755 venv/bin/circuit-relay-demo delete mode 100755 venv/bin/echo-demo delete mode 100755 venv/bin/echo-quic-demo delete mode 100755 venv/bin/floodsub-demo delete mode 100755 venv/bin/identify-demo delete mode 100755 venv/bin/identify-push-demo delete mode 100755 venv/bin/identify-push-listener-dialer-demo delete mode 100755 venv/bin/mdns-demo delete mode 100755 venv/bin/netaddr delete mode 100755 venv/bin/ping-demo delete mode 100755 venv/bin/pip delete mode 100755 venv/bin/pip3 delete mode 100755 venv/bin/protoc-gen-mypy delete mode 100755 venv/bin/protoc-gen-mypy_grpc delete mode 100755 venv/bin/pubsub-demo delete mode 120000 venv/bin/python delete mode 120000 venv/bin/python3 delete mode 120000 venv/lib64 delete mode 100644 venv/pyvenv.cfg diff --git a/.gitignore b/.gitignore index b8edfb6..43903f4 100644 --- a/.gitignore +++ b/.gitignore @@ -326,6 +326,8 @@ TSWLatexianTemp* #*Notes.bib # Python +venv/ +.venv/ __pycache__/ *.py[cod] *$py.class diff --git a/venv/bin/Activate.ps1 b/venv/bin/Activate.ps1 deleted file mode 100644 index b49d77b..0000000 --- a/venv/bin/Activate.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove VIRTUAL_ENV_PROMPT altogether. - if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { - Remove-Item -Path env:VIRTUAL_ENV_PROMPT - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } - $env:VIRTUAL_ENV_PROMPT = $Prompt -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/venv/bin/activate b/venv/bin/activate deleted file mode 100644 index 878ba41..0000000 --- a/venv/bin/activate +++ /dev/null @@ -1,70 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# You cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # Call hash to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - hash -r 2> /dev/null - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - unset VIRTUAL_ENV_PROMPT - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -# on Windows, a path can contain colons and backslashes and has to be converted: -if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath /home/moksha/MiniChain/venv) -else - # use the path as-is - export VIRTUAL_ENV=/home/moksha/MiniChain/venv -fi - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/"bin":$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1='(venv) '"${PS1:-}" - export PS1 - VIRTUAL_ENV_PROMPT='(venv) ' - export VIRTUAL_ENV_PROMPT -fi - -# Call hash to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh deleted file mode 100644 index 61a754b..0000000 --- a/venv/bin/activate.csh +++ /dev/null @@ -1,27 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. - -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV /home/moksha/MiniChain/venv - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/"bin":$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = '(venv) '"$prompt" - setenv VIRTUAL_ENV_PROMPT '(venv) ' -endif - -alias pydoc python -m pydoc - -rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish deleted file mode 100644 index 81cc92f..0000000 --- a/venv/bin/activate.fish +++ /dev/null @@ -1,69 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/). You cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - set -e _OLD_FISH_PROMPT_OVERRIDE - # prevents error when using nested fish instances (Issue #93858) - if functions -q _old_fish_prompt - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - end - - set -e VIRTUAL_ENV - set -e VIRTUAL_ENV_PROMPT - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV /home/moksha/MiniChain/venv - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/"bin $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" - set -gx VIRTUAL_ENV_PROMPT '(venv) ' -end diff --git a/venv/bin/base58 b/venv/bin/base58 deleted file mode 100755 index 30d5f80..0000000 --- a/venv/bin/base58 +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from base58.__main__ import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/chat-demo b/venv/bin/chat-demo deleted file mode 100755 index 89db539..0000000 --- a/venv/bin/chat-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.chat.chat import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/circuit-relay-demo b/venv/bin/circuit-relay-demo deleted file mode 100755 index 6911b6e..0000000 --- a/venv/bin/circuit-relay-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.circuit_relay.relay_example import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/echo-demo b/venv/bin/echo-demo deleted file mode 100755 index 2cf7e20..0000000 --- a/venv/bin/echo-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.echo.echo import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/echo-quic-demo b/venv/bin/echo-quic-demo deleted file mode 100755 index 7c968f0..0000000 --- a/venv/bin/echo-quic-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.echo.echo_quic import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/floodsub-demo b/venv/bin/floodsub-demo deleted file mode 100755 index 8509928..0000000 --- a/venv/bin/floodsub-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.pubsub.floodsub import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/identify-demo b/venv/bin/identify-demo deleted file mode 100755 index 23ae6e1..0000000 --- a/venv/bin/identify-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.identify.identify import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/identify-push-demo b/venv/bin/identify-push-demo deleted file mode 100755 index 10fbd2f..0000000 --- a/venv/bin/identify-push-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.identify_push.identify_push_demo import run_main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(run_main()) diff --git a/venv/bin/identify-push-listener-dialer-demo b/venv/bin/identify-push-listener-dialer-demo deleted file mode 100755 index 2dc08f6..0000000 --- a/venv/bin/identify-push-listener-dialer-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.identify_push.identify_push_listener_dialer import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/mdns-demo b/venv/bin/mdns-demo deleted file mode 100755 index 6a9936b..0000000 --- a/venv/bin/mdns-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.mDNS.mDNS import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/netaddr b/venv/bin/netaddr deleted file mode 100755 index fb72dd4..0000000 --- a/venv/bin/netaddr +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from netaddr.cli import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/ping-demo b/venv/bin/ping-demo deleted file mode 100755 index e1a0c7b..0000000 --- a/venv/bin/ping-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.ping.ping import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/pip b/venv/bin/pip deleted file mode 100755 index 7221cb7..0000000 --- a/venv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 deleted file mode 100755 index 7221cb7..0000000 --- a/venv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/protoc-gen-mypy b/venv/bin/protoc-gen-mypy deleted file mode 100755 index 687496b..0000000 --- a/venv/bin/protoc-gen-mypy +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from mypy_protobuf.main import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/protoc-gen-mypy_grpc b/venv/bin/protoc-gen-mypy_grpc deleted file mode 100755 index b2ff489..0000000 --- a/venv/bin/protoc-gen-mypy_grpc +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from mypy_protobuf.main import grpc -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(grpc()) diff --git a/venv/bin/pubsub-demo b/venv/bin/pubsub-demo deleted file mode 100755 index 7e64649..0000000 --- a/venv/bin/pubsub-demo +++ /dev/null @@ -1,6 +0,0 @@ -#!/home/moksha/MiniChain/venv/bin/python3 -import sys -from examples.pubsub.pubsub import main -if __name__ == '__main__': - sys.argv[0] = sys.argv[0].removesuffix('.exe') - sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python deleted file mode 120000 index b8a0adb..0000000 --- a/venv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/venv/bin/python3 b/venv/bin/python3 deleted file mode 120000 index ae65fda..0000000 --- a/venv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -/usr/bin/python3 \ No newline at end of file diff --git a/venv/lib64 b/venv/lib64 deleted file mode 120000 index 7951405..0000000 --- a/venv/lib64 +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg deleted file mode 100644 index 75270de..0000000 --- a/venv/pyvenv.cfg +++ /dev/null @@ -1,5 +0,0 @@ -home = /usr/bin -include-system-site-packages = false -version = 3.12.3 -executable = /usr/bin/python3.12 -command = /usr/bin/python3 -m venv /home/moksha/MiniChain/venv From 316703e6f8eaa357bce076af82967767a599d4f3 Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 10:00:34 +0000 Subject: [PATCH 4/6] Fix persistence timestamp validation and remove venv, run tests successfully --- minichain.egg-info/PKG-INFO | 8 ++++++++ minichain.egg-info/SOURCES.txt | 27 +++++++++++++++++++++++++ minichain.egg-info/dependency_links.txt | 1 + minichain.egg-info/entry_points.txt | 2 ++ minichain.egg-info/requires.txt | 2 ++ minichain.egg-info/top_level.txt | 3 +++ minichain/chain.py | 2 +- 7 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 minichain.egg-info/PKG-INFO create mode 100644 minichain.egg-info/SOURCES.txt create mode 100644 minichain.egg-info/dependency_links.txt create mode 100644 minichain.egg-info/entry_points.txt create mode 100644 minichain.egg-info/requires.txt create mode 100644 minichain.egg-info/top_level.txt diff --git a/minichain.egg-info/PKG-INFO b/minichain.egg-info/PKG-INFO new file mode 100644 index 0000000..e7c73d3 --- /dev/null +++ b/minichain.egg-info/PKG-INFO @@ -0,0 +1,8 @@ +Metadata-Version: 2.4 +Name: minichain +Version: 0.1.0 +Requires-Python: >=3.9 +Requires-Dist: PyNaCl>=1.5.0 +Requires-Dist: libp2p>=0.5.0 +Dynamic: requires-dist +Dynamic: requires-python diff --git a/minichain.egg-info/SOURCES.txt b/minichain.egg-info/SOURCES.txt new file mode 100644 index 0000000..89de1c2 --- /dev/null +++ b/minichain.egg-info/SOURCES.txt @@ -0,0 +1,27 @@ +README.md +main.py +setup.py +minichain/__init__.py +minichain/block.py +minichain/chain.py +minichain/contract.py +minichain/mempool.py +minichain/p2p.py +minichain/persistence.py +minichain/pow.py +minichain/serialization.py +minichain/state.py +minichain/transaction.py +minichain/validators.py +minichain.egg-info/PKG-INFO +minichain.egg-info/SOURCES.txt +minichain.egg-info/dependency_links.txt +minichain.egg-info/entry_points.txt +minichain.egg-info/requires.txt +minichain.egg-info/top_level.txt +tests/__init__.py +tests/test_contract.py +tests/test_core.py +tests/test_persistence.py +tests/test_protocol_hardening.py +tests/test_transaction_signing.py \ No newline at end of file diff --git a/minichain.egg-info/dependency_links.txt b/minichain.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/minichain.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/minichain.egg-info/entry_points.txt b/minichain.egg-info/entry_points.txt new file mode 100644 index 0000000..e6741a6 --- /dev/null +++ b/minichain.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +minichain = main:main diff --git a/minichain.egg-info/requires.txt b/minichain.egg-info/requires.txt new file mode 100644 index 0000000..c0553e1 --- /dev/null +++ b/minichain.egg-info/requires.txt @@ -0,0 +1,2 @@ +PyNaCl>=1.5.0 +libp2p>=0.5.0 diff --git a/minichain.egg-info/top_level.txt b/minichain.egg-info/top_level.txt new file mode 100644 index 0000000..b273658 --- /dev/null +++ b/minichain.egg-info/top_level.txt @@ -0,0 +1,3 @@ +main +minichain +tests diff --git a/minichain/chain.py b/minichain/chain.py index a98bbb7..70dacbf 100644 --- a/minichain/chain.py +++ b/minichain/chain.py @@ -67,7 +67,7 @@ def add_block(self, block): # Timestamp Validation - if block.timestamp <= previous_block.timestamp: + if block.timestamp < previous_block.timestamp: logger.warning( "Block %s rejected: timestamp older than previous block", block.index, From d4ed503864934c6781c6474a4b4bd61aa8bad65c Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 10:31:46 +0000 Subject: [PATCH 5/6] chore: remove autogenerated .egg-info files from repo --- minichain.egg-info/PKG-INFO | 8 -------- minichain.egg-info/SOURCES.txt | 27 ------------------------- minichain.egg-info/dependency_links.txt | 1 - minichain.egg-info/entry_points.txt | 2 -- minichain.egg-info/requires.txt | 2 -- minichain.egg-info/top_level.txt | 3 --- 6 files changed, 43 deletions(-) delete mode 100644 minichain.egg-info/PKG-INFO delete mode 100644 minichain.egg-info/SOURCES.txt delete mode 100644 minichain.egg-info/dependency_links.txt delete mode 100644 minichain.egg-info/entry_points.txt delete mode 100644 minichain.egg-info/requires.txt delete mode 100644 minichain.egg-info/top_level.txt diff --git a/minichain.egg-info/PKG-INFO b/minichain.egg-info/PKG-INFO deleted file mode 100644 index e7c73d3..0000000 --- a/minichain.egg-info/PKG-INFO +++ /dev/null @@ -1,8 +0,0 @@ -Metadata-Version: 2.4 -Name: minichain -Version: 0.1.0 -Requires-Python: >=3.9 -Requires-Dist: PyNaCl>=1.5.0 -Requires-Dist: libp2p>=0.5.0 -Dynamic: requires-dist -Dynamic: requires-python diff --git a/minichain.egg-info/SOURCES.txt b/minichain.egg-info/SOURCES.txt deleted file mode 100644 index 89de1c2..0000000 --- a/minichain.egg-info/SOURCES.txt +++ /dev/null @@ -1,27 +0,0 @@ -README.md -main.py -setup.py -minichain/__init__.py -minichain/block.py -minichain/chain.py -minichain/contract.py -minichain/mempool.py -minichain/p2p.py -minichain/persistence.py -minichain/pow.py -minichain/serialization.py -minichain/state.py -minichain/transaction.py -minichain/validators.py -minichain.egg-info/PKG-INFO -minichain.egg-info/SOURCES.txt -minichain.egg-info/dependency_links.txt -minichain.egg-info/entry_points.txt -minichain.egg-info/requires.txt -minichain.egg-info/top_level.txt -tests/__init__.py -tests/test_contract.py -tests/test_core.py -tests/test_persistence.py -tests/test_protocol_hardening.py -tests/test_transaction_signing.py \ No newline at end of file diff --git a/minichain.egg-info/dependency_links.txt b/minichain.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/minichain.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/minichain.egg-info/entry_points.txt b/minichain.egg-info/entry_points.txt deleted file mode 100644 index e6741a6..0000000 --- a/minichain.egg-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -minichain = main:main diff --git a/minichain.egg-info/requires.txt b/minichain.egg-info/requires.txt deleted file mode 100644 index c0553e1..0000000 --- a/minichain.egg-info/requires.txt +++ /dev/null @@ -1,2 +0,0 @@ -PyNaCl>=1.5.0 -libp2p>=0.5.0 diff --git a/minichain.egg-info/top_level.txt b/minichain.egg-info/top_level.txt deleted file mode 100644 index b273658..0000000 --- a/minichain.egg-info/top_level.txt +++ /dev/null @@ -1,3 +0,0 @@ -main -minichain -tests From c4363a4cf0bcbe30b7a466532d0fd10ffd3f224c Mon Sep 17 00:00:00 2001 From: Moksha Choksi Date: Sat, 28 Mar 2026 10:32:35 +0000 Subject: [PATCH 6/6] chore: ignore .egg-info build artifacts --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 43903f4..2420683 100644 --- a/.gitignore +++ b/.gitignore @@ -334,3 +334,4 @@ __pycache__/ *.so *bore.zip *bore_bin +*.egg-info/