Spaces:
Running
Running
Update src/trust_agent.py
Browse files- src/trust_agent.py +73 -44
src/trust_agent.py
CHANGED
|
@@ -161,72 +161,101 @@ class AgentTrust:
|
|
| 161 |
except: return "IPFS_Fail"
|
| 162 |
|
| 163 |
# --- CORE BLOCKCHAIN LOGIC ---
|
| 164 |
-
def stamp_on_chain(self, payload
|
| 165 |
-
"""
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
try:
|
| 169 |
-
|
| 170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
return False
|
| 172 |
|
| 173 |
-
#
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
)
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
|
| 187 |
-
#
|
| 188 |
-
|
| 189 |
-
nonce = self.w3.eth.get_transaction_count(account.address)
|
| 190 |
|
| 191 |
-
# 4. Build the Transaction targeting 'proposeEntry'
|
| 192 |
tx = contract.functions.proposeEntry(
|
| 193 |
phrase,
|
| 194 |
dialect,
|
| 195 |
-
|
| 196 |
license_type
|
| 197 |
).build_transaction({
|
| 198 |
-
'
|
|
|
|
|
|
|
| 199 |
'nonce': nonce,
|
| 200 |
-
'gas': 3000000, # Increased gas limit to prevent Out-Of-Gas reverts
|
| 201 |
-
'gasPrice': 0,
|
| 202 |
-
'chainId': self.config.PURECHAIN_ID
|
| 203 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
# 6. Wait for Confirmation
|
| 211 |
-
print(f"⏳ Waiting for confirmation on TX: {tx_hash.hex()}...")
|
| 212 |
-
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
|
| 213 |
|
| 214 |
-
# 7. Check if it Succeeded or Reverted
|
| 215 |
if receipt.status == 1:
|
| 216 |
-
print(f"
|
| 217 |
-
|
| 218 |
-
# 🟢 FIX: Trigger the local history logger and HF sync!
|
| 219 |
-
self.log_mint_to_history(phrase, dialect, tx_hash.hex(), receipt.blockNumber, ipfs_cid)
|
| 220 |
|
|
|
|
|
|
|
|
|
|
| 221 |
return True
|
| 222 |
else:
|
| 223 |
-
print(
|
| 224 |
-
print("Make sure your wallet address is registered via 'registerResearcher' first!")
|
| 225 |
return False
|
| 226 |
-
|
| 227 |
except Exception as e:
|
| 228 |
-
|
|
|
|
|
|
|
| 229 |
return False
|
|
|
|
|
|
|
| 230 |
|
| 231 |
def log_mint_to_history(self, utterance, dialect, tx_hash, block_num, cid):
|
| 232 |
history_file = "/app/minted_history.csv"
|
|
|
|
| 161 |
except: return "IPFS_Fail"
|
| 162 |
|
| 163 |
# --- CORE BLOCKCHAIN LOGIC ---
|
| 164 |
+
def stamp_on_chain(self, payload):
|
| 165 |
+
"""
|
| 166 |
+
Hashes the validated sociolinguistic data and mints it to the Purechain ledger
|
| 167 |
+
using the PureConvo contract's proposeEntry function.
|
| 168 |
+
"""
|
| 169 |
+
import json
|
| 170 |
+
import hashlib
|
| 171 |
+
import os
|
| 172 |
+
from web3 import Web3
|
| 173 |
+
from web3.middleware import geth_poa_middleware
|
| 174 |
+
|
| 175 |
+
print("\n" + "="*40)
|
| 176 |
+
print("⛓️ INITIATING PURECHAIN MINTING SEQUENCE")
|
| 177 |
|
| 178 |
try:
|
| 179 |
+
# 1. Load Environment Variables (Updated to match your secrets)
|
| 180 |
+
rpc_url = os.environ.get("PURECHAIN_RPC_URL")
|
| 181 |
+
private_key = os.environ.get("PRIVATE_KEY")
|
| 182 |
+
contract_address = os.environ.get("PURECHAIN_CONTRACT_ADDRESS")
|
| 183 |
+
|
| 184 |
+
if not all([rpc_url, private_key, contract_address]):
|
| 185 |
+
print("⚠️ Purechain skipped: Missing RPC_URL, PRIVATE_KEY, or PURECHAIN_CONTRACT_ADDRESS.")
|
| 186 |
return False
|
| 187 |
|
| 188 |
+
# 2. Establish Network Connection
|
| 189 |
+
w3 = Web3(Web3.HTTPProvider(rpc_url))
|
| 190 |
+
w3.middleware_onion.inject(geth_poa_middleware, layer=0) # PoA compatibility
|
| 191 |
+
|
| 192 |
+
if not w3.is_connected():
|
| 193 |
+
print("🔴 Purechain connection failed. Network may be offline.")
|
| 194 |
+
return False
|
| 195 |
+
|
| 196 |
+
account = w3.eth.account.from_key(private_key)
|
| 197 |
+
wallet_address = account.address
|
| 198 |
+
print(f"✅ Authenticated as Operator: {wallet_address}")
|
| 199 |
+
|
| 200 |
+
# 3. Cryptographic Hashing of the Data
|
| 201 |
+
# We hash the full JSON payload to use as our "IPFS CID" / Data Hash proof
|
| 202 |
+
payload_str = json.dumps(payload, sort_keys=True)
|
| 203 |
+
data_hash = hashlib.sha256(payload_str.encode('utf-8')).hexdigest()
|
| 204 |
+
print(f"🔒 Payload SHA-256 Proof: {data_hash}")
|
| 205 |
+
|
| 206 |
+
# 4. Load the Smart Contract using your config.py ABI
|
| 207 |
+
# Ensure your config is imported/available in trust_agent.py
|
| 208 |
+
contract = w3.eth.contract(address=contract_address, abi=self.config.CONTRACT_ABI)
|
| 209 |
+
|
| 210 |
+
# 5. Extract values for the proposeEntry parameters
|
| 211 |
+
# function proposeEntry(string _phrase, string _dialect, string _ipfsCid, string _license)
|
| 212 |
+
phrase = payload.get("original", "Unknown Utterance")
|
| 213 |
+
dialect = payload.get("dialect", "Unknown Dialect")
|
| 214 |
+
license_type = "CC-BY-4.0 (Open Research)" # Academic open data license
|
| 215 |
|
| 216 |
+
# 6. Build the Transaction
|
| 217 |
+
nonce = w3.eth.get_transaction_count(wallet_address)
|
|
|
|
| 218 |
|
|
|
|
| 219 |
tx = contract.functions.proposeEntry(
|
| 220 |
phrase,
|
| 221 |
dialect,
|
| 222 |
+
data_hash,
|
| 223 |
license_type
|
| 224 |
).build_transaction({
|
| 225 |
+
'chainId': w3.eth.chain_id,
|
| 226 |
+
'gas': 2000000,
|
| 227 |
+
'gasPrice': w3.eth.gas_price,
|
| 228 |
'nonce': nonce,
|
|
|
|
|
|
|
|
|
|
| 229 |
})
|
| 230 |
+
|
| 231 |
+
# 7. Sign and Broadcast
|
| 232 |
+
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
|
| 233 |
+
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
|
| 234 |
+
hex_hash = w3.to_hex(tx_hash)
|
| 235 |
|
| 236 |
+
print(f"🚀 Transaction Broadcasted! TX Hash: {hex_hash}")
|
| 237 |
+
|
| 238 |
+
# 8. Wait for Confirmation
|
| 239 |
+
receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
|
|
|
|
| 241 |
if receipt.status == 1:
|
| 242 |
+
print(f"💎 SUCCESS: Entry '{phrase[:15]}...' irreversibly minted in Block {receipt.blockNumber}")
|
|
|
|
|
|
|
|
|
|
| 243 |
|
| 244 |
+
# OPTIONAL: Save the receipt to your Gradio Transaction History tab
|
| 245 |
+
if hasattr(self, '_log_transaction_history'):
|
| 246 |
+
self._log_transaction_history(payload, hex_hash, receipt.blockNumber)
|
| 247 |
return True
|
| 248 |
else:
|
| 249 |
+
print("⚠️ Transaction reverted by the EVM. (Check if wallet is registered)")
|
|
|
|
| 250 |
return False
|
| 251 |
+
|
| 252 |
except Exception as e:
|
| 253 |
+
import traceback
|
| 254 |
+
print(f"\n❌ SMART CONTRACT ERROR ❌\n{e}")
|
| 255 |
+
traceback.print_exc()
|
| 256 |
return False
|
| 257 |
+
finally:
|
| 258 |
+
print("="*40 + "\n")
|
| 259 |
|
| 260 |
def log_mint_to_history(self, utterance, dialect, tx_hash, block_num, cid):
|
| 261 |
history_file = "/app/minted_history.csv"
|