Hemithea/Blockchain3.node
0
1import streamlit as st2import hashlib3import json4import time5import requests6import os7 8# --- 1. SİBER GÜVENLİK VE YEREL BULUT BAĞLANTISI ---9BIN_ID = os.getenv("MY_JSONBIN_ID")10API_KEY = os.getenv("MY_JSONBIN_KEY")11 12if not BIN_ID or not API_KEY:13 st.error("🚨 Kritik Hata: MY_JSONBIN_ID veya MY_JSONBIN_KEY bulunamadı!")14 st.stop()15 16URL_READ = f"https://api.jsonbin.io/v3/b/{BIN_ID}/latest"17URL_WRITE = f"https://api.jsonbin.io/v3/b/{BIN_ID}"18 19# PRO PLAN KISITLAMASINI KALDIRAN ÖZEL HEADERS20HEADERS = {21 "X-Master-Key": API_KEY, 22 "Content-Type": "application/json",23 "X-Bin-Versioning": "false"24}25 26# --- 2. GİZLİ DİĞER DEPO ID'LERİNİ SECRETS'TAN ÇEKME ---27OTHER_BINS = []28bin_1 = os.getenv("OTHER_NODE_1_BIN")29bin_2 = os.getenv("OTHER_NODE_2_BIN")30 31if bin_1: OTHER_BINS.append(bin_1.strip())32if bin_2: OTHER_BINS.append(bin_2.strip())33 34# --- BLOCKCHAIN CORE ---35class Block:36 def __init__(self, index, timestamp, data, previous_hash, nonce=0, block_hash=None):37 self.index = int(index)38 self.timestamp = str(timestamp) # Karakter kaymasını önlemek için metne kilitledik39 self.data = data40 self.previous_hash = str(previous_hash)41 self.nonce = int(nonce)42 self.hash = block_hash if block_hash else self.calculate_hash()43 44 def calculate_hash(self):45 # ensure_ascii=True ile JSON formatı tüm dünyada standart hale getirildi46 serialized_data = json.dumps(self.data, sort_keys=True, ensure_ascii=True)47 block_string = f"{self.index}{self.timestamp}{serialized_data}{self.previous_hash}{self.nonce}"48 return hashlib.sha256(block_string.encode()).hexdigest()49 50class HemitheaBlockchain:51 def is_chain_valid(self, chain_to_validate):52 if not chain_to_validate or len(chain_to_validate) == 0:53 return True54 for i in range(1, len(chain_to_validate)):55 current = chain_to_validate[i]56 previous = chain_to_validate[i-1]57 58 current_block_obj = Block(59 current["index"], 60 current["timestamp"], 61 current["data"], 62 current["previous_hash"], 63 current["nonce"]64 )65 66 if current["hash"] != current_block_obj.calculate_hash():67 return False68 if current["previous_hash"] != previous["hash"]:69 return False70 return True71 72# --- DEPO İLETİŞİM FONKSİYONLARI ---73def fetch_my_chain():74 try:75 response = requests.get(URL_READ, headers=HEADERS, timeout=5)76 if response.status_code == 200:77 return response.json()["record"].get("chain", [])78 except:79 pass80 return []81 82def save_my_chain(chain_data):83 try:84 payload = {"chain": chain_data}85 requests.put(URL_WRITE, headers=HEADERS, json=payload, timeout=5)86 except:87 st.error("Kendi yerel bulut deponuza yazılamadı!")88 89# --- ARAYÜZ TASARIMI ---90st.set_page_config(page_title="Hemithea P2P Secure Hub", layout="wide")91st.title("🥛 Hemithea Gizli ve Dağıtık P2P Blockchain Düğümü")92 93current_node = st.sidebar.selectbox("Mevcut Düğüm Kimliği", ["Node 1", "Node 2", "Node 3"])94st.sidebar.markdown(f"**Durum:** {current_node} AKTİF")95st.sidebar.info(f"Bağlı Gizli Diğer Depo Sayısı: {len(OTHER_BINS)}")96 97# --- SİSTEM SIFIRLAMA BUTONU ---98st.sidebar.markdown("---")99st.sidebar.markdown("🛠️ **Sistem Bakım Paneli**")100if st.sidebar.button("🚨 Depoları Sıfırla ve Temizle"):101 save_my_chain([])102 st.sidebar.success("Bulut deponuz başarıyla temizlendi! Sayfayı yenileyin.")103 st.rerun()104 105blockchain_engine = HemitheaBlockchain()106my_chain = fetch_my_chain()107 108if len(my_chain) == 0:109 genesis = {110 "index": 0, 111 "timestamp": "1700000000.00", 112 "data": {"info": "Genesis - Fabrika Cikis", "status": "SABIT"}, 113 "previous_hash": "0", 114 "nonce": 0, 115 "hash": "00-genesis-hash"116 }117 my_chain.append(genesis)118 save_my_chain(my_chain)119 120col1, col2 = st.columns([1, 2])121 122with col1:123 st.header("IoT Veri Girişi")124 temp = st.slider("Kamyon Sıcaklık Sensörü (°C)", 0.0, 10.0, 2.1)125 route = st.text_input("Yol Durumu", "Bolu Otoban Seyri")126 127 if st.button("Kendi Depoma Blok Kaz"):128 status = "ZINCIR KIRILDI! ODEME IPTAL." if temp > 4.0 else "GUVENLI ONAYLI"129 latest_block = my_chain[-1]130 131 fixed_temp = round(float(temp), 2)132 133 new_block = {134 "index": len(my_chain),135 "timestamp": f"{time.time():.2f}", 136 "data": {"temperature": fixed_temp, "route": str(route), "status": str(status)},137 "previous_hash": str(latest_block["hash"]),138 "nonce": 0,139 "hash": ""140 }141 142 block_obj = Block(new_block["index"], new_block["timestamp"], new_block["data"], new_block["previous_hash"], new_block["nonce"])143 new_block["hash"] = block_obj.hash144 145 my_chain.append(new_block)146 save_my_chain(my_chain)147 st.success("Blok başarıyla kendi deponuza yazıldı!")148 st.rerun()149 150 st.write("---")151 st.header("P2P Konsensüs Odası")152 153 if st.button("Gizli Depolardan Veri Çek ve Konsensüs Sağla"):154 longest_chain = None155 max_length = len(my_chain)156 157 for other_bin_id in OTHER_BINS:158 try:159 target_url = f"https://api.jsonbin.io/v3/b/{other_bin_id}/latest"160 st.write(f"📡 {other_bin_id[:8]}... nolu gizli depoya bağlanılıyor...")161 162 response = requests.get(target_url, headers=HEADERS, timeout=5)163 164 if response.status_code == 200:165 data = response.json()166 other_chain = data["record"].get("chain", [])167 other_length = len(other_chain)168 169 st.write(f"✅ Depo bağlantısı başarılı! Doğrulanan zincir uzunluğu: {other_length}")170 171 if other_length > max_length:172 if blockchain_engine.is_chain_valid(other_chain):173 max_length = other_length174 longest_chain = other_chain175 st.write(f"⭐ Ağda daha uzun bir aday bulundu! (Uzunluk: {other_length})")176 else:177 st.warning("⚠️ Diğer depodaki zincir kriptografik validasyon testini geçemedi!")178 else:179 st.warning(f"⚠️ Depo {other_bin_id[:8]}... hata döndürdü. Kod: {response.status_code}")180 181 except Exception as e:182 st.error(f"❌ Bağlantı koptu! Hata: {str(e)}")183 continue184 185 if longest_chain:186 save_my_chain(longest_chain)187 st.success(f"🚨 KONSENSÜS SAĞLANDI! Yerel defteriniz {max_length} blokluk yeni zincirle güncellendi.")188 st.rerun()189 else:190 st.info("Harika! Şu an ağdaki en güncel ve en uzun zincire sahipsiniz.")191 192with col2:193 st.header("🔒 Bu Düğümün Özel Defteri (Local Ledger)")194 for block in reversed(my_chain):195 is_error = float(block["data"].get("temperature", 0)) > 4.0 or "ZINCIR" in str(block["data"].get("status"))196 icon = "🚨" if is_error else "📦"197 with st.expander(f"{icon} Blok #{block['index']}", expanded=True):198 st.json(block)199 