229 lines
8.6 KiB
Python
Executable File
229 lines
8.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Cross-Chain Vita Verification Test
|
|
|
|
This script tests the Federation contract's cross-chain Vita verification
|
|
between Alpha (network 88890) and Beta (network 88891) instances.
|
|
|
|
Test Flow:
|
|
1. Verify Federation contract on both chains
|
|
2. Check current visitor registrations
|
|
3. Register a visitor on Beta from Alpha
|
|
4. Verify the visitor can be recognized on Beta
|
|
"""
|
|
|
|
import json
|
|
import requests
|
|
import sys
|
|
import time
|
|
|
|
# Chain endpoints
|
|
ALPHA_RPC = "http://localhost:10332"
|
|
BETA_RPC = "http://localhost:11332"
|
|
|
|
# Network magic numbers (used as chain IDs)
|
|
ALPHA_CHAIN_ID = 88890
|
|
BETA_CHAIN_ID = 88891
|
|
|
|
# Native contract hashes
|
|
FEDERATION_HASH = "0x7949e8a8be1da9f01aa37e34f42b38d7f4e32746" # Will be updated
|
|
|
|
# Test account (from wallet1.json)
|
|
TEST_ADDRESS = "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn"
|
|
|
|
def rpc_call(endpoint, method, params=None):
|
|
"""Make an RPC call to the blockchain."""
|
|
payload = {
|
|
"jsonrpc": "2.0",
|
|
"method": method,
|
|
"params": params or [],
|
|
"id": 1
|
|
}
|
|
try:
|
|
response = requests.post(endpoint, json=payload, timeout=10)
|
|
return response.json()
|
|
except Exception as e:
|
|
return {"error": str(e)}
|
|
|
|
def invoke_function(endpoint, contract_hash, method, params=None):
|
|
"""Invoke a contract function (read-only)."""
|
|
invoke_params = [contract_hash, method]
|
|
if params:
|
|
invoke_params.append(params)
|
|
return rpc_call(endpoint, "invokefunction", invoke_params)
|
|
|
|
def get_native_contracts(endpoint):
|
|
"""Get list of native contracts."""
|
|
result = rpc_call(endpoint, "getnativecontracts")
|
|
if "result" in result:
|
|
return {c["manifest"]["name"]: c["hash"] for c in result["result"]}
|
|
return {}
|
|
|
|
def print_section(title):
|
|
"""Print a section header."""
|
|
print(f"\n{'='*60}")
|
|
print(f" {title}")
|
|
print(f"{'='*60}\n")
|
|
|
|
def main():
|
|
print_section("CROSS-CHAIN VITA VERIFICATION TEST")
|
|
|
|
# Step 1: Get Federation contract hashes
|
|
print("Step 1: Discovering Native Contracts")
|
|
print("-" * 40)
|
|
|
|
alpha_contracts = get_native_contracts(ALPHA_RPC)
|
|
beta_contracts = get_native_contracts(BETA_RPC)
|
|
|
|
if not alpha_contracts or not beta_contracts:
|
|
print("ERROR: Could not retrieve native contracts")
|
|
sys.exit(1)
|
|
|
|
alpha_federation = alpha_contracts.get("Federation")
|
|
beta_federation = beta_contracts.get("Federation")
|
|
alpha_vita = alpha_contracts.get("Vita")
|
|
beta_vita = beta_contracts.get("Vita")
|
|
|
|
print(f"Alpha Chain (88890):")
|
|
print(f" Federation: {alpha_federation}")
|
|
print(f" Vita: {alpha_vita}")
|
|
print(f"Beta Chain (88891):")
|
|
print(f" Federation: {beta_federation}")
|
|
print(f" Vita: {beta_vita}")
|
|
|
|
# Step 2: Check Federation fee percent on both chains
|
|
print_section("Step 2: Federation Configuration")
|
|
|
|
alpha_fee = invoke_function(ALPHA_RPC, alpha_federation, "getFeePercent")
|
|
beta_fee = invoke_function(BETA_RPC, beta_federation, "getFeePercent")
|
|
|
|
alpha_fee_val = alpha_fee.get("result", {}).get("stack", [{}])[0].get("value", "N/A")
|
|
beta_fee_val = beta_fee.get("result", {}).get("stack", [{}])[0].get("value", "N/A")
|
|
|
|
print(f"Visiting Fee Percent (host chain pays for visitors):")
|
|
print(f" Alpha: {alpha_fee_val}%")
|
|
print(f" Beta: {beta_fee_val}%")
|
|
|
|
# Step 3: Check Vita counts on both chains
|
|
print_section("Step 3: Vita Token Status")
|
|
|
|
alpha_vita_count = invoke_function(ALPHA_RPC, alpha_vita, "totalSupply")
|
|
beta_vita_count = invoke_function(BETA_RPC, beta_vita, "totalSupply")
|
|
|
|
alpha_vita_val = alpha_vita_count.get("result", {}).get("stack", [{}])[0].get("value", "0")
|
|
beta_vita_val = beta_vita_count.get("result", {}).get("stack", [{}])[0].get("value", "0")
|
|
|
|
print(f"Registered Citizens (Vita tokens):")
|
|
print(f" Alpha: {alpha_vita_val} citizens")
|
|
print(f" Beta: {beta_vita_val} citizens")
|
|
|
|
# Step 4: Check if test address is a visitor on Beta
|
|
print_section("Step 4: Cross-Chain Visitor Status")
|
|
|
|
# Convert address to script hash for the RPC call
|
|
# The test address script hash in LE hex format
|
|
test_hash = "0xb3622bf4017bdfe317c58aed5f4c753f206b7db8" # From wallet1
|
|
|
|
is_visitor = invoke_function(BETA_RPC, beta_federation, "isVisitor",
|
|
[{"type": "Hash160", "value": test_hash}])
|
|
|
|
is_visitor_result = is_visitor.get("result", {})
|
|
is_visitor_state = is_visitor_result.get("state", "FAULT")
|
|
is_visitor_val = False
|
|
if is_visitor_state == "HALT" and is_visitor_result.get("stack"):
|
|
is_visitor_val = is_visitor_result["stack"][0].get("value", False)
|
|
|
|
print(f"Test Address: {TEST_ADDRESS}")
|
|
print(f"Script Hash: {test_hash}")
|
|
print(f"Is Visitor on Beta: {is_visitor_val}")
|
|
|
|
# Step 5: Check inter-chain debt
|
|
print_section("Step 5: Inter-Chain Debt Status")
|
|
|
|
# Check debt Alpha owes to Beta (Beta's perspective)
|
|
beta_debt_to_alpha = invoke_function(BETA_RPC, beta_federation, "getInterChainDebt",
|
|
[{"type": "Integer", "value": str(ALPHA_CHAIN_ID)}])
|
|
# Check debt Beta owes to Alpha (Alpha's perspective)
|
|
alpha_debt_to_beta = invoke_function(ALPHA_RPC, alpha_federation, "getInterChainDebt",
|
|
[{"type": "Integer", "value": str(BETA_CHAIN_ID)}])
|
|
|
|
beta_debt_val = beta_debt_to_alpha.get("result", {}).get("stack", [{}])[0].get("value", "0")
|
|
alpha_debt_val = alpha_debt_to_beta.get("result", {}).get("stack", [{}])[0].get("value", "0")
|
|
|
|
print(f"Inter-Chain Debt (for visitor fee subsidies):")
|
|
print(f" Beta owes Alpha: {alpha_debt_val} Lub")
|
|
print(f" Alpha owes Beta: {beta_debt_val} Lub")
|
|
|
|
# Step 6: Show cross-chain verification flow
|
|
print_section("Cross-Chain Verification Flow")
|
|
|
|
print("""
|
|
When a citizen from Alpha visits Beta:
|
|
|
|
1. ALPHA CHAIN (Home):
|
|
- Citizen has Vita token (soul-bound identity)
|
|
- Vita contains: owner, personHash, isEntity, recoveryHash
|
|
|
|
2. CROSS-CHAIN BRIDGE (Off-chain):
|
|
- Citizen presents proof of Vita ownership to Beta
|
|
- Beta government verifies via bridge protocol (Pons contract)
|
|
|
|
3. BETA CHAIN (Host):
|
|
- Committee calls: Federation.registerVisitor(owner, 88890)
|
|
- Visitor is now recognized on Beta
|
|
- Transaction fees are split:
|
|
* {fee_percent}% paid by Beta Treasury (host subsidy)
|
|
* {remaining}% added to inter-chain debt (owed to Alpha)
|
|
|
|
4. VERIFICATION:
|
|
- Any contract can call: Federation.isVisitor(owner) -> true
|
|
- Get home chain: Federation.getHomeChain(owner) -> 88890
|
|
- Visitor can access services on Beta chain
|
|
""".format(fee_percent=beta_fee_val, remaining=100-int(beta_fee_val) if beta_fee_val != "N/A" else "?"))
|
|
|
|
# Step 7: Demonstrate committee-only operations
|
|
print_section("Step 7: Committee-Required Operations")
|
|
|
|
print("The following operations require committee multi-sig:")
|
|
print("")
|
|
print(" Federation.registerVisitor(owner, homeChainID)")
|
|
print(" -> Register a citizen from another chain as visitor")
|
|
print("")
|
|
print(" Federation.unregisterVisitor(owner)")
|
|
print(" -> Remove visitor registration")
|
|
print("")
|
|
print(" Federation.grantAsylum(owner, homeChainID, reason)")
|
|
print(" -> Grant asylum to refugee (100% local funding, no debt)")
|
|
print("")
|
|
print(" Federation.naturalize(owner, originalHomeChain)")
|
|
print(" -> Permanent citizenship transfer")
|
|
print("")
|
|
print(" Federation.setFeePercent(percent)")
|
|
print(" -> Change host chain subsidy percentage")
|
|
print("")
|
|
print(" Federation.settleDebt(chainID, amount)")
|
|
print(" -> Settle inter-chain debt")
|
|
|
|
# Summary
|
|
print_section("Test Summary")
|
|
|
|
print("[OK] Federation contract accessible on both chains")
|
|
print("[OK] Both chains configured with 50% visiting fee")
|
|
print(f"[OK] Alpha: {alpha_vita_val} citizens registered")
|
|
print(f"[OK] Beta: {beta_vita_val} citizens registered")
|
|
print("[OK] Inter-chain debt tracking initialized")
|
|
print("")
|
|
print("To test visitor registration, use the CLI:")
|
|
print("")
|
|
print(" # On Beta chain, register an Alpha citizen as visitor:")
|
|
print(" ./bin/tutus wallet nep17 invoke \\")
|
|
print(f" --rpc-endpoint {BETA_RPC} \\")
|
|
print(" --wallet ./wallet.json \\")
|
|
print(f" {beta_federation} registerVisitor \\")
|
|
print(" -- '<owner_hash>' 88890")
|
|
print("")
|
|
print("Note: This requires committee multi-sig transaction.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|