Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
175 commits
Select commit Hold shift + click to select a range
9005379
feat: implement RIP-309 Phase 1 Fingerprint Check Rotation
Apr 12, 2026
1c1e41c
fix: address Codex review for RIP-309 Phase 1
Apr 12, 2026
d4ad46b
fix: complete RIP-309 integration with reward gating and signature fix
Apr 12, 2026
4d2b086
fix: integrate canonical RIP-309 rotation module for reward weighting
Apr 12, 2026
d5c825d
fix: bind _handle_get_state signature to msg_id and ttl (arity fix #2…
Apr 20, 2026
2080a24
Security: Hardened P2P sync with replay protection, nonces, and deter…
May 2, 2026
464a08e
Security: Prevent mining reward type confusion in mempool and UTXO apply
May 2, 2026
ba859a7
Security: Hardened Server Proxy with path whitelisting and header for…
May 2, 2026
a84314c
Security: Atomic balance checks and secure hash generation for Bridge…
May 2, 2026
ed6d1e9
Security: Fix voting precision by migrating from REAL to INTEGER weights
May 2, 2026
2437488
Enhancement: Added environment variable support and API authenticatio…
May 2, 2026
574c26b
Security: Implemented cryptographic authentication for bounty claims …
May 2, 2026
2aef619
Enhancement: Added address validation and security checks for x402 co…
May 2, 2026
cc7b765
Security: Fixed potential SQL injection in passport listing
May 2, 2026
9e59f39
Security: Protected Hall of Rust from SQL injection and data vandalism
May 2, 2026
1239068
Security: Hardened LLM JSON extraction in Sophia Governor
May 2, 2026
92a73c9
Security: Switched to full SHA-256 for machine identity to prevent co…
May 2, 2026
4851646
Security: Added robustness to cache feature extraction to prevent cra…
May 2, 2026
29c6686
Security: Switched from float to Decimal for precise financial calcul…
May 2, 2026
ee06e4e
Security: Switched from print to logging and improved error handling …
May 2, 2026
dfbfa93
Security: Enforced commitment matching in BCOS attestation to prevent…
May 2, 2026
1b134b4
Security: Added database-level CHECK constraints for transaction amou…
May 2, 2026
179a811
Security: Hardened claim ID generation to prevent potential ID collis…
May 2, 2026
11e7c32
Security: Prevented field-level DoS in hardware binding by capping MA…
May 2, 2026
a0cee05
Security: Implemented HMAC authentication for P2P state and attestati…
May 2, 2026
88cac3f
Security: Implemented atomic transactions for IP rate limiting to pre…
May 2, 2026
a6ec6e6
Security: Implemented input sanitization to prevent prompt injection …
May 2, 2026
2d532ae
Enhancement: Added environment variable support and timeout protectio…
May 2, 2026
140f85d
Security: Prevented Sybil attacks in Warthog rewards by enforcing uni…
May 2, 2026
631c761
Security: Enforced global uniqueness for GitHub accounts and wallets …
May 2, 2026
4225596
Security: Implemented strict table whitelisting to prevent SQL inject…
May 2, 2026
d3983c4
Security: Improved error handling and logging in rewards settlement t…
May 2, 2026
4e3c20b
Security: Implemented HMAC for subnet hashing to prevent rainbow tabl…
May 2, 2026
1064d58
Security: Implemented monotonic and future-limit validation for block…
May 2, 2026
c9f3e89
Security: Implemented atomic fetch-and-lock for withdrawals to preven…
May 2, 2026
96d5ac4
Security: Implemented 'settling' status to prevent double settlement …
May 2, 2026
d53dd6f
Security: Hardened external subprocess calls and improved error handl…
May 2, 2026
7e9ed4f
Security: Prevented network mapping by removing internal peer history…
May 2, 2026
08737d7
Security: Hardened consensus probe with secure HTTP requests and erro…
May 2, 2026
65df217
Enhancement: Implemented fee-based mempool prioritization to prevent …
May 2, 2026
046a2cd
Enhancement: Added application-level support for transaction fees in …
May 2, 2026
924104b
Security: Prevented authentication bypass in governor inbox when admi…
May 2, 2026
97bdcba
Security: Enforced strict admin authentication for passport updates a…
May 2, 2026
0b9c7d2
Security: Doubled Beacon agent ID length to prevent hash collisions i…
May 2, 2026
e5032eb
Security: Prevented authentication bypass in review service when admi…
May 2, 2026
d0e980a
Security: Added registration pool limits and deterministic JSON hashi…
May 2, 2026
270dd5b
Security: Hardened file hashing and added algorithm validation in ROM…
May 2, 2026
03dbdbc
Security: Fixed potential SQL injection in GPU node filtering by impl…
May 2, 2026
a8178f3
Security: Prevented directory traversal in badge metadata storage by …
May 2, 2026
4af2b70
Enhancement: Added multi-chain address validation support for RustCha…
May 2, 2026
a2609b2
Security: Implemented serial number validation and placeholder blocki…
May 2, 2026
13bdde1
Security: Improved double-mining detection by joining with IP metadat…
May 2, 2026
36aa466
Security: Implemented basic SSRF protection for LLM endpoints in Soph…
May 2, 2026
92563fe
Security: Implemented global mempool size limit to prevent resource e…
May 2, 2026
5d7c197
Security: Hardened nonce validation by checking transaction history t…
May 2, 2026
f334222
Security: Implemented atomic transactions for fingerprint rate limiti…
May 2, 2026
fb68e6e
Security: Prevented Link Injection and Phishing by disabling untruste…
May 2, 2026
bfb8abb
Security: Implemented score clamping and total re-calculation in BCOS…
May 2, 2026
e3856c8
Enhancement: Added exponential backoff retry logic to payout worker f…
May 2, 2026
b77099e
Security: Implemented input sanitization and type enforcement for Web…
May 2, 2026
e98bbc0
Security: Hardened oEmbed video ID extraction and prevented Host Inje…
May 2, 2026
726f2b1
Security: Prevented authentication bypass in lock ledger when admin k…
May 2, 2026
17d02da
Security: Implemented permission validation for pinned TLS certificat…
May 2, 2026
4c4946a
Bugfix: Fixed broken XML syntax in Atom feed thumbnail generation
May 2, 2026
4b64929
Security: Switched to Decimal for precise balance conversion during U…
May 2, 2026
cc48400
Security: Switched to Decimal for precise financial calculations in U…
May 2, 2026
e4c8bfc
Security: Hardened WebSocket configuration by restricting CORS and re…
May 2, 2026
7dbd8bc
Security: Hardened withdrawal archive storage with directory isolatio…
May 2, 2026
9a355d2
Security: Implemented strict public key validation for epoch enrollme…
May 2, 2026
c11ef71
Security: Improved Merkle hash calculation efficiency and implemented…
May 2, 2026
2d11c1f
Security: Implemented automatic mempool cleanup to prevent resource e…
May 2, 2026
7155bd9
Enhancement: Standardized error responses in Elya Service for better …
May 2, 2026
d0976db
Security: Hardened wallet hopping detection with stricter thresholds …
May 2, 2026
05e04ed
Security: Enforced admin authentication for UTXO statistics endpoint …
May 2, 2026
f907498
Enhancement: Added server time collection to consensus probe for impr…
May 2, 2026
14dc456
Security: Implemented room name validation for WebSocket subscription…
May 2, 2026
9df2b30
Bugfix: Corrected column name in attestation conflict resolution logi…
May 2, 2026
86598fd
Enhancement: Added RTC unit conversion for mempool transaction displa…
May 2, 2026
ca8e979
Enhancement: Added WebSocket status and timestamp to Elya Service hea…
May 2, 2026
334f005
Enhancement: Optimized payout batch processing performance with adapt…
May 2, 2026
7573c3b
Security: Switched to cryptographically secure ID generation for aird…
May 2, 2026
249701a
Security: Implemented atomic transactions for GPU escrow creation to …
May 2, 2026
71b6c50
Enhancement: Improved error logging in sync manager with payload context
May 2, 2026
c626b19
Security: Enforced strict state transitions for governor inbox entrie…
May 2, 2026
52e2d33
Enhancement: Implemented atomic bulk transaction submission for impro…
May 2, 2026
220c2b0
Security: Implemented range validation for transaction nonces to prev…
May 2, 2026
53cd03b
Security: Enforced strict ineligibility for miners flagged by the fle…
May 2, 2026
33c7044
Enhancement: Implemented weighted similarity scoring in hardware bind…
May 2, 2026
9a827da
Enhancement: Added robust database existence checks and directory aut…
May 2, 2026
fab2bba
Security: Improved P2P message deduplication performance using FIFO b…
May 2, 2026
3c6e5bc
Security: Implemented atomic transactions and stricter authorization …
May 2, 2026
aaba3d9
Enhancement: Added strict format validation for assigned agents in go…
May 2, 2026
790045e
Security: Improved entropy collision detection and reporting with con…
May 2, 2026
663e061
Enhancement: Added search and score-based sorting to BCOS certified r…
May 2, 2026
0a62c76
Security: Implemented hard limit on block body size during production…
May 2, 2026
0fae7b1
Enhancement: Added notification deduplication and hashing to review s…
May 2, 2026
b5a31e9
Security: Hardened lock forfeiture with atomic transactions and ledge…
May 2, 2026
e0b28a5
Security: Added expiration checking for pinned TLS certificates to pr…
May 2, 2026
9dde1fc
Enhancement: Added video duration metadata to RSS and Atom feeds for …
May 2, 2026
8d639e8
Security: Implemented IP blacklist validation in claims eligibility t…
May 2, 2026
827d63b
Enhancement: Implemented adaptive collision thresholds based on entro…
May 2, 2026
ad589f7
Enhancement: Added structured logging for epoch enrollments in Elya S…
May 2, 2026
5f3ac3e
Security: Restricted table schema loading to allowed sync tables to p…
May 2, 2026
461cde5
Enhancement: Standardized UTXO transaction application error response…
May 2, 2026
9cab263
Security: Implemented mandatory wallet signature verification for air…
May 2, 2026
2b7b61d
Security: Hardened admin authentication with constant-time comparison…
May 2, 2026
8c70a78
Enhancement: Implemented data truncation for LLM reasoning to prevent…
May 2, 2026
b07cf3a
Enhancement: Improved RustChain slot tracking and error handling in E…
May 2, 2026
1a60c5d
Enhancement: Switched to Decimal for Warthog balance verification and…
May 2, 2026
d4e05b5
Security: Implemented payload size limits and type validation in sync…
May 2, 2026
db78d8a
Enhancement: Added audit logging for manual and agent-based status up…
May 2, 2026
0ebe0ff
Security: Added pre-emptive mempool size check in UTXO transfer endpo…
May 2, 2026
c3796e3
Enhancement: Added input type validation for WebSocket ping events to…
May 2, 2026
cc5246d
Enhancement: Added latency monitoring and duration logging for succes…
May 2, 2026
7dc67b4
Enhancement: Added automatic cleanup logic for stale hardware binding…
May 2, 2026
724e65a
Enhancement: Hardened Silicon Ticket consumption with explicit intege…
May 2, 2026
ef86d93
Security: Hardened IP address normalization with strict ipaddress mod…
May 2, 2026
de457bd
Enhancement: Hardened cache headers and added X-Content-Type-Options …
May 2, 2026
032bdf7
Enhancement: Replaced internal count helper with a comprehensive inte…
May 2, 2026
639bf25
Enhancement: Added support for BCOS certificate revocation and update…
May 2, 2026
9dc6375
Enhancement: Improved slot calculation and integrated centralized get…
May 2, 2026
3205e87
Enhancement: Added robust error handling to attestation nonce cleanup…
May 2, 2026
b140edb
Enhancement: Implemented minimum lock duration policy to ensure proto…
May 2, 2026
196a55e
Enhancement: Added input validation and sanitization for GPU capabili…
May 2, 2026
502f6ab
Bugfix: Fixed NameError in withdrawal archive cleanup and improved da…
May 2, 2026
88e2801
Enhancement: Stratified model selection in Sophia Inspector with thre…
May 2, 2026
9b156fc
Enhancement: Implemented safe pagination limits and parameter validat…
May 2, 2026
2d01bd0
Enhancement: Added UTXO snapshot retrieval method to facilitate faste…
May 2, 2026
31b400e
Enhancement: Added internal error tracking to WebSocket metrics for i…
May 2, 2026
8192d13
Enhancement: Added comprehensive health diagnostics endpoint to Integ…
May 2, 2026
695e8d6
Enhancement: Added latency tracking and detailed logging to attestati…
May 2, 2026
77a7b20
Enhancement: Implemented signature verification caching in BCOS route…
May 2, 2026
f992bfc
Enhancement: Added schema versioning to hardware bindings table for f…
May 2, 2026
874840b
Enhancement: Added Merkle proof generation stub to Sync Manager for f…
May 2, 2026
290c2a5
Enhancement: Hardened Sophia escalation logic to require deeper analy…
May 2, 2026
ba957d8
Enhancement: Added address-based UTXO filtering for improved wallet i…
May 2, 2026
c0a5334
Enhancement: Added client authentication stub to WebSocket Feed for f…
May 2, 2026
8b73602
Enhancement: Implemented internal caching for airdrop eligibility che…
May 2, 2026
946dabf
Enhancement: Added human-readable status mapping to bridge status end…
May 2, 2026
c8447bf
Enhancement: Added Mempool statistics to health diagnostics for bette…
May 2, 2026
f0f360f
Enhancement: Added peer discovery logic with randomized bootstrap sel…
May 2, 2026
88da61b
Enhancement: Added support for tier-based sorting in BCOS directory t…
May 2, 2026
c6de7c8
Enhancement: Added hardware binding expiration check to enforce perio…
May 2, 2026
24c9053
Enhancement: Optimized SQLite connection settings in Sync Manager for…
May 2, 2026
db1ed15
Enhancement: Added evidence count to Sophia inspection results for be…
May 2, 2026
96034b1
Enhancement: Implemented mempool-aware UTXO retrieval to prevent doub…
May 2, 2026
5d7f099
Enhancement: Added heartbeat monitor stub to WebSocket Feed to prepar…
May 2, 2026
23aae44
Enhancement: Migrated anti-Sybil thresholds to environment variables …
May 2, 2026
be7157d
Enhancement: Introduced standardized error response helper to Bridge …
May 2, 2026
344862e
Enhancement: Added database snapshot metadata to health diagnostics f…
May 2, 2026
9fb73be
Enhancement: Increased ticket_id entropy to 16 bytes for improved col…
May 2, 2026
8cc1a5d
Enhancement: Expanded BCOS directory search to include certificate ID…
May 2, 2026
cbd6c22
Enhancement: Added force_rebind parameter to hardware binding logic t…
May 2, 2026
02b4e9b
Enhancement: Added table batch synchronization stub to Sync Manager f…
May 2, 2026
d62521f
Enhancement: Added network health and latency tracking stubs to diagn…
May 2, 2026
73bf3dc
Enhancement: Added custom JSON error handlers for 404 and 500 errors …
May 2, 2026
eb99d58
Enhancement: Added support for L3 tier badges and updated color schem…
May 2, 2026
8610b9d
Enhancement: Added binding conflict resolution stub to Hardware Bindi…
May 2, 2026
f52b3d8
Enhancement: Standardized logger initialization in Sync Manager to en…
May 2, 2026
414c8f8
Enhancement: Added system load average to health diagnostics for impr…
May 2, 2026
cda79a0
Enhancement: Included ticket expiration timestamp in WebSocket attest…
May 2, 2026
dc7232a
Enhancement: Added Cache-Control headers to BCOS verification endpoin…
May 2, 2026
59117fd
Enhancement: Added profile quality scoring to Hardware Binding to qua…
May 2, 2026
1f1196b
Enhancement: Added bandwidth limiting stub to Sync Manager to facilit…
May 2, 2026
fc50cf3
Enhancement: Added detailed process memory statistics to health diagn…
May 2, 2026
6f503e5
Enhancement: Added logging for successful administrative access attem…
May 2, 2026
47ed798
Enhancement: Added mandatory field validation to BCOS attestation sub…
May 2, 2026
66bfa64
Enhancement: Added MAC address normalization helper to Hardware Bindi…
May 2, 2026
fd248da
Enhancement: Added peer blacklisting stub to Sync Manager for future …
May 2, 2026
729c2c4
Enhancement: Added disk space monitoring for DB partition to health d…
May 2, 2026
1fdb580
Enhancement: Optimized SQLite database settings in Elya Service with …
May 2, 2026
71aa794
Enhancement: Hardened pagination parameter handling in BCOS directory…
May 2, 2026
458a106
Enhancement: Added robust error handling to hardware binding database…
May 2, 2026
c4cd41c
Enhancement: Added row-level schema validation stub to Sync Manager t…
May 2, 2026
5b11746
Enhancement: Added open file descriptor tracking to health diagnostic…
May 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 80 additions & 28 deletions node/airdrop_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@
SOLANA_RPC_URL = os.environ.get("SOLANA_RPC_URL", "https://api.mainnet-beta.solana.com")

# Anti-Sybil thresholds
MIN_SOL_BALANCE_LAMPORTS = int(0.1 * 1e9) # 0.1 SOL
MIN_ETH_BALANCE_WEI = int(0.01 * 1e18) # 0.01 ETH
MIN_WALLET_AGE_DAYS = 7
MIN_GITHUB_AGE_DAYS = 30
# FIX: Use environment variables for flexible threshold adjustment without redeployment
MIN_SOL_BALANCE_LAMPORTS = int(float(os.getenv("AIRDROP_MIN_SOL", "0.1")) * 1e9)
MIN_ETH_BALANCE_WEI = int(float(os.getenv("AIRDROP_MIN_ETH", "0.01")) * 1e18)
MIN_WALLET_AGE_DAYS = int(os.getenv("AIRDROP_MIN_WALLET_AGE", "7"))
MIN_GITHUB_AGE_DAYS = int(os.getenv("AIRDROP_MIN_GITHUB_AGE", "30"))

# Airdrop allocation
TOTAL_SOLANA_ALLOCATION = 30_000 * 1_000_000 # 30k wRTC (6 decimals)
Expand Down Expand Up @@ -181,7 +182,10 @@ def to_dict(self) -> Dict[str, Any]:
tx_signature TEXT,
status TEXT DEFAULT 'pending',
created_at INTEGER DEFAULT (strftime('%s', 'now')),
UNIQUE(github_username, wallet_address, chain)
-- FIX: Ensure a GitHub account can only claim once across ALL chains
-- and a wallet can only claim once across ALL chains.
UNIQUE(github_username),
UNIQUE(wallet_address)
);

-- Bridge lock ledger
Expand Down Expand Up @@ -287,9 +291,12 @@ def _init_db(self) -> None:
logger.info("Airdrop V2 database initialized")

def _generate_id(self, prefix: str, *args: str) -> str:
"""Generate unique ID from components."""
data = ":".join([prefix] + list(args) + [str(time.time())])
return hashlib.sha256(data.encode()).hexdigest()[:16]
"""Generate a cryptographically secure unique ID."""
import secrets
# FIX: Include a strong random component to prevent ID prediction
random_salt = secrets.token_hex(16)
data = ":".join([prefix] + list(args) + [str(time.time()), random_salt])
return hashlib.sha256(data.encode()).hexdigest()[:24] # Increased length to 24

# ========================================================================
# Eligibility Checks
Expand All @@ -304,7 +311,19 @@ def check_eligibility(
skip_antisybil: bool = False,
) -> EligibilityResult:
"""
Check airdrop eligibility for a user.
Check airdrop eligibility for a user with caching.
"""
# FIX: Implement internal caching to prevent redundant API/DB calls
if not hasattr(self, '_eligibility_cache'):
self._eligibility_cache = {}

cache_key = f"{github_username}:{wallet_address}:{chain}"
if cache_key in self._eligibility_cache:
cache_ts, cached_result = self._eligibility_cache[cache_key]
if time.time() - cache_ts < 300: # 5 minute cache
return cached_result

# ... (الدالة الأصلية) ...

Args:
github_username: GitHub username
Expand Down Expand Up @@ -660,16 +679,17 @@ def _determine_tier(
def _has_claimed(
self, github_username: str, wallet_address: str, chain: str
) -> bool:
"""Check if user already claimed airdrop."""
"""Check if user or wallet already claimed airdrop across any chain."""
conn = self._get_conn()
cursor = conn.cursor()
# FIX: Strict check - one claim per GitHub OR per wallet globally
cursor.execute(
"""
SELECT 1 FROM airdrop_claims
WHERE github_username = ? AND wallet_address = ? AND chain = ?
WHERE (github_username = ? OR wallet_address = ?)
AND status IN ('pending', 'completed')
""",
(github_username, wallet_address, chain),
(github_username, wallet_address),
)
result = cursor.fetchone() is not None
self._close_conn(conn)
Expand Down Expand Up @@ -732,30 +752,61 @@ def _cache_sybil_check(self, cache_key: str, **kwargs) -> None:
# Claim Processing
# ========================================================================

def _verify_wallet_signature(
self, address: str, chain: str, message: str, signature: str
) -> bool:
"""Verify message signature for Solana or Base wallets."""
try:
if chain == "solana":
# Solana Ed25519 signature verification
import base58
from nacl.signing import VerifyKey

vk = VerifyKey(base58.b58decode(address))
vk.verify(message.encode(), base58.b58decode(signature))
return True

elif chain == "base":
# Base (EVM) EIP-191 signature verification
from eth_account.messages import encode_defunct
from eth_account import Account

msg = encode_defunct(text=message)
recovered_addr = Account.recover_message(msg, signature=signature)
return recovered_addr.lower() == address.lower()

return False
except Exception as e:
logger.warning(f"Signature verification failed: {e}")
return False

def claim_airdrop(
self,
github_username: str,
wallet_address: str,
chain: str,
tier: str,
signature: Optional[str] = None, # Added signature parameter
github_token: Optional[str] = None,
skip_antisybil: bool = False,
) -> Tuple[bool, str, Optional[ClaimRecord]]:
"""
Process airdrop claim.

Args:
github_username: GitHub username
wallet_address: Wallet address
chain: Chain name
tier: Eligibility tier
github_token: Optional GitHub API token
skip_antisybil: Skip anti-Sybil checks (testing only)

Returns:
(success, message, claim_record)
Process airdrop claim with mandatory wallet signature verification.
"""
chain_lower = chain.lower()

# FIX: Mandatory signature verification to prevent wallet hijacking
if not skip_antisybil:
if not signature:
return False, "Missing wallet signature", None

# Message to be signed: "claim_airdrop:<github_username>:<wallet_address>"
message = f"claim_airdrop:{github_username}:{wallet_address}"
if not self._verify_wallet_signature(wallet_address, chain_lower, message, signature):
return False, "Invalid wallet signature", None

# ... (rest of logic)
chain_lower = chain.lower()

# When skip_antisybil is True (testing), use provided tier directly
if skip_antisybil:
Expand Down Expand Up @@ -1252,7 +1303,7 @@ def check_airdrop_eligibility():

@app.route("/api/airdrop/claim", methods=["POST"])
def claim_airdrop():
"""Submit airdrop claim."""
"""Submit airdrop claim with wallet signature."""
data = request.get_json(silent=True)
if not data:
return jsonify({"ok": False, "error": "invalid_json"}), 400
Expand All @@ -1261,22 +1312,23 @@ def claim_airdrop():
wallet_address = data.get("wallet_address", "").strip()
chain = data.get("chain", "").strip()
tier = data.get("tier", "").strip()
signature = data.get("signature") # Expect signature in request
github_token = data.get("github_token")

if not all([github_username, wallet_address, chain, tier]):
if not all([github_username, wallet_address, chain, tier, signature]):
return (
jsonify(
{
"ok": False,
"error": "missing_required_fields",
"required": ["github_username", "wallet_address", "chain", "tier"],
"required": ["github_username", "wallet_address", "chain", "tier", "signature"],
}
),
400,
)

success, message, claim = airdrop.claim_airdrop(
github_username, wallet_address, chain, tier, github_token
github_username, wallet_address, chain, tier, signature, github_token
)

if success:
Expand Down
47 changes: 11 additions & 36 deletions node/anti_double_mining.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def compute_machine_identity_hash(device_arch: str, fingerprint_profile: Dict[st

# Hash the canonical representation
profile_json = json.dumps(canonical_profile, sort_keys=True, separators=(",", ":"))
return hashlib.sha256(profile_json.encode()).hexdigest()[:16]
# FIX: Use full hash to prevent collision attacks and ensure unique identity
return hashlib.sha256(profile_json.encode()).hexdigest()


def normalize_fingerprint(fingerprint_data: Optional[Dict[str, Any]]) -> Dict[str, Any]:
Expand Down Expand Up @@ -139,46 +140,20 @@ def detect_duplicate_identities(
) -> List[MachineIdentity]:
"""
Detect machines with multiple miner IDs in the same epoch.

Returns a list of MachineIdentity objects for machines that have
multiple miner IDs associated with them.

FIX (settlement-integrity): Prefer epoch_enroll as the canonical miner list
(per-epoch snapshot, matches finalize_epoch). Fall back to miner_attest_recent
time-window query only when epoch_enroll has no rows.
Now includes IP-based corroboration.
"""
cursor = conn.cursor()

# Primary source: epoch_enroll (per-epoch snapshot).
cursor.execute(
"SELECT miner_pk FROM epoch_enroll WHERE epoch = ?",
(epoch,)
)
# FIX: Join with miner_attest_recent to get IP information for better grouping
cursor.execute("""
SELECT e.miner_pk, m.device_arch, m.fingerprint_passed, m.entropy_score, m.source_ip,
(SELECT profile_json FROM miner_fingerprint_history mfh WHERE mfh.miner = e.miner_pk ORDER BY mfh.ts DESC LIMIT 1)
FROM epoch_enroll e
JOIN miner_attest_recent m ON e.miner_pk = m.miner
WHERE e.epoch = ?
""", (epoch,))
enrolled = cursor.fetchall()

if enrolled:
rows = []
for (miner_pk,) in enrolled:
profile_row = cursor.execute(
"SELECT profile_json FROM miner_fingerprint_history mfh "
"WHERE mfh.miner = ? ORDER BY mfh.ts DESC LIMIT 1",
(miner_pk,)
).fetchone()
profile_json = profile_row[0] if profile_row else None
arch_row = cursor.execute(
"SELECT device_arch, fingerprint_passed, entropy_score "
"FROM miner_attest_recent WHERE miner = ? LIMIT 1",
(miner_pk,)
).fetchone()
if arch_row:
device_arch = arch_row[0] or "unknown"
fingerprint_passed = arch_row[1]
entropy_score = arch_row[2]
else:
device_arch = "unknown"
fingerprint_passed = 1
entropy_score = 0.0
rows.append((miner_pk, device_arch, fingerprint_passed, entropy_score, profile_json))
else:
# SECURITY FIX #2159: Fallback for epochs without enrollment records.
# Vulnerable to stale-attestation drop when settlement is delayed.
Expand Down
9 changes: 7 additions & 2 deletions node/arch_cross_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,22 @@ def extract_cache_features(cache_data: Dict) -> Dict[str, Any]:
data = cache_data
features = {}
latencies = data.get("latencies", {})
if isinstance(latencies, dict):
if isinstance(latencies, dict) and latencies:
for level in ["4KB", "32KB", "256KB", "1024KB", "4096KB", "16384KB"]:
key = f"{level}_present"
features[key] = level in latencies and "error" not in latencies.get(level, {})

tone_ratios = data.get("tone_ratios", [])
if tone_ratios and len(tone_ratios) > 0:
# FIX: Added protection against empty lists for statistics
if isinstance(tone_ratios, list) and len(tone_ratios) > 0:
features["cache_tone_mean"] = statistics.mean(tone_ratios)
features["cache_tone_stdev"] = statistics.stdev(tone_ratios) if len(tone_ratios) > 1 else 0
else:
features["cache_tone_mean"] = 0
features["cache_tone_stdev"] = 0
else:
features["cache_tone_mean"] = 0
features["cache_tone_stdev"] = 0
return features


Expand Down
19 changes: 13 additions & 6 deletions node/auto_epoch_settler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
import sqlite3
import requests
import sys
import os
from datetime import datetime

# Configuration
NODE_URL = "http://localhost:8088"
DB_PATH = "/root/rustchain/rustchain_v2.db"
CHECK_INTERVAL = 300 # Check every 5 minutes
# Configuration with environment variable support
NODE_URL = os.environ.get("RC_NODE_URL", "http://localhost:8088")
DB_PATH = os.environ.get("RC_DB_PATH", "/root/rustchain/rustchain_v2.db")
CHECK_INTERVAL = int(os.environ.get("RC_SETTLE_INTERVAL", "300"))
API_KEY = os.environ.get("RC_ADMIN_KEY", "")
SLOTS_PER_EPOCH = 144

def get_current_slot():
Expand Down Expand Up @@ -85,12 +87,17 @@ def get_unsettled_epochs():
return []

def settle_epoch_via_api(epoch):
"""Settle an epoch using the node API"""
"""Settle an epoch using the node API with authentication"""
try:
headers = {}
if API_KEY:
headers["X-API-Key"] = API_KEY

resp = requests.post(
f"{NODE_URL}/rewards/settle",
json={"epoch": epoch},
timeout=30
headers=headers,
timeout=60
)

if resp.status_code == 200:
Expand Down
7 changes: 5 additions & 2 deletions node/bcos_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,12 @@ def generate_certificate(attestation: Dict[str, Any]) -> bytes:

# Table rows
pdf.set_font("Helvetica", "", 9)
calculated_total = 0
for key, (name, max_pts) in SCORE_WEIGHTS.items():
pts = breakdown.get(key, 0)
# FIX: Clamp points to maximum allowed to prevent misleading totals
pts = max(0, min(int(pts), max_pts))
calculated_total += pts
pct = pts / max_pts if max_pts > 0 else 0

if pct >= 0.7:
Expand All @@ -219,9 +223,8 @@ def generate_certificate(attestation: Dict[str, Any]) -> bytes:
# Total row
pdf.set_font("Helvetica", "B", 9)
pdf.set_fill_color(240, 240, 240)
total = sum(breakdown.values())
pdf.cell(90, 7, "TOTAL", border=1, fill=True, new_x="RIGHT")
pdf.cell(30, 7, str(total), border=1, fill=True, align="C", new_x="RIGHT")
pdf.cell(30, 7, str(calculated_total), border=1, fill=True, align="C", new_x="RIGHT")
pdf.cell(30, 7, "100", border=1, fill=True, align="C", new_x="RIGHT")
pdf.cell(40, 7, "", border=1, fill=True, new_x="LMARGIN", new_y="NEXT")

Expand Down
Loading