NAC_Blockchain/nvm_v2/nvm-l1/nrpc-server.py

243 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
NAC NRPC3.0 服务器Python实现
提供HTTP RPC和WebSocket接口
"""
import json
import asyncio
import websockets
from http.server import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
import time
class NRPCHandler(BaseHTTPRequestHandler):
"""NRPC HTTP处理器"""
def do_POST(self):
"""处理POST请求"""
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
try:
request = json.loads(post_data.decode('utf-8'))
response = self.handle_rpc_request(request)
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
self.wfile.write(json.dumps(response).encode('utf-8'))
except Exception as e:
self.send_error(500, str(e))
def do_OPTIONS(self):
"""处理OPTIONS请求CORS预检"""
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
def handle_rpc_request(self, request):
"""处理RPC请求"""
method = request.get('method', '')
params = request.get('params', [])
request_id = request.get('id', 1)
# 模拟响应
if method == 'nrpc_getChainInfo':
result = {
'chainId': 20260131,
'chainName': 'NAC Testnet',
'consensus': 'CBPP',
'blockHeight': 850,
'tps': 3000,
'activeNodes': 1
}
elif method == 'nrpc_getBlockByNumber':
result = {
'epoch': 0,
'round': 850,
'branch': 0,
'hash': '0x711d16878e525fd1',
'timestamp': int(time.time() * 1000),
'transactions': [],
'producer': '0x' + '02' * 33
}
elif method == 'nrpc_getBalance':
result = {
'address': params[0] if params else '0x' + '1' * 40,
'balance': '1000000000000000000000',
'unit': 'wei'
}
elif method == 'nrpc_getAssetToken':
result = {
'tokenId': params[0] if params else '0x9f2462e690ea37e9',
'assetType': 'RealEstate',
'owner': '0x' + '1' * 40,
'valuationUSD': 5000000,
'status': 'Active'
}
elif method == 'nrpc_getEquityToken':
result = {
'contractAddress': params[0] if params else '0x40ee5fcd27e00259',
'name': 'Property Equity Token',
'symbol': 'PET',
'totalSupply': '1000000000000000000000000',
'holders': 100
}
elif method == 'nrpc_getStakingInfo':
result = {
'stakingId': params[0] if params else '0xed12d6f40e171622',
'stakedAmount': '800000000000000000000000',
'stakingRatio': 0.8,
'issuedTokens': '1000000000000000000000000'
}
else:
return {
'jsonrpc': '2.0',
'id': request_id,
'error': {
'code': -32601,
'message': f'Method not found: {method}'
}
}
return {
'jsonrpc': '2.0',
'id': request_id,
'result': result
}
def log_message(self, format, *args):
"""自定义日志"""
print(f"[NRPC HTTP] {format % args}")
async def websocket_handler(websocket, path):
"""WebSocket处理器"""
print(f"[NRPC WS] 新连接: {websocket.remote_address}")
try:
async for message in websocket:
try:
request = json.loads(message)
method = request.get('method', '')
if method == 'nrpc_subscribe':
# 订阅请求
subscription_type = request.get('params', [])[0] if request.get('params') else 'newBlocks'
subscription_id = f"sub_{int(time.time() * 1000)}"
response = {
'jsonrpc': '2.0',
'id': request.get('id', 1),
'result': subscription_id
}
await websocket.send(json.dumps(response))
# 开始推送数据
asyncio.create_task(push_subscription_data(websocket, subscription_id, subscription_type))
elif method == 'nrpc_unsubscribe':
# 取消订阅
response = {
'jsonrpc': '2.0',
'id': request.get('id', 1),
'result': True
}
await websocket.send(json.dumps(response))
else:
# 普通RPC请求
handler = NRPCHandler(None, None, None)
result = handler.handle_rpc_request(request)
await websocket.send(json.dumps(result))
except json.JSONDecodeError:
error_response = {
'jsonrpc': '2.0',
'error': {
'code': -32700,
'message': 'Parse error'
}
}
await websocket.send(json.dumps(error_response))
except websockets.exceptions.ConnectionClosed:
print(f"[NRPC WS] 连接关闭: {websocket.remote_address}")
async def push_subscription_data(websocket, subscription_id, subscription_type):
"""推送订阅数据"""
try:
while True:
await asyncio.sleep(5) # 每5秒推送一次
if subscription_type == 'newBlocks':
data = {
'jsonrpc': '2.0',
'method': 'nrpc_subscription',
'params': {
'subscription': subscription_id,
'result': {
'epoch': 0,
'round': int(time.time()) % 1000,
'branch': 0,
'hash': f"0x{int(time.time()):016x}",
'timestamp': int(time.time() * 1000)
}
}
}
elif subscription_type == 'balance':
data = {
'jsonrpc': '2.0',
'method': 'nrpc_subscription',
'params': {
'subscription': subscription_id,
'result': {
'address': '0x' + '1' * 40,
'balance': str(int(time.time() * 1000000000000000000)),
'timestamp': int(time.time() * 1000)
}
}
}
else:
continue
await websocket.send(json.dumps(data))
print(f"[NRPC WS] 推送数据: {subscription_type}")
except websockets.exceptions.ConnectionClosed:
print(f"[NRPC WS] 订阅连接关闭: {subscription_id}")
def start_http_server():
"""启动HTTP服务器"""
server = HTTPServer(('0.0.0.0', 18545), NRPCHandler)
print("✅ NRPC HTTP服务器启动: http://0.0.0.0:18545")
server.serve_forever()
async def start_websocket_server():
"""启动WebSocket服务器"""
async with websockets.serve(websocket_handler, '0.0.0.0', 18546):
print("✅ NRPC WebSocket服务器启动: ws://0.0.0.0:18546")
await asyncio.Future() # 保持运行
def main():
"""主函数"""
print("========================================")
print("NAC NRPC3.0 服务器")
print("版本: 1.0.0")
print("协议: NRPC3.0 (神经网络区块链协议)")
print("========================================")
print()
# 启动HTTP服务器在单独线程中
http_thread = Thread(target=start_http_server, daemon=True)
http_thread.start()
# 启动WebSocket服务器在主线程中
asyncio.run(start_websocket_server())
if __name__ == '__main__':
main()