243 lines
8.6 KiB
Python
243 lines
8.6 KiB
Python
#!/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()
|