diff --git a/.gitignore b/.gitignore index a1c2a23..d2fa3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/build # Compiled class file *.class diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/make.bat b/make.bat new file mode 100755 index 0000000..9534b01 --- /dev/null +++ b/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/source/ContractAPI.rst b/source/ContractAPI.rst new file mode 100644 index 0000000..2c26bfa --- /dev/null +++ b/source/ContractAPI.rst @@ -0,0 +1,4636 @@ +BDContract SDK +============== + +除使用可视化的智能合约在线IDE外,用户还可使用WebSocket接口、Http接口、Bash接口来启动和运行合约. + +-------------- + +WebSocketSDK下载与安装 +---------------------- + +合约SDK提供javascript版本与java版本的客户端。 + +java客户端的下载链接为:\ `java +source <./_static/BDWareJavaClient.zip>`__\ 和\ `jar <./_static/BDWareConfigTool.zip>`__ +可参考java_source下的README.md及测试用例。 + +javascript的下载链接为:\ `js SDK <./_static/js/createWS.js>`__ +内置的SM2加密库链接:\ `sm2 SDK <./_static/js/sm2.js>`__ + +建立连接 +~~~~~~~~ + +建立与节点服务器之间的WebSocket连接. + +参数 +^^^^ + ++---------+------------------------------------------------------------+ +| 字段 | 值 | ++=========+============================================================+ +| url | 建立WebSocket的服务器URL. 使用\ ``http``\ 协议时, | +| | 前缀为\ ``ws://``, | +| | 如\ ``"ws://localhost:1717/SCIDE/SCExecutor"``; | +| | 使用\ ``https``\ 协议时, 前缀为\ ``wss://`` | ++---------+------------------------------------------------------------+ +| msgHand | 收到服务器WebSocket回复后的回调函数, 用户可自行编写, | +| ler | 也可参考下面提供的示例 | ++---------+------------------------------------------------------------+ + +请求示例 +^^^^^^^^ + +.. code:: javascript + + var url = "ws://127.0.0.1:1717/SCIDE/SCExecutor";//与Slave节点建立连接 + //var url = "ws://127.0.0.1:1718/NodeCenterWS";//与Manager节点建立连接 + var msgHandler = function(m){ + console.log("recmsg:"); + console.log(m); + }; + var onOpenHandler=undefined; + wssocket = createWssocket(url,onOpenHandler,msgHandler); + +返回结果示例 +^^^^^^^^^^^^ + +:: + + { + receiveSeg: [Function (anonymous)], + isSending: false, + sendList: [], + monitor: [Function (anonymous)], + send: [Function (anonymous)], + sendNextSegment: [Function (anonymous)], + isOpen: [Function (anonymous)] + } + +ping +~~~~ + +``ping``\ 服务器测试 + +.. _参数-1: + +参数 +^^^^ + +====== ==== +字段 值 +====== ==== +action ping +====== ==== + +.. _请求示例-1: + +请求示例 +^^^^^^^^ + +:: + + var request = {}; + request.action = "ping"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-1: + +返回结果示例 +^^^^^^^^^^^^ + +:: + + { + "action":"pong" + } + +登录 +~~~~ + +使用Websocket接口调用需要权限的接口时,不论是连接CenterPortal还是NodePortal必须先\ **登录**\ 。 +登录的流程有3步: + +- 客户端向服务端建立连接,连接建立完成后发送{“action”:“getSessionID”}(可在onOpenHandler中实现) +- 服务端收到请求后,会向客户端返回类似{“action”:“onGetSessionID”,“session”:“-4959947809200104526_session”}的结果 +- 客户端收到onGetSessionID后,会使用本地的公私钥对sessionID进行签名,并调用login接口 +- 服务端会返回onLogin的结果,data字段返回的是该公钥对应的角色。 + +-------------- + +用户角色划分 +------------ + +合约节点的角色划分 +~~~~~~~~~~~~~~~~~~ + +在合约节点(NodePortal.html)中分为NodeManager/ContractProvider/ContractInstanceManager/ContractUser四类角色。 + +======================= ========================================================================== +角色 说明 +======================= ========================================================================== +NodeManager 该节点的管理者,拥有用户管理、节点配置等权限 +ContractProvider 拥有编辑合约、开发合约代码、运行调试等权限 +ContractInstanceManager 拥有启、停合约实例、配置合约实例IO等权限 +ContractUser 拥有查看合约实例列表、调用合约等权限 +Anonymous 匿名用户,可以调用合约,可以申请成为ContractProvider/InstanceManager等角色 +======================= ========================================================================== + +=============================== ==================== ========================================= +接口 说明 角色 +=============================== ==================== ========================================= +changeDumpPeriod 设置备份周期 ContractInstanceManager; +createLedger 创建账本 ContractInstanceManager; +dumpContract 手动备份 ContractInstanceManager; +deleteMemoryFile 删除镜像 ContractInstanceManager; +forkContract 迁移合约 ContractInstanceManager; +getDumpPeriod 获取备份周期 ContractInstanceManager; +killAllContract 停止全部实例 ContractInstanceManager; +killContractProcess 停止某一实例 ContractInstanceManager; +listMemoryFiles 列取某一实例的镜像 ContractInstanceManager; +loadMemory 加载镜像 ContractInstanceManager; +queryContractInstanceDOI 查询合约实例信息 ContractInstanceManager; +rebuildHashIndex ContractInstanceManager; +setPermission ContractProvider;ContractInstanceManager; +startContract 启动合约 ContractInstanceManager; +startContractBatched 废弃 ContractInstanceManager; +startContractByYPK 启动合约 ContractInstanceManager; +startContractInTempZips 废弃 ContractInstanceManager; +startContractConfig 启动合约(集群模式) ContractInstanceManager; +updateContract ContractInstanceManager; +connectTo 连接合约实例输出流 ContractInstanceManager;ContractUser; +countContractLogGroupByAction ContractInstanceManager;ContractUser; +countContractLogGroupByCategory ContractInstanceManager;ContractUser; +getLastLog 查询日志 ContractInstanceManager;ContractUser; +getLog 查询日志 ContractInstanceManager;ContractUser; +getLogSize 查询日志 ContractInstanceManager;ContractUser; +listAllContractProcess ContractInstanceManager;ContractUser; +listContractProcess 查询合约实例列表 ContractInstanceManager;ContractUser; +listLeakContractProcess ContractInstanceManager;ContractUser; +queryContractLogByDate ContractInstanceManager;ContractUser; +queryContractLogByKey ContractInstanceManager;ContractUser; +queryContractLogByOffset ContractInstanceManager;ContractUser; +queryContractLogDetail ContractInstanceManager;ContractUser; +queryContractLogSize ContractInstanceManager;ContractUser; +queryNodeLogByDate ContractInstanceManager;ContractUser; +queryNodeLogByOffset ContractInstanceManager;ContractUser; +queryNodeLogSize ContractInstanceManager;ContractUser; +rebuildContractLogIndex ContractInstanceManager;ContractUser; +rebuildNodeLogIndex ContractInstanceManager;ContractUser; +changePublic ContractProvider; +createFile 新建文件 ContractProvider; +deleteFile 删除文件 ContractProvider; +distributeContract ContractProvider; +downloadContract ContractProvider; +downloadContractFromOtherHost ContractProvider; +generateAnnotationSample ContractProvider; +generateAppDataAnalysis ContractProvider; +generateAppDataSource ContractProvider; +generateBDCoinEventProject ContractProvider; +generateBDCoinProject ContractProvider; +generateBiddingExample ContractProvider; +generateCSVProject ContractProvider; +generateContractExecutor ContractProvider; +generateDAC4BDOA ContractProvider; +generateDAC4BDOA_persist ContractProvider; +generateDACSample ContractProvider; +generateEmptyProject ContractProvider; +generateEventPublisher ContractProvider; +generateEventSubscriber ContractProvider; +generateGasExample ContractProvider; +generateHello ContractProvider; +generateHttpExample ContractProvider; +generateIncentives ContractProvider; +generateJSONExample ContractProvider; +generateLedgerExample ContractProvider; +generateLedgerProject ContractProvider; +generateLicenceManager ContractProvider; +generateLoggerExample ContractProvider; +generateMySQLExample ContractProvider; +generateMySQLProject ContractProvider; +generatePostgreSQLSample ContractProvider; +generateReadme ContractProvider; +generateRenderSample ContractProvider; +generateRocksDBSample ContractProvider; +generateSM2Example ContractProvider; +generateStaticResource ContractProvider; +generateTFLinux ContractProvider; +generategenerateTFMac ContractProvider; +getProject ContractProvider; +getTemplateList ContractProvider; +importContractInstanceCodeByDOI ContractProvider; +listFile ContractProvider; +listProject ContractProvider; +listProjectPermission ContractProvider; +listProjects ContractProvider; +renameFile ContractProvider; +saveFile ContractProvider; +startContractAsDebug ContractProvider; +uploadFile ContractProvider; +compile ContractProvider;ContractInstanceManager; +evaluates ContractProvider;ContractInstanceManager; +executeContractP2PTrustfully ContractProvider;ContractInstanceManager; +getCodeByID 查询代码 ContractProvider;ContractInstanceManager; +getControlFlowByFileName ContractProvider;ContractInstanceManager; +getGasValue ContractProvider;ContractInstanceManager; +listCompiledFiles ContractProvider;ContractInstanceManager; +queryContractResourceInfo ContractProvider;ContractInstanceManager; +queryFreeResourceInfo ContractProvider;ContractInstanceManager; +staticVerifyContract ContractProvider;ContractInstanceManager; +writeDyjs ContractProvider;ContractInstanceManager; +authNodeRole 授权角色 NodeManager; +changeBDledger 修改账本配置 NodeManager; +changeIpPort NodeManager; +changeNodeCenter 修改集群地址 NodeManager; +changeNodeName NodeManager; +changeIpPort NodeManager; +changeDOIPConfig NodeManager; +changeYJSPath NodeManager; +countNodeLogGroupByCategory NodeManager; +countRole NodeManager; +deleteRole NodeManager; +downloadUUID 废弃 NodeManager; +getEncodedUUID 废弃 NodeManager; +getPeerID NodeManager; +listAllAuthRole NodeManager; +listNodeInfos NodeManager; +listUnAuthRole NodeManager; +loadConfig NodeManager; +loadNodeConfig NodeManager; +lockEdit NodeManager; +unlockEdit NodeManager; +updateConfig NodeManager; +uploadLicence NodeManager; +applyNodeRole 申请角色 任意角色 +executeContract 调用合约 任意角色 +getConnCount 任意角色 +getHashAbstractLocally 任意角色 +getHashLocally 任意角色 +getNodeRoleDeprecated 查询当前角色 任意角色 +getSessionID 任意角色 +listAdapters 任意角色 +listTheContractProcess 任意角色 +login 登录 任意角色 +longStr 任意角色 +ping 任意角色 +queryDataByHash 任意角色 +queryDataByHashLocally 任意角色 +queryHashByOffset 任意角色 +queryHashByRequestID 任意角色 +queryHashSize 任意角色 +queryLedgers 任意角色 +queryRole 任意角色 +queryTransactionByHash 任意角色 +sendTransaction 任意角色 +setLogStage 任意角色 +=============================== ==================== ========================================= + +合约准入中心角色划分 +~~~~~~~~~~~~~~~~~~~~ + +共分为两类角色:CenterManager和NodeManager。其中,CenterManager拥有对集群设置的权限。 +NodeManager可以增加、删除节点等操作。 + +============================= ============ ========================== +接口 说明 角色 +============================= ============ ========================== +authNodeManager CenterManager; +countActionLogByCategory CenterManager; +countCMLogByCategory CenterManager; +delete CenterManager; +listAllUsers CenterManager; +listApplyList CenterManager; +listLicence CenterManager; +queryActionLog CenterManager; +queryCMLog CenterManager; +updateLicence CenterManager; +addNode CenterManager;NodeManager; +changeNCFile CenterManager;NodeManager; +changeOtherNC CenterManager;NodeManager; +createTrustUnit 创建可信集群 CenterManager;NodeManager; +deleteTrustUnit CenterManager;NodeManager; +getNCFile CenterManager;NodeManager; +getNodeTrustUnits CenterManager;NodeManager; +getOtherNC CenterManager;NodeManager; +listContractProcess CenterManager;NodeManager; +listMultiPointContractProcess CenterManager;NodeManager; +listNodes CenterManager;NodeManager; +listTrustUnits CenterManager;NodeManager; +queryUserStat CenterManager;NodeManager; +stopMultiPointContractProcess CenterManager;NodeManager; +applyRole NodeManager; +executeContract 调用合约 任意角色 +executeContractTrustfully 任意角色 +getManagerPubkey 任意角色 +getNodeRole 任意角色 +getNodeSessionID 任意角色 +getRole 任意角色 +getSessionID 任意角色 +login 登录 任意角色 +============================= ============ ========================== + +-------------- + +合约节点Http接口 +---------------- + +``http://xxx.xxx.xxx.xxx:1717/SCIDE/SCManager``\ 为提供Http接口服务的服务器 +URL(\ ``xxx.xxx.xxx.xxx:1717``\ 为BDWare SCIDE运行的IP和端口号) , +用户可通过在URL后附加字段参数, 完成以下功能. +``http://xxx.xxx.xxx.xxx:18000/SCIDE/SCManager`` +为提供Http接口服务的服务器 + +URL(\ ``xxx.xxx.xxx.xxx:1717`` 为BDWare +SCIDE运行的IP和端口号),用户可通过在URL后附加字段参数,完成以下功能: + +用户管理类 +~~~~~~~~~~ + +.. _ping-1: + +ping +^^^^ + +``ping``\ 服务器测试 + +方法 +'''' + +GET + +.. _参数-2: + +参数 +'''' + +====== ==== +字段 值 +====== ==== +action ping +====== ==== + +.. _请求示例-2: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=ping + +.. _返回结果示例-2: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"data":"pong"} + +合约代码管理类 +~~~~~~~~~~~~~~ + +下载合约项目 +^^^^^^^^^^^^ + +.. _方法-1: + +方法 +'''' + +GET + +.. _参数-3: + +参数 +'''' + +=========== ================ +字段 值 +=========== ================ +action downloadContract +projectName 合约项目名 +isPrivate 是否在私有目录下 +pubKey 用户公钥 +timestamp 时间戳 +sign 签名 +=========== ================ + +.. _请求示例-3: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=downloadContract&projectName=BDCoin&isPrivate=false&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba3 + 8b7ff78aa631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 + +上传文件 +^^^^^^^^ + +.. _方法-2: + +方法 +'''' + +POST + +.. _参数-4: + +参数 +'''' + +========= ================ +字段 值 +========= ================ +path 文件上传路径 +fileName 待上传文件名 +isPrivate 是否在私有目录下 +order 第几个数据包 +count 数据包总数 +timestamp 时间戳 +sign 签名 +========= ================ + +.. _请求示例-4: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/Upload?path=/TEST/TEST.yjs&fileName=WechatIMG15.jpeg&isPrivate=true&order=0&count=3&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba36ca83066870cf2c1d5de6df67e24e68dde7934af9b31d94a6084281db3d32d5ce42ab8f75bf799aca05&sign=dd867469f5adf9986e4ea6215febeae50c7d4c3836d002cf8c17050dfca031fd2595ffa8646e9eeae53150d2cbaea690e27d818eaf5cea3632ee1b69c3307a4b631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 + +.. _返回结果示例-3: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":"true","data":"success"} + +保存合约脚本 +^^^^^^^^^^^^ + +向服务器发送请求, 向服务器本地保存合约脚本内容. + +.. _方法-3: + +方法 +'''' + +GET + +.. _参数-5: + +参数 +'''' + +======= ============== +字段 值 +======= ============== +action writeDyjs +target 合约脚本文件名 +content 合约脚本内容 +======= ============== + +.. _请求示例-5: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=writeDyjs&target=testyjs.yjs&content=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D + +.. _返回结果示例-4: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "status": false, + "action": "onWriteDyjs", + "data": "success" + } + +后续用户可启动并调用该合约. + +合约实例管理类 +~~~~~~~~~~~~~~ + +查询合约进程 +^^^^^^^^^^^^ + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +.. _方法-4: + +方法 +'''' + +GET + +.. _参数-6: + +参数 +'''' + +====== =================== +字段 值 +====== =================== +action listContractProcess +====== =================== + +.. _请求示例-6: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=listContractProcess + +.. _返回结果示例-5: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "status": false, + "action": "onListContractProcess", + "data": "[\n {\n \"id\": \"-562752842\",\n \"name\": \"shortc\",\n \"port\": \"1626\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]" + } + +启动合约 +^^^^^^^^ + +向服务器发送请求, 启动某个合约. + +.. _方法-5: + +方法 +'''' + +GET + +.. _参数-7: + +参数 +'''' + +====== ================================= +字段 值 +====== ================================= +action startContract +script 合约脚本内容, 需进行进行URIEncode +====== ================================= + +.. _请求示例-7: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=startContract&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D + +.. _返回结果示例-6: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "data": "{\"status\":\"Success\",\"result\":\"\"}", + "action": "onStartContract", + "cid": "-562752842", + "executeTime": 1187 + } + +调用合约 +^^^^^^^^ + +向服务器发送请求, 调用某个合约. + +.. _方法-6: + +方法 +'''' + +GET + +.. _参数-8: + +参数 +'''' + +=================== =========================== +字段 值 +=================== =========================== +action executeContract +contractID 合约ID +withDynamicAnalysis true/false 是否进行动态分析 +operation 调用合约的方法名 +arg 调用合约的参数 +pubkey 可选,调用者公钥 +signature 可选,签名 +=================== =========================== + +其中pubkey为sm2的公钥,计算方式如下: + +.. code:: javascript + + //sm2 可从sm2.js中加载获得。 + signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); + +.. _请求示例-8: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=executeContract&contractID=-620602333&operation=main&arg=hhh + +.. _返回结果示例-7: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "data": "{\"status\":\"Success\",\"result\":\"3\"}", + "action": "onExecuteResult", + "executeTime": "13" + } + +批量启动合约 +^^^^^^^^^^^^ + +向服务器发送请求, 启动服务器中保存有合约脚本的一系列合约. + +.. _方法-7: + +方法 +'''' + +GET + +.. _参数-9: + +参数 +'''' + +======== ==================================== +字段 值 +======== ==================================== +action startContractBatched +fileList 合约脚本文件列表(Json数组,URLEncode) +======== ==================================== + +.. _请求示例-9: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=startContractBatched&fileList=%5B%20%22EventPuber.yjs%22%2C%20%22EventSuber.yjs%22%2C%20%22LicenceManager.yjs%22%20%5D + +.. _返回结果示例-8: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"EventPuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","LicenceManager.yjs":"{\"status\":\"Success\",\"result\":\"\"}","EventSuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","action":"onStartContract"} + +启动Zip包合约 +^^^^^^^^^^^^^ + +向服务器发送请求, 启动服务器中包装为\ ``zip``\ 格式的合约. + +.. _方法-8: + +方法 +'''' + +GET + +.. _参数-10: + +参数 +'''' + +========= ======================= +字段 值 +========= ======================= +action startContractInTempZips +owner 调用者公钥 +path zip合约(路径及)文件名 +signature 调用者签名 +========= ======================= + +.. _请求示例-10: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=startContractInTempZips&owner=0475c7b061f32477c1e228dd04143daf58a5574dc3f6b02bd2857cc794eb92bfe98606dc314049e77fd8714f57a5a481cb470cc759e688fe60d40fc87092165e55&path=traceTest.zip&signature=650d3cad50509682937c253d84da99230e8ea1bcfb9b10f6d18f8888c7c4b6b4%2C72231a6daa078a3ce657c0a2ed38251b7db56cf725beaf86780d4c240b19ccc2 + +.. _返回结果示例-9: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"data":"verify failed","action":"onStartContract"} + +获取合约代码 +^^^^^^^^^^^^ + +向服务器发送请求, 获取某个ID合约的脚本代码. + +.. _方法-9: + +方法 +'''' + +GET + +.. _参数-11: + +参数 +'''' + +========== =========== +字段 值 +========== =========== +action getCodeByID +contractID 合约ID +========== =========== + +.. _请求示例-11: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=getCodeByID&contractID=814046805 + +.. _返回结果示例-10: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":true,"action":"onCodeResult","data":"@LogType(\"Arg\")\ncontract EventSuberAtCHQ{\n\t\n \texport function init(arg){\n\t\tvar result \u003d YancloudUtil.subscribe(\"EventPuberAt3966\",\"abc\",handler);\n // print(\"Handler:\"+handler);\n \t \n \t\treturn result;\n\t}\n \texport function handler(e){\n var ret \u003d \"ReceiveEvent:\";\n\t\tret+\u003d\"\\n\";\n \tprint(ret);\n \tret+\u003dYancloudUtil.executeContract(\"EventPuberAt3966\",\"notify\",\"success\");\n \tprint(ret);\n return ret;\n\t}\n}\n"} + +保存合约状态 +^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器的状态转移日志. + +.. _方法-10: + +方法 +'''' + +GET + +.. _参数-12: + +参数 +'''' + +========== =================== +字段 值 +========== =================== +action dumpContract +contractID 合约ID 或 合约Name= +========== =================== + +.. _请求示例-12: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/SCManager?action=dumpContract&contractID=counter&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022004ffd1346b936196f5b13953d2f3e11823a0d0a2d2f6fecea258cef8e20d99c0022100bbc219ed1f56799ba28a763b9e9e47063164e7ceecfbfa752de42f44551ffb83 + +.. _返回结果示例-11: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"data":"success","size":"3.76 KB","time":"0.03s"} + +获取合约内存文件列表 +^^^^^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取某子文件夹中的所有内存文件列表. + +.. _方法-11: + +方法 +'''' + +GET + +.. _参数-13: + +参数 +'''' + +========== ================== +字段 值 +========== ================== +action listMemoryFiles +contractID 合约Id 或 合约Name +========== ================== + +.. _请求示例-13: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/SCManager?action=listMemoryFiles&contractID=-247468535&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022075c7268e888b0efdef167a3f4dfc6589d771c6be41b3c0a1dc12d057e811f395022100d44f460d0cc3643e169ef08231e75a1e895646c53295c0ef1d15c3b462a53d6b + +.. _返回结果示例-12: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"data":["2020-09-23.18:40:38","2020-09-24.16:03:41","2020-09-24.16:58:39","2020-09-24.18:25:47","2020-09-24.18:32:37","2020-09-24.20:54:41","2020-09-24.20:57:39","2020-09-24.21:31:07","2020-09-24.21:32:09","2020-09-24.21:36:11","2020-09-28.15:29:15","2020-09-28.20:28:29","2020-09-28.20:39:46","2020-09-28.21:45:31","2020-09-28.21:49:18","2020-09-28.22:27:34","2020-09-28.22:31:09","2020-09-28.22:32:49","2020-10-07.16:51:06","2020-10-07.16:51:23","2020-10-25.21:09:10","2020-12-14.19:06:53","2021-02-02.10:28:56","2021-02-02.10:31:13"],"action":"onListMemoryFiles"} + +停止合约 +^^^^^^^^ + +向服务器发送请求, 停止某个合约. + +.. _方法-12: + +方法 +'''' + +GET + +.. _参数-14: + +参数 +'''' + +=========== =================== +字段 值 +=========== =================== +action killContractProcess +id 合约ID +\*requestID 请求ID, String类型 +=========== =================== + +``*``\ 表示可选参数 + +.. _请求示例-14: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=killContractProcess&id=-1759263594 + +.. _返回结果示例-13: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":false,"action":"onListContractProcess","data":"[\n {\n \"id\": \"-65051856\",\n \"name\": \"EventSuber\",\n \"port\": \"1631\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"814046805\",\n \"name\": \"EventSuberAtCHQ\",\n \"port\": \"1630\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"2023975189\",\n \"name\": \"LicenceService\",\n \"port\": \"1632\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"-620602333\",\n \"name\": \"shortc\",\n \"port\": \"1627\",\n \"times\": \"0 \",\n \"traffic\": \"0.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]"} + +停止所有合约 +^^^^^^^^^^^^ + +向服务器发送请求, 停止服务器上启动的所有合约. + +.. _方法-13: + +方法 +'''' + +GET + +.. _参数-15: + +参数 +'''' + +====== =============== +字段 值 +====== =============== +action killAllContract +====== =============== + +.. _请求示例-15: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=killAllContract + +.. _返回结果示例-14: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":false,"action":"onKillAllContract","data":"Kill:7357,7541,7548,7555,7584,7585,7591,7598,7609,7612,8440,8442,8444,8521,"} + +静态分析合约 +^^^^^^^^^^^^ + +向服务器发送请求, 静态分析合约脚本. + +.. _方法-14: + +方法 +'''' + +GET + +.. _参数-16: + +参数 +'''' + +========== ==================== +字段 值 +========== ==================== +action staticVerifyContract +contractid 合约ID +script 请求ID, String类型 +========== ==================== + +.. _请求示例-16: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=staticVerifyContract&contractid=943728900&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D&path=static.yjs + +.. _返回结果示例-15: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"data":"{\"status\":\"Success\",\"result\":\"{\\\"main\\\":\\\"Ret:arg \\\"}\"}","action":"onExecuteResult","cid":"943728900","executeTime":54} + +获取合约静态分析流 +^^^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取某个合约的静态分析Control Flow. + +.. _方法-15: + +方法 +'''' + +GET + +.. _参数-17: + +参数 +'''' + +====== ======================== +字段 值 +====== ======================== +action getControlFlowByFileName +path 合约ID +====== ======================== + +.. _请求示例-17: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=getControlFlowByFileName&path=EventSuber.yjs + +.. _返回结果示例-16: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"init":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","aload 4","invokedynamic dyn:getProp|getElem|getMethod:YancloudUtil (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B3","stmts":["dup","invokedynamic dyn:getMethod|getProp|getElem:subscribe (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B4","stmts":["swap","ldc XiaomiSmartHomeAtPKU","ldc onAirPurifierModeChange","aload 4","invokedynamic dyn:getProp|getElem|getMethod:handler (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B5","stmts":["invokedynamic dyn:call:\\\u003dYancloudUtil\\,subscribe (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B6","stmts":["\u003dL3\u003d","astore 5"],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B7","stmts":["\u003dL4\u003d","aload 5","areturn"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B8","stmts":["\u003dL5\u003d"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B9","stmts":["\u003dL6\u003d"],"original":" \t\treturn result;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B9","label":{"label":"e"}}]},"handler":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","ldc ReceiveEvent:","aload 2","invokedynamic dyn:getProp|getElem|getMethod:content (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B3","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B4","stmts":["ldc ","invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B5","stmts":["aload 2","invokedynamic dyn:getProp|getElem|getMethod:type (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B6","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B7","stmts":["\u003dL3\u003d","astore 5"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B8","stmts":["\u003dL4\u003d","aload 4","invokedynamic dyn:getMethod|getProp|getElem:print (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B9","stmts":["getstatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime UNDEFINED Lwrp/jdk/nashorn/internal/runtime/Undefined;","aload 5","invokedynamic dyn:call:print (Ljava/lang/Object;Lwrp/jdk/nashorn/internal/runtime/Undefined;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B10","stmts":["pop"],"original":" \tprint(ret);"},{"type":"Continuous","name":"B11","stmts":["\u003dL5\u003d","aload 5","areturn"],"original":" return ret;"},{"type":"Continuous","name":"B12","stmts":["\u003dL6\u003d"],"original":" return ret;"},{"type":"Continuous","name":"B13","stmts":["\u003dL7\u003d"],"original":" return ret;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B8","label":{"label":"e"}},{"from":"B8","to":"B9","label":{"label":"e"}},{"from":"B9","to":"B10","label":{"label":"e"}},{"from":"B10","to":"B11","label":{"label":"e"}},{"from":"B11","to":"B13","label":{"label":"e"}}]}} + +日志查看类 +~~~~~~~~~~ + +合约日志-查询数量 +^^^^^^^^^^^^^^^^^ + +.. _方法-16: + +方法 +'''' + +GET + +contractName为空或是不传入时,则为查询全部合约的条数 + +.. _参数-18: + +参数 +'''' + +============ ======================== +字段 值 +============ ======================== +action queryContractLogSize +contractName 字符串,非必须,合约名称 +============ ======================== + +.. _请求示例-18: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogSize&contractName=NanningDataSource + +.. _返回结果示例-17: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "size": 12, + "action": "onQueryContractLogSize", + "status": "success" + } + +合约日志-根据日期查询 +^^^^^^^^^^^^^^^^^^^^^ + +.. _方法-17: + +方法 +'''' + +GET + +.. _参数-19: + +参数 +'''' + +============ ===================================== +字段 值 +============ ===================================== +action queryContractLogByDate +start long,必须,起始时间 +end long,非必须,若无end,默认为当前时间 +contractName 字符串,非必须,合约名称 +============ ===================================== + +.. _请求示例-19: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByDate&start=1597296300272&end=1597296305747 + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getMainFrame", + "costTime": "2493", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296300272, + "key": "-8590335427581967208" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "732", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296301030, + "key": "849660532962309239" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4580", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305745, + "key": "-8003529429500512736" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4551", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305746, + "key": "7604666709899222357" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305751, + "key": "-7561786202695627022" + } + ], + "action": "onQueryRecentContractLog" + } + +合约日志-根据偏移量查询 +^^^^^^^^^^^^^^^^^^^^^^^ + +.. _方法-18: + +方法 +'''' + +GET + +.. _参数-20: + +参数 +'''' + +============ ============================================= +字段 值 +============ ============================================= +action queryContractLogByOffset +count long,必须,获取日志条数 +offset long,非必须,若无offset,默认返回最新count条 +contractName 字符串,非必须,合约名称 +============ ============================================= + +.. _请求示例-20: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByOffset&count=5&contractName=NanningDataSource + +.. _返回结果-1: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305842, + "key": "-2390672423847654148" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "isOwner", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305868, + "key": "6056586201629372511" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getApplyList", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305893, + "key": "3882409580676458151" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getAcceptList", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305908, + "key": "-3437513873417136535" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654, + "key": "203156239086062402" + } + ], + "action": "onQueryRecentContractLog" + } + +合约日志-根据key查询 +^^^^^^^^^^^^^^^^^^^^ + +.. _方法-19: + +方法 +'''' + +GET + +.. _参数-21: + +参数 +'''' + +====== =========================== +字段 值 +====== =========================== +action queryContractLogByKey +key long,必须,该日志对应的key +====== =========================== + +.. _请求示例-21: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByKey&key=203156239086062402 + +.. _返回结果-2: + +返回结果 +'''''''' + +.. code:: json + + { + "data": { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654 + }, + "action": "onQueryContractLogByKey" + } + +合约日志-按时间段统计调用次数 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _方法-20: + +方法 +'''' + +GET + +.. _参数-22: + +参数 +'''' + +======== ======================================================== +字段 值 +======== ======================================================== +action countContractLogGroupByCategory +start long,必须,起始时间 +end 非必须,终止时间,默认为当前 +interval long,非必须,统计间隔 +category 非必须,合约名称以逗号连接,不传入时统计全部合约调用情况 +======== ======================================================== + +.. _请求示例-22: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=countContractLogGroupByCategory&start=1596758400000&interval=86400000 + +.. _返回结果-3: + +返回结果 +'''''''' + +.. code:: json + + { + "start": 1596758400000, + "interval": 86400000, + "action": "onCountContractLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 43, + 14 + ] + } + +账本日志-查询数量 +^^^^^^^^^^^^^^^^^ + +查询通过本节点去账本上记录的日志数量 + +.. _方法-21: + +方法 +'''' + +GET + +.. _参数-23: + +参数 +'''' + +============ ================ +字段 值 +============ ================ +action queryHashSize +contractName 非必须,合约名称 +============ ================ + +.. _请求示例-23: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashSize&contractName=NanningDataSource + +.. _返回结果-4: + +返回结果 +'''''''' + +.. code:: json + + { + "count": "2", + "action": "onQueryHashSize" + } + +账本日志-根据偏移量查询 +^^^^^^^^^^^^^^^^^^^^^^^ + +查询x条通过本节点去账本上记录的日志的哈希列表 + +.. _方法-22: + +方法 +'''' + +GET + +.. _参数-24: + +参数 +'''' + +============ =========================================================== +字段 值 +============ =========================================================== +action queryHashByOffset +count 整数,必须,表示条数 +offset 整数,非必须,表示偏移量,不传入offset则默认返回最新count条 +contractName 字符串,非必须,表示合约名称 +============ =========================================================== + +.. _请求示例-24: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashByOffset&count=1&contractName=NanningDataSource + +.. _返回结果-5: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "hash": "3a6c60621907146b77146c1f2d48700e47520173", + "date": 1597296314658 + } + ], + "action": "onQueryHash", + "status": "success" + } + +账本日志-根据hash查询详情 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +根据hash来查询日志内容 + +.. _方法-23: + +方法 +'''' + +GET + +.. _参数-25: + +参数 +'''' + +====== =============================== +字段 值 +====== =============================== +action queryDataByHash +hash 字符串,可通过queryHashByOffset +====== =============================== + +.. _请求示例-25: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryDataByHash&count=1&contractName=NanningDataSource&hash=3a6c60621907146b77146c1f2d48700e47520173 + +.. _返回结果-6: + +返回结果 +'''''''' + +.. code:: json + + { + "from": "0x3034643139323433323966373263656431343866", + "to": "0x65786563757465436f6e74726163740000000000", + "data": "1597296314655 --> {\"extraGas\":\"0\",\"totalGas\":\"0\",\"executionGas\":\"0\",\"signature\":\"4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02\",\"costTime\":\"6\",\"arg\":\" {\\\\\\\"year\\\\\\\":2018,\\\\\\\"category\\\\\\\":\\\\\\\"工业\\\\\\\",\\\\\\\"indexType\\\\\\\":\\\\\\\"营业额\\\\\\\"}\",\"contractID\":\"-1382208250\",\"action\":\"analysisByIndustry\",\"pubKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}", + "requestID": "1597296314629_6067", + "action": "onQueryDataByHash" + } + +账本日志-根据requestID查询Hash +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +根据requestID来查询日志内容,需由开发者保证requestID的唯一性 + +.. _方法-24: + +方法 +'''' + +GET + +.. _参数-26: + +参数 +'''' + +========= ======================== +字段 值 +========= ======================== +action queryHashByRequestID +requestID 字符串,在发起调用时生成 +========= ======================== + +.. _请求示例-26: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=queryHashByRequestID&requestID=0987654321ab + +节点日志-查询数量 +^^^^^^^^^^^^^^^^^ + +.. _方法-25: + +方法 +'''' + +GET + +.. _参数-27: + +参数 +'''' + +======== ============================ +字段 值 +======== ============================ +action queryNodeLogSize +category 非必须,不传入时查询全部情况 +======== ============================ + +其中包括:ping、startContract、saveFile等。 + +.. _请求示例-27: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize&category=login + +.. _返回结果-7: + +返回结果 +'''''''' + +.. code:: json + + { + "size": 177, + "action": "onQueryNodeLogSize", + "status": "success" + } + +节点日志-按日期查询 +^^^^^^^^^^^^^^^^^^^ + +.. _方法-26: + +方法 +'''' + +GET + +.. _参数-28: + +参数 +'''' + +======== ============================ +字段 值 +======== ============================ +action queryNodeLogByDate +start long,必须,起始日期 +end long,非必须 +category 非必须,不传入时查询全部情况 +======== ============================ + +.. _请求示例-28: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1597376006441 + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1596758400000&category=login + +.. _返回结果-8: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByDate" + } + +节点日志-按偏移量查询 +^^^^^^^^^^^^^^^^^^^^^ + +.. _方法-27: + +方法 +'''' + +GET + +.. _参数-29: + +参数 +'''' + +============ ============================================= +字段 值 +============ ============================================= +action queryNodeLogByOffset +count long,必须,获取日志条数 +offset long,非必须,若无offset,默认返回最新count条 +contractName 字符串,非必须,合约名称 +============ ============================================= + +.. _请求示例-29: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByOffset&count=5 + +.. _返回结果-9: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByOffset" + } + +节点日志-按时间段统计调用次数 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _方法-28: + +方法 +'''' + +GET + +.. _参数-30: + +参数 +'''' + +======== ================================================== +字段 值 +======== ================================================== +action countLogGroupByCategory +start long,必须,起始时间 +end 非必须,终止时间,默认为当前 +interval long,非必须,统计间隔 +category 非必须,action以逗号连接,不传入时统计全部调用情况 +======== ================================================== + +其中,category中的action为NodePortal的接口的action集合。 +包括:ping、startContract、saveFile等。 + +.. _请求示例-30: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000 + + http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000&category=ping,startContract + +.. _返回结果-10: + +返回结果 +'''''''' + +.. code:: json + + { + "start": 1596758400000, + "interval": 86400000, + "action": "onCountNodeLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 912, + 761 + ] + } + +输出历史记录日志 +^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +.. _方法-29: + +方法 +'''' + +GET + +.. _参数-31: + +参数 +'''' + +====== ================== +字段 值 +====== ================== +action printTimeTravelLog +====== ================== + +.. _请求示例-31: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=printTimeTravelLog + +.. _返回结果示例-18: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":false,"data":"[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa_1572335939893.dyjs\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n"} + +输出节点转移日志 +^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器的状态转移日志. + +.. _方法-30: + +方法 +'''' + +GET + +.. _参数-32: + +参数 +'''' + +====== ================ +字段 值 +====== ================ +action printTransferLog +====== ================ + +.. _请求示例-32: + +请求示例 +'''''''' + +:: + + http://127.0.0.1:1717/SCIDE/SCManager?action=printTransferLog + +.. _返回结果示例-19: + +返回结果示例 +'''''''''''' + +.. code:: json + + {"status":false,"data":""} + +模板生成类 +~~~~~~~~~~ + +-------------- + +合约节点WebSocket接口 +--------------------- + +.. _用户管理类-1: + +用户管理类 +~~~~~~~~~~ + +获取Session +^^^^^^^^^^^ + +登录前获取session以便进行签名。 + +.. _参数-33: + +参数 +'''' + +====== ============ +字段 值 +====== ============ +action getSessionID +====== ============ + +.. _请求示例-33: + +请求示例 +'''''''' + +:: + + var req = {}; + req.action = "getSessionID"; + wssocket.send(JSON.stringify(req)); + +.. _返回结果-11: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onSessionID", + "session": "9782323_session" + } + +用户登录 +^^^^^^^^ + +用户进行公私钥身份验证 + +.. _参数-34: + +参数 +'''' + +====== ===== +字段 值 +====== ===== +action login +====== ===== + +.. _请求示例-34: + +请求示例 +'''''''' + +:: + + var loginParam = {}; + loginParam.pubKey = global.sm2Key.publicKey; + loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); + loginParam.action = "login"; + wssocket.send(JSON.stringify(loginParam)); + +.. _返回结果-12: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onLogin", + "data": "NodeManager,ContractProvider" + } + +申请角色 +^^^^^^^^ + +在节点管理员界面申请可以申请称为合约管理员(ContractInstanceManager)、合约使用者(ContractUser)、合约提供者(ContractProvider) + +.. _参数-35: + +参数 +'''' + +====== ============= +字段 值 +====== ============= +action applyNodeRole +role 申请角色名称 +====== ============= + +.. _请求示例-35: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "applyNodeRole"; + param.role = "ContractUser"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-13: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onApplyRole", + "data": "success" + } + + { + "action":"onApplyRole", + "data":"already has!" + } + +授权角色 +^^^^^^^^ + +.. _参数-36: + +参数 +'''' + +======== ==================== +字段 值 +======== ==================== +action authNodeRole +isAccept bool类型,表示否授权 +pubKey 授权用户公钥 +======== ==================== + +.. _请求示例-36: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "authNodeRole"; + param.isAccept = true; + param.pubKey = "xxxxx"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-14: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onAuthNodeRole", + "data": "success" + } + +删除用户角色 +^^^^^^^^^^^^ + +.. _参数-37: + +参数 +'''' + +====== ============ +字段 值 +====== ============ +action deleteRole +role 删除角色名称 +====== ============ + +.. _请求示例-37: + +请求示例 +'''''''' + +:: + + var deleteInfo = {}; + deleteInfo.pubKey = global.authorizedUsers.[publicKey]; + deleteInfo.action = "deleteRole"; + deleteInfo.role="ContractUser"; + wssocket.send(JSON.stringify(deleteInfo)); + +.. _返回结果-15: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onDeleteRole", + "data": "success" + } + +查看授权用户列表 +^^^^^^^^^^^^^^^^ + +查看准入管理员当前组网中已经授权的节点管理员 + +.. _参数-38: + +参数 +'''' + +====== =============== +字段 值 +====== =============== +action listAllAuthRole +====== =============== + +.. _请求示例-38: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "listAllAuthRole"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-16: + +返回结果 +'''''''' + +.. code:: json + + { + "status":false, + "action":"onListAllAuthRole", + "data": + { + "kv":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"NodeManager,ContractProvider,ContractUser,ContractInstanceManager"}], + "time":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"1617178709933"}] + } + } + +查看申请用户列表 +^^^^^^^^^^^^^^^^ + +.. _参数-39: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action listUnAuthRole +====== ============== + +.. _请求示例-39: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "listUnAuthRole"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-17: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onListUnAuthRole", + "kv": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "ContractProvider,ContractUser" + }], + "time": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "1587398989914" + }] + } + +参数(删除) +'''''''''' + +====== ============= +字段 值 +====== ============= +action queryUserStat +====== ============= + +.. _请求示例-40: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "queryUserStat"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-18: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 + } + +.. _合约代码管理类-1: + +合约代码管理类 +~~~~~~~~~~~~~~ + +获取公共合约文件列表 +^^^^^^^^^^^^^^^^^^^^ + +.. _参数-40: + +参数 +'''' + +====== ============ +字段 值 +====== ============ +action listProjects +====== ============ + +.. _请求示例-41: + +请求示例 +'''''''' + +:: + + var request = {}; + request.action = "listProjects"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-19: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\",\"BiddingExample\",\"ContractExecutor\"]", + "executeTime":0, + "isPrivate":false + } + +获取私有合约文件列表 +^^^^^^^^^^^^^^^^^^^^ + +.. _参数-41: + +参数 +'''' + +========= ============ +字段 值 +========= ============ +action listProjects +pubKey 该用户的公钥 +isPrivate true +========= ============ + +.. _请求示例-42: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "listProjects"; + request.pubKey = "global.sm2.publicKey"; + request.isPrivate=true; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-20: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true + } + +获取合约实例 +^^^^^^^^^^^^ + +.. _参数-42: + +参数 +'''' + +====== =================== +字段 值 +====== =================== +action listContractProcess +====== =================== + +.. _请求示例-43: + +请求示例 +'''''''' + +:: + + var request = {}; + request.action = "listContractProcess"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-21: + +返回结果 +'''''''' + +.. code:: json + + { + "status":false, + "action":"onListContractProcess", + "data":"[{\"id\": \"1658407837\",\"name\": \"BDCoin\",\"port\": \"1617\"}]" + } + +.. _启动合约-1: + +启动合约 +^^^^^^^^ + +.. _参数-43: + +参数 +'''' + +========= ============= +字段 值 +========= ============= +action startContract +owner pubkey +requestID 当前时间 +script 脚本内容 +signature 签名 +========= ============= + +.. _请求示例-44: + +请求示例 +'''''''' + +:: + + request.action = "startContract"; + request.owner = global.sm2Key.publicKey; + request.requestID = new Date().getTime() + ""; + request.script = global.projectScript; + request.signature = sm2.doSignature("Algorithm|" + request.script + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); + wssocket.send(JSON.stringify(request)); + +.. _返回结果-22: + +返回结果 +'''''''' + +.. code:: json + + { + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":\"\",\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStartContract", + "cid":"-506393888", + "executeTime":2496, + "responseID":"1617206735696" + } + +分发合约项目 +^^^^^^^^^^^^ + +.. _参数-44: + +参数 +'''' + +============= ================== +字段 值 +============= ================== +action distributeContract +peersID 集群中节点peer +projectName 合约名 +isPrivate 是否在私有目录 +sponsorPeerID 发起者ID +signature 签名 +============= ================== + +.. _请求示例-45: + +请求示例 +'''''''' + +.. code:: javascript + + request.action = "distributeContract"; + request.peersID = peersID; + request.projectName = global.projects[global.lastClickedProjectId]; + request.isPrivate = $("#privateDir-tab").hasClass("active"); + request.sponsorPeerID = global.peerID; + request.signature = sm2.doSignature("DistributeContract|" + request.projectName + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); + wssocket.send(JSON.stringify(request)); + +.. _返回结果-23: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onDistributeContract", + "progress":"100.00%" + } + +终止合约 +^^^^^^^^ + +.. _参数-45: + +参数 +'''' + +========= =================== +字段 值 +========= =================== +action killContractProcess +id 合约id +requestID 请求ID +========= =================== + +.. _请求示例-46: + +请求示例 +'''''''' + +:: + + request.action = "killContractProcess"; + request.id = contractid; + request.requestID = new Date().getTime() + ""; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-24: + +返回结果 +'''''''' + +.. code:: json + + { + "data": "ContractHandler: exit in 3 seconds!", + "action": "onOutputStream" + } + +终止所有合约 +^^^^^^^^^^^^ + +.. _参数-46: + +参数 +'''' + +====== =============== +字段 值 +====== =============== +action killAllContract +====== =============== + +.. _请求示例-47: + +请求示例 +'''''''' + +:: + + request.action = "killAllContract"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-25: + +返回结果 +'''''''' + +.. code:: json + + { + "status":false, + "action":"onKillAllContract", + "data":"Kill:7241,7245," + } + +.. _静态分析合约-1: + +静态分析合约 +^^^^^^^^^^^^ + +.. _参数-47: + +参数 +'''' + +========== ==================== +字段 值 +========== ==================== +action staticVerifyContract +owner 用户私钥 +isPartial 是否是部分 +contractid contractid +script 脚本内容 +path 合约文件名 +========== ==================== + +.. _请求示例-48: + +请求示例 +'''''''' + +.. code:: javascript + + request.action = "staticVerifyContract"; + request.owner = global.sm2Key.privateKey + request.isPartial = false; + request.contractid = contractid; + request.script = global.projectScript; + request.path = global.projectName; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-26: + +返回结果 +'''''''' + +.. code:: json + + + { + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":{\"hello\":\"Ret:\"},\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStaticVerifyResult", + "cid":"verify", + "executeTime":83 + } + +删除合约 +^^^^^^^^ + +.. _参数-48: + +参数 +'''' + +====== ========== +字段 值 +====== ========== +action deleteFile +file fileName +====== ========== + +.. _请求示例-49: + +请求示例 +'''''''' + +.. code:: javascript + + request.action = "deleteFile"; + request.file = fileName; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-27: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onDeleteFile", + "data":"success", + "executeTime":0 + } + +私有合约传至公共目录 +^^^^^^^^^^^^^^^^^^^^ + +.. _参数-49: + +参数 +'''' + +======== ============ +字段 值 +======== ============ +action changePublic +pubkey 用户公钥 +fileName fileName +======== ============ + +.. _请求示例-50: + +请求示例 +'''''''' + +.. code:: javascript + + request.action = "changePublic"; + request.pubkey = pubkey; + request.fileName = fileName; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-28: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onChangePublic", + "data":"success", + "executeTime":0 + } + +上传合约 +^^^^^^^^ + +.. _参数-50: + +参数 +'''' + +========= ======================== +字段 值 +========= ======================== +action UploadFile +isAppend false +fileName fileName +path path +isPrivate true/false +content fileContent(base64编码) +========= ======================== + +.. _请求示例-51: + +请求示例 +'''''''' + +:: + + request.action = "uploadFile"; + request.isAppend = false; + request.fileName = "test1.yjs"; + request.path = "test1"; + text="Y29udHJhY3QgdGVzdDF7CglleHBvcnQgZnVuY3Rpb24gaGVsbG8oYXJnKXsgCiAgICAgICAgcmV0dXJuICJ3b3JsZCI7ICAKICAgIH0gICAKfQ==" + request.content = text; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-29: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onUploadFile", + "data":"success", + "executeTime":0 + } + +编译合约 +^^^^^^^^ + +.. _参数-51: + +参数 +'''' + +========== ========================== +字段 值 +========== ========================== +action compile +path string, 待编译的项目名称 +privateTab bool, 是否为私有目录的项目 +========== ========================== + +.. _请求示例-52: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {"action":"compile","path":"Hello","privateTab":true} + +.. _返回结果-30: + +返回结果 +'''''''' + +.. code:: json + + {"result":"Hello_2020-08-17-09:09:40.ypk","action":"onCompile"} + +锁定私有目录 +^^^^^^^^^^^^ + +锁定某个用户的的私有目录编辑功能 + +.. _参数-52: + +参数 +'''' + +====== ====================== +字段 值 +====== ====================== +action lockEdit +pubKey string, 要被锁定的公钥 +====== ====================== + +.. _请求示例-53: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.action = "lockEdit"; + req.pubKey = "xxxxxx"; + wssocket.send(JSON.stringify(req)); + +.. code:: json + + { + "action":"onLockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" + } + +解锁私有目录 +^^^^^^^^^^^^ + +解锁某个用户的的私有目录编辑功能 + +.. _参数-53: + +参数 +'''' + +====== ====================== +字段 值 +====== ====================== +action unLockEdit +pubKey string, 要被锁定的公钥 +====== ====================== + +.. _请求示例-54: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.action = unlockEdit; + req.pubKey = "xxxxxx"; + wssocket.send(JSON.stringify(req)); + +.. code:: json + + { + "action":"onUnlockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" + } + +.. _合约实例管理类-1: + +合约实例管理类 +~~~~~~~~~~~~~~ + +.. _查询合约进程-1: + +查询合约进程 +^^^^^^^^^^^^ + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +.. _参数-54: + +参数 +'''' + +====== =================== +字段 值 +====== =================== +action listContractProcess +====== =================== + +.. _请求示例-55: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "listContractProcess"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-20: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "status": false, + "action": "onListContractProcess", + "data": "[...]" + } + +.. _调用合约-1: + +调用合约 +^^^^^^^^ + +向服务器发送请求, 调用某个合约. + +.. _参数-55: + +参数 +'''' + +=================== ================================ +字段 值 +=================== ================================ +action executeContract +contractID 合约ID +withDynamicAnalysis true/false 是否进行动态分析,可选 +operation 调用合约的方法名 +arg 调用合约的参数 +pubkey 调用者公钥,可选 +signature 调用者签名 ,可选 +=================== ================================ + +``*``\ 表示可选参数 + +.. code:: javascript + + //sm2 可从sm2.js中加载获得。 + signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); + +.. _请求示例-56: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "executeContract"; + request.contractID = "2073401446"; + request.operation = "main"; + request.arg = "hhhhh"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-21: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "needSeq":false, + "seq":0, + "status":"Success", + "result":"world", + "isInsnLimit":false, + "totalGas":0, + "executionGas":0, + "extraGas":0, + "size":0, + "eventRelated":false, + "responseID":"1617211077264_223", + "action":"onExecuteResult", + "executeTime":"5" + } + +输出历史记录日志(删除) +^^^^^^^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +.. _参数-56: + +参数 +'''' + +====== ================== +字段 值 +====== ================== +action printTimeTravelLog +====== ================== + +.. _请求示例-57: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "printTimeTravelLog"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-22: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "status": false, + "data": "[CMActions] dumpContract :…t/contractExamples/memoryDumps/LicenceManager\n" + } + +输出节点转移日志(删除) +^^^^^^^^^^^^^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器的状态转移日志. + +.. _参数-57: + +参数 +'''' + +====== ================ +字段 值 +====== ================ +action printTransferLog +====== ================ + +.. _请求示例-58: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "printTransferLog"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-23: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "status": false, + "data": "" + } + +合约状态迁移 +^^^^^^^^^^^^ + +向服务器发送请求, 获取节点服务器的状态转移日志. + +.. _参数-58: + +参数 +'''' + +============ ============ +字段 值 +============ ============ +action loadMemory +contractName 合约名称 +memoryFile 合约文件名称 +============ ============ + +.. _请求示例-59: + +请求示例 +'''''''' + +.. code:: javascript + + var request = {}; + request.action = "loadMemory"; + request.contractName = "JsonContract"; + request.memoryFile = "2020-03-17.20/42/55"; + wssocket.send(JSON.stringify(request)); + +.. _返回结果示例-24: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "data":"success", + "size":"0.00 B", + "action":"onTransferTo", + "time":"0.01s" + } + +.. _日志查看类-1: + +日志查看类 +~~~~~~~~~~ + +查看本地近n日节点日志(删除) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _参数-59: + +参数 +'''' + +====== ================ +字段 值 +====== ================ +action listLocalNodeLog +date 当前时间 +====== ================ + +.. _请求示例-60: + +请求示例 +'''''''' + +:: + + request.action = "listLocalNodeLog"; + request.date = new Date().getTime() - 24 * 3600 * 1000 * n; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-31: + +返回结果 +'''''''' + +.. code:: json + + { + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" + } + +查看本地近n日合约日志(删除) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _参数-60: + +参数 +'''' + +====== ==================== +字段 值 +====== ==================== +action listLocalContractLog +date 当前时间 +====== ==================== + +.. _请求示例-61: + +请求示例 +'''''''' + +:: + + request.action = "listLocalContractLog"; + request.date = new Date().getTime() - 24 * 3600 * 1000 * n; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-32: + +返回结果 +'''''''' + +.. code:: json + + { + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7ba358d9234939623ab51ea94ca685e6a1f36ed81fd9630ccba6473e632f163bb30faffd4c91f21e5bace20101d6d6e36c04ac67eea14cc24b4962b84f57\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" + } + +节点配置类 +~~~~~~~~~~ + +获取节点配置信息 +^^^^^^^^^^^^^^^^ + +.. _参数-61: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action loadNodeConfig +====== ============== + +.. _请求示例-62: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "loadNodeConfig"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-33: + +返回结果 +'''''''' + +:: + + { + "status": true, + "action": "onLoadNodeConfig", + "data": { + "nodeName": "04BF52213343C147E631B877BCEB17B794230EE551E85F58FA429C4BA03D690778CC384C6916C63DF36CB9E35C7E274FDB4E18491DFE3D611D347856D441CACC5AF9090B515F02AFC2DFBF56461EC83B5A4CD342466360D6CF82E6E40B637430AC4A329CCBC798DAF7D526AF9E3B3600E0BEA1BFAB8C160EF90128FAF67B19E45F37664F1E4B", + "licence": "04AADCC7103CD02626D228AFFBEF53F8242ECA4DDD6F179D30B622440666715CFBB6FD1D3678A2B25812DEA9917073E79A65F7ADE517F784DC76288EFCEB37ECAA1025E6903540702F729DA1C2ECCD93F4E6FAFCE40DF443E7FD74387169D0C6D927C7BB12882D0471C8D3E6F31B0316A42FC38F6DD9978D4351B23B2AD63E2244909E98F51185D32CB99B4AE4E22D3AB4C04027BB", + "expireTime": "Wed Aug 26 09:43:08 CST 2020", + "nodes": "[\"node1\",\"node2\",\"node3\"]", + "yjsPath": "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar", + "nodeCenter": "ws://127.0.0.1:1719/SCIDE/NodeCenter" + } + } + + { + "status":true, + "action":"onLoadNodeConfig", + "data":{ + "nodeName":"Node_180", + "peerID":"", + "masterAddress":"39.104.201.40:21031", + "licence":"04AADCC7103C", + "doipConfig":"{\\"LHSProxyAddress\\":\\"http://39.104.201.40:21042/\\",\\"ownerHandle\\":\\"86.5000.470/dou.TEST\\",\\"certPath\\":\\"keys/dou.TEST.keystore\\",\\"certPassword\\":\\"123456\\",\\"repoID\\":\\"86.5000.470/doip.vcg9Mu1gSq_bdw\\",\\"listeners\\":\\"[{\\\\\\"url\\\\\\":\\\\\\"tcp://39.104.201.40:21032\\\\\\",\\\\\\"protocolVersion\\\\\\":\\\\\\"2.1\\\\\\",\\\\\\"messageFormat\\\\\\":\\\\\\"packet\\\\\\"}]\\",\\"serviceDescription\\":\\"test local Contract Repository\\",\\"serviceName\\":\\"ContractEngine021\\"}", + "clusterConnected":"false", + "nodePubKey":"0492d974b8a5b473d0ed2c81800917f76e2a1ec3666067888c85fe6922a672223f2083f95402ae13a744df58deabbe7206c4a317dd14296b0d3941a26ca4e34dc5", + "ipPort":"", + "bdledger":"39.108.56.240:18091,39.108.56.12:1809139.104.70.160:18091 47.98.247.70:18091 47.98.248.208:18091 39.104.77.165:18091 47.98.249.131:18091", + "yjsPath":"/data/bdwaas/bdcontract/yjs.jar", + "nodeCenter":"ws://39.104.201.21040/SCIDE/NodeCenter" + } + } + +修改节点配置 +^^^^^^^^^^^^ + +.. _参数-62: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action updateConfig +key 要改的配置项 +val 要更改的目标值 +====== ============== + +其中,key的可选项包括: + +============= =================================== =============================== +key的示 val示例 说明 +============= =================================== =============================== +yjsPath /User/xxx/cp/yjs.jar 合约进程启动所需的jar +dataChain 192.168.1.8:18090,182.173.2.3:18091 账本节点的ip与端口 +nodeCenter ws://127.0.0.1:18002 CenterPortal所在的ip/端口 +nodeName Node_180 字符串类型 +masterAddress 192.168.3.2:18001 该NodePortal节点的ip和的TCP端口 +============= =================================== =============================== + +其中NodePortal的TCP端口为Node的http/ws端口号+1。 + +修改节点名称 +^^^^^^^^^^^^ + +.. _参数-63: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action changeNodeName +data 新的节点名称 +====== ============== + +.. _请求示例-63: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "changeNodeName"; + param.data = "NewNodeName"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-34: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onChangeNodeName", + "data": true + } + +修改节点YJS路径 +^^^^^^^^^^^^^^^ + +.. _参数-64: + +参数 +'''' + +====== ===================== +字段 值 +====== ===================== +action changeYJSPath +data 节点服务器yjs.jar路径 +====== ===================== + +.. _请求示例-64: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "changeYJSPath"; + param.data = "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-35: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onChangeYJSPath", + "data": true + } + +修改NodeCenter +^^^^^^^^^^^^^^ + +.. _参数-65: + +参数 +'''' + +====== ========================================= +字段 值 +====== ========================================= +action changeNodeCenter +data 节点服务器要连接的NodeCenterWebSocket路径 +====== ========================================= + +.. _请求示例-65: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "changeNodeCenter"; + param.data = "ws://127.0.0.1:1719/SCIDE/NodeCenter"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-36: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onChangeNodeCenter", + "data": true + } + +修改账本节点 +^^^^^^^^^^^^ + +.. _参数-66: + +参数 +'''' + +====== =========================== +字段 值 +====== =========================== +action changeBDledger +data 数链节点的IP:port,用“,”隔开 +====== =========================== + +.. _请求示例-66: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "changeBDledger"; + param.data = "39.108.56.240:18091,39.108.56.12:18091"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-37: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onChangeBDledger", + "data": true + } + +上传节点Licence +^^^^^^^^^^^^^^^ + +.. _参数-67: + +参数 +'''' + +====== ======================= +字段 值 +====== ======================= +action uploadLicence +data 节点服务器的Licence内容 +====== ======================= + +.. _请求示例-67: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "uploadLicence"; + param.data = "04AADCC7103C"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-38: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onUploadLicence", + "data": true + } + +获取节点ID +^^^^^^^^^^ + +.. _参数-68: + +参数 +'''' + +====== ========= +字段 值 +====== ========= +action getNodeID +====== ========= + +.. _请求示例-68: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "getNodeID"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-39: + +返回结果 +'''''''' + +.. code:: json + + { + "status": true, + "action": "onGetNodeID", + "data": "0431…d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d" + } + +获取节点所在的可信执行集群 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _参数-69: + +参数 +'''' + +========== ================================================ +字段 值 +========== ================================================ +action getNodeTrustUnits +data 节点ID +msgHandler 收到回复的回调函数, 可使用“建立连接”的msgHandler +ws 节点所属的NodeCenter的WebSocket地址 +========== ================================================ + +.. _请求示例-69: + +请求示例 +'''''''' + +:: + + centerportalws = createWssocket("ws://127.0.0.1:1718/NodeCenterWS",function() { + var param = {}; + param.action = "getNodeTrustUnits"; + param.data = "0431e311bd70840fe69965e2cabea97fafe99f2133953c01abb9bd7cb62af42f8283f474d203051e920d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d"; + centerportalws.send(JSON.stringify(param)); + }, msgHandler); + +.. _返回结果-40: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [{ + "key": "0475c7b061...65e55_4063665700873624164", + "value": "[\"04541429c11b094…40009b4f06d\"]" + }], + "action": "onGetNodeTrustUnits" + } + +.. _模板生成类-1: + +模板生成类 +~~~~~~~~~~ + +获取合约模板列表 +^^^^^^^^^^^^^^^^ + +.. _参数-70: + +参数 +'''' + +====== =============== +字段 值 +====== =============== +action getTemplateList +====== =============== + +.. _请求示例-70: + +请求示例 +'''''''' + +.. code:: javascript + + req={}; + req.action = "getTemplateList"; + wssocket.send(JSON.stringify(req)); + +.. _返回结果-41: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [ + { + "formDesc": { + "dbPWD": { + "label": "密码", + "type": "input" + }, + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + }, + "dbUserName": { + "label": "用户名", + "type": "input" + }, + "fieldList": { + "label": "字段名", + "type": "tag" + }, + "dbUrl": { + "label": "数据库链接", + "type": "input" + }, + "tableName": { + "label": "表名", + "type": "input" + } + }, + "apiName": "generateMySQLProject" + }, + { + "formDesc": { + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + } + }, + "apiName": "generateEmptyProject" + } + ], + "action": "onTemplateList" + } + +空白合约模板 +^^^^^^^^^^^^ + +.. _参数-71: + +参数 +'''' + +============ ============================= +字段 值 +============ ============================= +action generateEmptyProject +contractName 字符串类型,合约名称 +isPrivate 布尔类型,是否为私有项目 +accessPolicy 若为“DAC”,则实现直接访问控制 +============ ============================= + +.. _请求示例-71: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.contractName = "Empty22"; + req.action = "generateEmptyProject"; + req.accessPolicy = "DAC"; + //wssocket为建立好的连接 + wssocket.send(JSON.stringify(req)); + +.. _返回结果-42: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\"]", + "executeTime":0, + "isPrivate":false + } + +MySQL接入合约 +^^^^^^^^^^^^^ + +.. _参数-72: + +参数 +'''' + +============= ====================================================== +字段 值 +============= ====================================================== +action generateMySQLProject +contractName 字符串类型,合约名称 +isPrivate 布尔类型,是否为私有项目 +dbUrl 字符串类型,数据库的URI +dbUserName 字符串类型,数据库的用户名 +dbPWD 字符串类型,数据库密码 +accessPolicy 若为“DAC”,则实现直接访问控制,若为“NAC”则没有访问控制 +tableName 字符串类型,数据库的表名 +fieldList 字符串列表,数据库的字段列表 +defaultAccept 布尔值,表示申请时是否默认有权 +============= ====================================================== + +.. _请求示例-72: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.contractName = "MySQLFromTemplate"; + req.action = "generateMySQLProject"; + req.pubKey = global.sm2Key.publicKey; + req.isPrivate = true; + req.tableName = "data"; + req.dbUrl = "jdbc:mysql://xxx:xxx/xxx"; + req.dbUserName = "loushuai"; + req.dbPWD = "loushuai"; + req.fieldList = [{"name":"名字","code":"*"}]; + req.basicInfo={"type":"所属分类","name":"资源名称"}; + req.accessPolicy = "DAC"; + req.defaultAccept = true; + //global.wssocket为建立好的连接 + global.wssocket.send(JSON.stringify(req)); + +.. _返回结果-43: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true + } + +CSV接入合约 +^^^^^^^^^^^ + +.. _参数-73: + +参数 +'''' + +================= ====================================================== +字段 值 +================= ====================================================== +action generateCSVProject +contractName 字符串类型,合约名称 +base64EncodedData 字符串类型,通过base64编码后的CSV文件内容 +isPrivate 可选字段,布尔类型,是否为私有项目 +accessPolicy 若为“DAC”,则实现直接访问控制,若为“NAC”则没有访问控制 +defaultAccept 可选字段,布尔值,表示申请时是否默认有权 +================= ====================================================== + +.. _请求示例-73: + +请求示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.contractName = "CSVFromTemplate"; + req.action = "generateCSVProject"; + req.pubKey = global.sm2Key.publicKey; + req.isPrivate = true; + req.tableName = "data"; + req.accessPolicy = "DAC"; + req.defaultAccept = true; + req.base64EncodedData = "bmFtZSwgc2NvcmUsCmphY2ssIDkwLApsdWN5LCA5MQo="; + //global.wssocket为建立好的连接 + global.wssocket.send(JSON.stringify(req)); + +.. _返回结果-44: + +返回结果 +'''''''' + +.. code:: json + + { + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true + } + +-------------- + +路由节点WebSocket接口 +--------------------- + +.. _用户管理类-2: + +用户管理类 +~~~~~~~~~~ + +.. _获取session-1: + +获取Session +^^^^^^^^^^^ + +登录前获取session以便进行签名。 + +.. _参数-74: + +参数 +'''' + +====== ============ +字段 值 +====== ============ +action getSessionID +====== ============ + +.. _请求示例-74: + +请求示例 +'''''''' + +:: + + var req = {}; + req.action = "getSessionID"; + wssocket.send(JSON.stringify(req)); + +.. _返回结果-45: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onSessionID", + "session": "9782323_session" + } + +.. _用户登录-1: + +用户登录 +^^^^^^^^ + +用户进行公私钥身份验证,需先调用“getSessionID”获取sessionID以便于签名。 + +.. _参数-75: + +参数 +'''' + +====== ===== +字段 值 +====== ===== +action login +====== ===== + +.. _请求示例-75: + +请求示例 +'''''''' + +:: + + var loginParam = {}; + loginParam.pubKey = global.sm2Key.publicKey; + loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); + loginParam.action = "login"; + wssocket.send(JSON.stringify(loginParam)); + +.. _返回结果示例-25: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onLogin", + "data": "CenterManager" + } + +用户获取当前角色(删除) +^^^^^^^^^^^^^^^^^^^^^^ + +用户根据登录时的公钥获取对应的角色,如果是第一次登录则此时的公钥默认称为准入管理员 + +.. _参数-76: + +参数 +'''' + +====== ======= +字段 值 +====== ======= +action getRole +====== ======= + +.. _请求示例-76: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "getRole"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果示例-26: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onGetRole", + "data": "CenterManager" + } + +.. _申请角色-1: + +申请角色 +^^^^^^^^ + +在准入管理员界面可以申请称为组网中某个节点的节点管理员 + +.. _参数-77: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action applyRole +role 申请的角色名称 +====== ============== + +.. _请求示例-77: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "applyRole"; + param.role=" + wssocket.send(JSON.stringify(param)); + +.. _返回结果示例-27: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onApplyRole", + "data": "failed" + } + +添加节点 +^^^^^^^^ + +.. _参数-78: + +参数 +'''' + +========== ================ +字段 值 +========== ================ +action addNode +nodePubKey 要添加的节点公钥 +========== ================ + +.. _请求示例-78: + +请求示例 +^^^^^^^^ + +:: + + var req = {}; + //某节点的publicKey可通过连接该节点,并通过"获取节点配置信息"接口获取 + req.nodePubKey = publicKey; + req.action = "addNode"; + wssocket.send(JSON.stringify(req)); + +.. _删除用户角色-1: + +删除用户角色 +^^^^^^^^^^^^ + +.. _参数-79: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action delete +pubKey 对应用户的公钥 +====== ============== + +.. _请求示例-79: + +请求示例 +'''''''' + +:: + + var deleteInfo = {}; + deleteInfo.pubKey = user.publicKey; + deleteInfo.action = "delete"; + wssocket.send(JSON.stringify(deleteInfo)); + +.. _返回结果示例-28: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onDelete", + "data": "success" + } + +.. _查看授权用户列表-1: + +查看授权用户列表 +^^^^^^^^^^^^^^^^ + +查看准入管理员当前组网中已经授权的节点管理员 + +.. _参数-80: + +参数 +'''' + +====== ============ +字段 值 +====== ============ +action listAllUsers +====== ============ + +.. _请求示例-80: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "onListAllUsers"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果示例-29: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onListAllUsers", + "kv": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": " NodeManager" + }, + "time": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": 1587398989914 + } + } + +.. _查看申请用户列表-1: + +查看申请用户列表 +^^^^^^^^^^^^^^^^ + +.. _参数-81: + +参数 +'''' + +====== ============= +字段 值 +====== ============= +action listApplyList +====== ============= + +.. _请求示例-81: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "onListApplyList"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-46: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onListApplyList", + "kv": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": " NodeManager" + }, + "time": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": 1587398989914 + } + } + +查看用户类型分布 +^^^^^^^^^^^^^^^^ + +.. _参数-82: + +参数 +'''' + +====== ============= +字段 值 +====== ============= +action queryUserStat +====== ============= + +.. _请求示例-82: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "onQueryUserStat"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果示例-30: + +返回结果示例 +'''''''''''' + +.. code:: json + + { + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 + } + +节点管理类 +~~~~~~~~~~ + +查看节点列表 +^^^^^^^^^^^^ + +查看该用户有权限查看的节点列表(仅准入管理员及合约管理者可用) + +.. _参数-83: + +参数 +'''' + +====== ========= +字段 值 +====== ========= +action listNodes +====== ========= + +.. _请求示例-83: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "listNodes"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-47: + +返回结果 +'''''''' + +.. code:: json + + { + "offline": [{ + "key": "0431e31...40009b4f06d", + "value": "0431e311bd708...b4f06d" + }], + "action": "onListNodes", + "online": [{ + "contracts": [], + "pubKey": "0431e311...09b4f06d", + "nodeName": "NewNodeName", + "udpID": "528822126", + "cimanager": "" + }] + } + +查看可信执行集群列表 +^^^^^^^^^^^^^^^^^^^^ + +查看该用户有权限查看的节点列表(仅中心管理员及合约管理者可用) + +.. _参数-84: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action listTrustUnits +====== ============== + +.. _请求示例-84: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "listTrustUnits"; + wssocket.send(JSON.stringify(param)); + +.. _返回结果-48: + +返回结果 +'''''''' + +.. code:: json + + { + "data": [{ + "key": "0470b2f27f4f6…1cb855f1ecec11", + "value": "[...]" + }], + "action": "onListTrustUnits" + } + +建立可信执行集群 +^^^^^^^^^^^^^^^^ + +.. _参数-85: + +参数 +'''' + +====== ====================== +字段 值 +====== ====================== +action createTrustUnit +data 节点公钥组成的Json数组 +Msg 集群名称 +====== ====================== + +.. _请求示例-85: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "createTrustUnit"; + param.data = "[\"382r0934309t...\",\"345343rr3f34...\"]"; + param.msg = "newUnit1"; + global.wssocket.send(JSON.stringify(param)); + +.. _返回结果-49: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onCreateTrustUnit", + "status": "Success" + } + +删除可信执行集群 +^^^^^^^^^^^^^^^^ + +.. _参数-86: + +参数 +'''' + +====== =============== +字段 值 +====== =============== +action deleteTrustUnit +data 可信执行集群ID +====== =============== + +.. _请求示例-86: + +请求示例 +'''''''' + +:: + + var param = {}; + param.action = "deleteTrustUnit"; + param.data = "0475d34rf3434..._1583410158761"; + global.wssocket.send(JSON.stringify(param)); + +.. _返回结果-50: + +返回结果 +'''''''' + +.. code:: json + + { + "action": "onDeleteTrustUnit", + "status": "Success" + } + +.. _日志查看类-2: + +日志查看类 +~~~~~~~~~~ + +查看组网管理操作的统计 +^^^^^^^^^^^^^^^^^^^^^^ + +.. _参数-87: + +参数 +'''' + +====== ============== +字段 值 +====== ============== +action queryActionLog +date 当前时间 +====== ============== + +.. _请求示例-87: + +请求示例 +'''''''' + +:: + + request.action = "onQueryActionLog"; + request.date = new Date().getTime() - 24 * 3600 * 1000 * n; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-51: + +返回结果 +'''''''' + +.. code:: json + + { "action":"onQueryActionLog", + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" + } + +查看本地近n日合约日志 +^^^^^^^^^^^^^^^^^^^^^ + +.. _参数-88: + +参数 +'''' + +====== ==================== +字段 值 +====== ==================== +action listLocalContractLog +date 当前时间 +====== ==================== + +.. _请求示例-88: + +请求示例 +'''''''' + +:: + + request.action = "listLocalContractLog"; + request.date = new Date().getTime() - 24 * 3600 * 1000 * n; + wssocket.send(JSON.stringify(request)); + +.. _返回结果-52: + +返回结果 +'''''''' + +.. code:: json + + { + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7b...\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" + } + +-------------- + +Bash接口 +-------- + +已废弃。可使用BDWareConfigTool代替。 通过命令行发送Socket指令, +执行调用\ ``ContractController``\ 类中方法, 完成以下功能. +(需要在本机的``1615``\ 端口运行\ ``ContractManager``\ 实例) + +.. figure:: ./_static/imgs/bash-api.png + :alt: Bash接口功能示意图 + + Bash接口功能示意图 + +指令 +~~~~ + +.. code:: bash + + java -jar yjs.jar function_name arguments + +``function_name``\ 为调用的方法名; + +``arguments``\ 为方法参数. + +.. _启动合约-2: + +启动合约 +~~~~~~~~ + +.. _参数-89: + +参数 +^^^^ + +``function_name``\ 为\ ``startContract``; + +``arguments``\ 为启动合约需要的参数, 包括合约类型\ ``type``, +合约ID\ ``id``, 合约脚本\ ``script``. + +指令示例 +^^^^^^^^ + +.. code:: bash + + java -jar yjs.jar startContract "{\"type\":\"Algorigthm\",\"id\":\"656565\",\"script\":\"contract c{function main(arg){return arg/1.0+1;}}\"}" + +.. _调用合约-2: + +调用合约 +~~~~~~~~ + +.. _参数-90: + +参数 +^^^^ + +``function_name``\ 为\ ``executeContract``; + +``arguments``\ 为调用合约需要的参数, 包括调用参数\ ``arg``, +合约ID\ ``contractID``. + +.. _指令示例-1: + +指令示例 +^^^^^^^^ + +.. code:: bash + + java -jar yjs.jar executeContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" + +.. _停止合约-1: + +停止合约 +~~~~~~~~ + +.. _参数-91: + +参数 +^^^^ + +``function_name``\ 为\ ``stopContract``; + +``arguments``\ 为调用合约需要的参数, 即合约ID\ ``contractID``. + +.. _指令示例-2: + +指令示例 +^^^^^^^^ + +.. code:: bash + + java -jar yjs.jar stopContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" + +停止全部合约 +~~~~~~~~~~~~ + +.. _参数-92: + +参数 +^^^^ + +``function_name``\ 为\ ``stopAllContracts``. + +.. _指令示例-3: + +指令示例 +^^^^^^^^ + +.. code:: bash + + java -jar yjs.jar stopAllContracts + +查询全部合约 +~~~~~~~~~~~~ + +.. _参数-93: + +参数 +^^^^ + +``function_name``\ 为\ ``listContracts``. + +.. _指令示例-4: + +指令示例 +^^^^^^^^ + +.. code:: bash + + java -jar yjs.jar listContracts diff --git a/source/IDEUsage.rst b/source/IDEUsage.rst new file mode 100644 index 0000000..2fa95fd --- /dev/null +++ b/source/IDEUsage.rst @@ -0,0 +1,672 @@ +BDContract管理界面 +================== + +-------------- + +合约节点管理界面 +---------------- + +该界面的使用地址为:\ `NodePortal.html `__ + +用户管理菜单 +~~~~~~~~~~~~ + +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +概览 +^^^^ + +|nodeUserManager| +节点用户管理页面一共有四个模块:用户情况、用户活跃统计、授权用户管理、未授权用户管理。 + +用户类型分布 +^^^^^^^^^^^^ + +主要统计当前节点管理员所拥有的四种角色的数量:合约提供者、合约管理员、合约使用者 +|userList| + +用户活跃统计 +^^^^^^^^^^^^ + +|userActive| 统计30天之内\ **登录**\ 、\ **授权**\ 、\ **申请**\ 的次数 + +当前用户信息 +^^^^^^^^^^^^ + +|nodeInfo| \* +在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录节点管理员界面,可以将自己的公私钥复制到这个文本框中。 +\* +将自己的公私钥复制完成之后要点击\ **导入公钥**\ ,将公钥加入到节点管理员本地 +\* +然后在\ **本地公钥**\ 中可以看见公钥的前五位,选择自己的公钥,将在\ **我的权限**\ 中展示出当前选择的公钥的角色,如果是还没有在中心管理员认证的节点则默认为\ **Anonymous** +\* +如果不是节点管理员,想要加入某个中心管理员的网络,那么要在中心管理员所在的用户管理中用自己的公私钥导入后进行认证。 +\* +如果想要行使更多关于合约的操作,则需要认证不同的角色:合约管理员、合约使用者、合约提供者,然后进行\ **角色认证** + +授权与非授权用户列表 +^^^^^^^^^^^^^^^^^^^^ + +|roleAuth| +在节点管理员认证角色之后,节点管理员登录会在\ **未授权角色管理**\ 表格中看见带有公钥的申请信息,如果同意,则点击\ **授权**\ ,如果不同意点击\ **忽略**\ 就可以。 +授权之后将在\ **授权角色管理**\ 表格中看见授权后的节点列表。如果节点管理员想要移除某个节点的角色,则在授权角色管理列表中\ **删除**\ 即可。 + +合约代码管理菜单 +~~~~~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/codeManageMenu.png + :alt: codeManageMenu + + codeManageMenu + +合约文件 +^^^^^^^^ + +.. figure:: ./_static/imgs/codeManage1.png + :alt: codeManage1 + + codeManage1 + +在合约代码管理菜单中,用户可以看到公共合约以及个人私有合约。 +|codeManage1-1| + +对于公共合约,节点管理员可以对其中文件进行删除和上传操作,可以对合约项目进行下载和删除操作。 +|codeManage1-2| + +对于私有合约,合约提供者可以对其中文件进行删除和上传操作,可以对合约项目进行下载、删除和传至公共合约目录操作。 + +以下是对合约文件进行操作的示例。 + +上传文件 +^^^^^^^^ + +.. figure:: ./_static/imgs/codeManage6.png + :alt: codeManage6 + + codeManage6 + +删除 +^^^^ + +.. figure:: ./_static/imgs/codeManage5.png + :alt: codeManage5 + + codeManage5 + +传至公共 +^^^^^^^^ + +.. figure:: ./_static/imgs/codeManage7.png + :alt: codeManage7 + + codeManage7 + +下拉框 +^^^^^^ + +.. figure:: ./_static/imgs/codeManage2.png + :alt: codeManage2 + + codeManage2 + +四个下拉框中,可以分别对合约状态保存模式、已启动合约实例、节点所在集群以及结果校验方式进行选择。 + +按钮操作 +^^^^^^^^ + +.. figure:: ./_static/imgs/codeManage3.png + :alt: codeManage3 + + codeManage3 + +启动 +^^^^ + +在文件列表中选择合约文件之后,在合约运行模式中选择“单节点执行”,点击启动按钮,会启动指定文件,并在结果显示框中显示返回结果。 + +启动P2P集群合约 +^^^^^^^^^^^^^^^ + +在文件列表中选择合约文件之后,在合约运行模式中选择该可信合约运行的合约集群,点击启动按钮,会在该集群的所有节点上启动指定文件,并在结果显示框中显示返回结果。 + +启动全部 +^^^^^^^^ + +在合约运行模式中选择“单节点执行”,点击启动全部按钮,会启动合约文件列表中所有合约。 + +停止P2P集群合约 +^^^^^^^^^^^^^^^ + +在已启动合约实例的下拉框中选择一个合约实例,在合约运行模式中选择该可信合约运行的合约集群,点击停止按钮,会在该集群的所有节点上终止这个合约进程。 + +停止 +^^^^ + +在已启动合约实例的下拉框中选择一个合约实例,点击停止按钮,会终止这个合约进程。 + +停止全部 +^^^^^^^^ + +点击停止全部按钮,会停止该节点上运行的所有合约实例。 + +静态分析 +^^^^^^^^ + +在合约文件列表中选择合约文件,并在合约实例下拉框中选择合约实例,点击静态分析按钮,会对该合约进行静态分析,并在结果显示框中显示返回结果。 + +分发合约 +^^^^^^^^ + +在合约文件列表中选择合约项目,并在合约运行模式中选择一个集群,点击分发合约按钮,会将该合约项目打包为ypk分发给这个集群中的所有节点。 + +返回结果 +^^^^^^^^ + +.. figure:: ./_static/imgs/codeManage4.png + :alt: codeManage4 + + codeManage4 + +返回结果显示中显示一些操作的返回结果。 + +合约权限配置 +^^^^^^^^^^^^ + +在启动合约之后,如果当前用户的角色可以查看已经启动合约进程,那么在选定查看合约进程时将会在右下方展示当前合约的IO权限。 +|permissionShow| + +如果选中的合约没有IO权限,则在当前权限的展示框中提示\ **当前合约没有IO权限** +|nullPermission| + +当前用户是合约管理员时可以对已有的合约IO权限进行修改。系统会提示修改后合约将有可能不会正常运行,如果还是确定要取消,那么点击\ **确定** +即可,反之点击\ **关闭** |updatePermission| + +点击关闭或者打开之后,下一次查看同一个合约代码的进程将会默认显示最近一次修改之后的IO权限。 +|closePermission| + +合约实例管理菜单 +~~~~~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/nodeInstancesPage.png + :alt: nodeInstancesPage + + nodeInstancesPage + +合约实例管理菜单显示了该节点当前的所有合约实例, +用户可查看合约实例的状态, 并对合约实例进行执行或状态迁移的操作. + +合约实例列表 +^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/nodeInstancesList.png + :alt: nodeInstancesList + + nodeInstancesList + +该列表显示了当前节点的所有合约实例信息, 包括合约ID, 合约名称, +合约类型合约状态, 合约进程端口, 合约调用次数, 合约流量, 及合约占用内存, +集群合约的结果校验模式. + +合约实例执行 +^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/chooseInstance.png + :alt: chooseInstance + + chooseInstance + +用户可在合约实例的选择下拉框中选择合约实例, 对该合约实例进行操作. + +.. figure:: ./_static/imgs/intanceExecute.png + :alt: intanceExecute + + intanceExecute + +选择合约实例后, 用户可在“方法”的下拉框中选择该合约的方法名, +在“参数”输入框中输入方法的参数, 点击“执行”. + +用户还可点击“动态分析执行”进行带有动态分析结果的执行. + +若该合约为单点合约, 则合约在单点执行; 若该合约为集群合约, +则该合约在该集群的所有节点上执行. + +合约实例执行结果 +^^^^^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/executeResult.png + :alt: executeResult + + executeResult + +合约实例的执行完成后的结果显示在“执行结果”区域中, 包括该次执行的ID, +执行成功/失败, 执行时间, 及执行结果. + +.. figure:: ./_static/imgs/analysisExecuteResult.png + :alt: analysisExecuteResult + + analysisExecuteResult + +若该合约的执行方式为“动态分析执行”, 则结果框内除执行结果, +还会显示该次执行的动态分析结果. + +合约状态迁移 +^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/memoryDump.png + :alt: memoryDump + + memoryDump + +对于支持用户手动迁移的合约实例, +用户可点击“本地状态保存”对合约实例的状态进行保存, +或从合约的TimeTravel列表中选择已保存的合约实例, +将合约状态迁移到对应时刻. + +日志管理菜单 +~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/logMenu.png + :alt: logMenu + + logMenu + +该菜单是对该节点本地节点日志以及合约日志的统计结果展示。 + +其中,节点管理员可以查看节点日志的相关数据;合约管理者及合约使用者可以查看该节点本地合约日志的相关数据。 + +日志统计图 +^^^^^^^^^^ + +.. figure:: ./_static/imgs/log1.png + :alt: log1 + + log1 + +各类平台操作百分比 +^^^^^^^^^^^^^^^^^^ + +该图默认显示近2日各类平台操作占比的饼图,其中平台操作分为登陆类、用户类、日志类、合约类、维护类以及其他类这六类。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比会同步更新。 + +各类合约操作百分比 +^^^^^^^^^^^^^^^^^^ + +合约操作分为启动、终止、静态分析和执行这四类,该图为近2日对各类合约操作占比的饼图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比会同步更新。 + +每日平台使用统计 +^^^^^^^^^^^^^^^^ + +该图为近2日平台操作次数统计的折线图。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日平台使用统计折线图会同步更新。 + +每日合约使用统计 +^^^^^^^^^^^^^^^^ + +该图为近2日对该节点上合约的操作次数统计的折线图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日合约使用统计折线图会同步更新。 + +日志详情 +^^^^^^^^ + +节点日志详情 +^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/log2.png + :alt: log2 + + log2 + +节点日志详情表是对节点日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比和每日平台使用统计会同步更新。 + +合约日志详情 +^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/log3.png + :alt: log3 + + log3 + +合约日志详情表是对合约日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比和每日合约使用统计会同步更新。 + +节点管理菜单 +~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/nodeConfig.png + :alt: nodeConfig + + nodeConfig + +节点管理菜单显示了该节点的配置信息及所属可信执行集群信息. + +节点配置 +^^^^^^^^ + +.. figure:: ./_static/imgs/nodeConfigChange.png + :alt: nodeConfigChange + + nodeConfigChange + +节点管理员可查看该节点的配置信息, 包括节点名称, 节点YJS路径, +节点的网络中心节点, 节点管理员还可对以上配置进行修改. + +若节点管理员修改了节点的网络中心, 该节点后重新想改节点连接, +整个页面刷新重载. + +节点可信执行集群列表 +^^^^^^^^^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/nodeUnits.png + :alt: nodeUnits + + nodeUnits + +节点管理员可查看节点所属的可信执行集群信息, 包括集群创建者, 集群ID, +集群中节点数目, 集群中节点的信息. + +-------------- + +节点Licence配置 +^^^^^^^^^^^^^^^ + +.. figure:: ./_static/imgs/nodeLicence.png + :alt: nodeLicence + + nodeLicence + +用户可以查看该节点的Licence及过期时间, 还可申请Licence, 上传Licence, +保存节点UUID. + +智能合约在线编辑器 +------------------ + +用户与账号 +~~~~~~~~~~ + +创建账号 +^^^^^^^^ + +申请授权 +^^^^^^^^ + +创建项目 +~~~~~~~~ + +新建文件 +^^^^^^^^ + +.. _上传文件-1: + +上传文件 +^^^^^^^^ + +启动合约 +~~~~~~~~ + +.. figure:: ./_static/imgs/contractMode.png + :alt: contractMode + + contractMode + +####正常模式 点击左侧启动按钮,以正常模式启动合约。 + +####debug模式 +点击右侧debug按钮,以debug模式启动合约。目前约定debug模式合约通过executeContract调用正常模式合约时,返回正常模式合约文档中的返回结果示例。 + +调用合约 +~~~~~~~~ + +###生成文档 |genReadme| + +启动合约后点击“生成文档”按钮,可以通过各export函数的@Description / +@Param / @Result 对合约进行调用及结果返回,从而生成合约的说明文档。 + +-------------- + +路由准入管理界面 +---------------- + +权限申请与授权 +~~~~~~~~~~~~~~ + +仪表盘 +~~~~~~ + +仪表盘为提供对准入节点中用户数量,合约数量,节点数量的概览。 + +整体视图 +~~~~~~~~ + +|dashboard| +一共分为四个模块,一个模块是用户、合约、节点数量的概览,然后分别是这三个数量的详细分类的数据统计情况。 + +节点数目 +~~~~~~~~ + +|node| 当前在线和离线节点统计 + +.. _用户类型分布-1: + +用户类型分布 +~~~~~~~~~~~~ + +|userAll| +当前准入节点所在组网中的节点管理员、准入管理员的数量和申请中节点的数量 + +合约调用情况 +~~~~~~~~~~~~ + +|contract| +当前准入节点所在组网中所有合约中事件、多点执行、ws调用、Http调用的折线统计图。 + +用户管理 +~~~~~~~~ + +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +.. _概览-1: + +概览 +~~~~ + +|centerManager| 用户管理页面一共有四个模块。 + +.. _用户类型分布-2: + +用户类型分布 +~~~~~~~~~~~~ + +主要统计当前中心管理员所管理的网络中有多少节点管理员,多少个中心管理以及申请节点管理员的数量 +|userList| + +30天内的申请情况统计 +~~~~~~~~~~~~~~~~~~~~ + +|userApplyGraph| +统计30天之内申请节点管理员的数量和授权成为节点管理员的数量 + +.. _当前用户信息-1: + +当前用户信息 +~~~~~~~~~~~~ + +|authNodeManager| \* +在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录中心管理员界面,可以将自己的公私钥复制到这个文本框中。 +\* +将自己的公私钥复制完成之后要点击\ **导入公钥**\ ,将公钥加入到中心管理员本地 +\* +然后在\ **本地公钥**\ 中可以看见公钥的前五位,选择自己的公钥,将在\ **我的权限**\ 中展示出当前选择的公钥的角色,如果是中心管理员则拥有中心管理员的一切权限。 +\* +如果不是中心管理员或者节点管理员,想要加入当前中心管理员的网络,那么可以在下面的选择框中选中节点管理员,进行\ **角色认证**\ 。 + +.. _授权与非授权用户列表-1: + +授权与非授权用户列表 +~~~~~~~~~~~~~~~~~~~~ + +在中心管理员当前用户信息申请之后,中心管理员登录会在\ **未授权用户管理**\ 表格中看见带有公钥的申请信息,如果同意,则点击\ **授权**\ ,如果不同意点击\ **忽略**\ 就可以,此时这个申请就无效。 +|authMan| +授权之后将在\ **授权用户管理**\ 表格中看见授权后的节点列表。如果中心管理员想要移除某个节点管理员的某项角色,则在授权用户管理列表中选择相应的角色,然后点击\ **删除**\ 即可删除选中的角色。 +|authMana| + +节点管理 +~~~~~~~~ + +.. figure:: ./_static/imgs/centerNodePage.png + :alt: centerNodePage + + centerNodePage + +节点管理为Manager对连接到自己的Cluster节点进行管理的页面, +仅Manager管理员及合约管理者可见. +Manager管理员及合约管理者可在本页面查看节点信息, 并管理可信执行集群. + +.. _概览-2: + +概览 +~~~~ + +.. figure:: ./_static/imgs/centerNodePreview.png + :alt: centerNodePreview + + centerNodePreview + +概览中显示了该Manager节点所管理的所有节点的统计信息, 包括总节点数量, +总合约数量, 总订阅事件数量, 及可信执行集群数量, +右侧的饼图则为节点的分别处于Online/Offline的数量统计. + +节点列表 +~~~~~~~~ + +.. figure:: ./_static/imgs/centerNodeList.png + :alt: centerNodeList + + centerNodeList + +节点列表显示了用户有权限查看的节点信息(Manager管理员可查看全部节点, +合约管理者可查看自己负责管理的Online节点). 包括节点的名称, 状态, +合约数目, 订阅事件数目, 用于节点间P2P通信的PeerID, +用于节点间UDP通信的UDPID, 及节点公钥. + +可信执行集群列表 +~~~~~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/centerNodeUnits.png + :alt: centerNodeUnits + + centerNodeUnits + +可信执行集群列表显示了用户有权限查看的可信执行集群信息(Manager管理员可查看全部集群, +合约管理者可查看自己创建的集群). 包括集群的创建者, 集群ID, +集群中节点数目, 以及集群中节点的信息. + +用户可点击列表表项的“删除”按钮, 将该集群删除. + +创建可信执行集群 +~~~~~~~~~~~~~~~~ + +.. figure:: ./_static/imgs/centerNodeUnitCreate.png + :alt: centerNodeUnitCreate + + centerNodeUnitCreate + +用户可以通过多选节点, 创建新的可信执行集群. +用户可以选择的节点为自己有权限查看的节点, +即Manager管理员从全部节点中选择, +合约管理者可从自己负责管理的Online节点中选择). 选择后点击提交, +即可看到创建成功的提示信息, 该集群将随即显示在可信执行集群列表中. +集群名称由创建者选取, 不能含有双引号, +该名称为合约管理者选择集群时的可见标识. + +日志管理 +~~~~~~~~ + +日志管理主要展示准入节点的各项日志信息,一共分为六个模块。 ### 概览 +|log| + +管理操作分类统计(2日) +~~~~~~~~~~~~~~~~~~~~~~~ + +|operator| +两日内所有管理类操作的统计饼图,管理类操作主要分为登录类、日志类、维护类、用户类。 + +管理操作每日统计(2日) +~~~~~~~~~~~~~~~~~~~~~~~ + +|everyLog| 两日内管理类所有的操作每日操作统计 + +合约操作分类统计(2日) +~~~~~~~~~~~~~~~~~~~~~~~ + +|contractLog| +两日内合约操作分类统计饼图,合约操作主要分为连接类和状态更新类。 + +合约操作每日统计(2日) +~~~~~~~~~~~~~~~~~~~~~~~ + +|contracteveryLog| 两日内合约操作数量折线统计图。 + +管理操作日志列表 +~~~~~~~~~~~~~~~~ + +|opList| +管理操作日志的详细信息列表。包括日志时间,管理操作名称,操作对应的节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +合约操作日志列表 +~~~~~~~~~~~~~~~~ + +|contractList| +合约操作日志详细信息列表。包括日志产生时间,合约操作名称,合约操作节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +设置 +~~~~ + +设置页面是节点证书的状态展示以及配置节点证书 + +.. _概览-3: + +概览 +~~~~ + +.. figure:: ./_static/imgs/set.jpg + :alt: set + + set + +证书状态 +~~~~~~~~ + +|licence| 证书状态主要包括许可到期时间和许可节点数量。 + +配置证书 +~~~~~~~~ + +|plicence| 配置证书模块可以下载节点ID文件或者输入证书信息进行提交。 + +.. |nodeUserManager| image:: ./_static/imgs/nodeUserManager.jpg +.. |userList| image:: ./_static/imgs/userList.jpg +.. |userActive| image:: ./_static/imgs/userActive.jpg +.. |nodeInfo| image:: ./_static/imgs/nodeInfo.jpg +.. |roleAuth| image:: ./_static/imgs/roleAuth.jpg +.. |codeManage1-1| image:: ./_static/imgs/codeManage1-1.png +.. |codeManage1-2| image:: ./_static/imgs/codeManage1-2.png +.. |permissionShow| image:: ./_static/imgs/permissionShow.png +.. |nullPermission| image:: ./_static/imgs/nullPermission.png +.. |updatePermission| image:: ./_static/imgs/updatePermission.png +.. |closePermission| image:: ./_static/imgs/closePermission.png +.. |genReadme| image:: ./_static/imgs/genReadme.png +.. |dashboard| image:: ./_static/imgs/dashboard.jpg +.. |node| image:: ./_static/imgs/node.jpg +.. |userAll| image:: ./_static/imgs/userAll.jpg +.. |contract| image:: ./_static/imgs/contract.jpg +.. |centerManager| image:: ./_static/imgs/centerManager.jpg +.. |userApplyGraph| image:: ./_static/imgs/userApplyGraph.jpg +.. |authNodeManager| image:: ./_static/imgs/authNodeManager.jpg +.. |authMan| image:: ./_static/imgs/authMan.jpg +.. |authMana| image:: ./_static/imgs/authMana.jpg +.. |log| image:: ./_static/imgs/log.jpg +.. |operator| image:: ./_static/imgs/operator.jpg +.. |everyLog| image:: ./_static/imgs/everyLog.jpg +.. |contractLog| image:: ./_static/imgs/contractLog.jpg +.. |contracteveryLog| image:: ./_static/imgs/contracteveryLog.jpg +.. |opList| image:: ./_static/imgs/opList.jpg +.. |contractList| image:: ./_static/imgs/contractList.jpg +.. |licence| image:: ./_static/imgs/licence.jpg +.. |plicence| image:: ./_static/imgs/plicence.jpg + diff --git a/source/InstallTips.rst b/source/InstallTips.rst new file mode 100644 index 0000000..3733755 --- /dev/null +++ b/source/InstallTips.rst @@ -0,0 +1,223 @@ +BDContract安装说明 +================== + +-------------- + +依赖环境的安装 +-------------- + +1.安装Java1.8环境。 + +例如,在Ubuntu下使用apt-get进行安装: + +.. code:: bash + + apt-get install openjdk-8-jre + +在Centos环境下,使用yum进行安装: + +.. code:: bash + + yum install java-1.8.0-openjdk + +如果是离线环境,可先下载openjdk的安装包后进行离线安装。 + +Ubuntu下 + +.. code:: bash + + dpkg -i jdk-8uxxxxx.deb + +在Centos环境下,使用yum进行离线安装: + +.. code:: bash + + yum localinstall jdk-8u271-linux-xxx.rpm + +2.安装wget与unzip。 例如,在Ubuntu下使用apt-get进行安装: + +.. code:: bash + + apt-get install unzip + apt-get install wget + +-------------- + +网络拓扑说明 +------------ + +部署数瑞智能合约引擎最小仅需一个节点,此时可用作调试、测试,不能通过多节点模式来实现可信的计算。 +单节点部署时,可通过配置账本实现“防抵赖”的计算,但不能实现“难篡改”的计算。 + +多节点部署时可参考下图,包含三种逻辑节点,同一虚拟机可安装一至三种节点。 + +1)账本节点。即数瑞图式账本。 + +2)合约节点。运行代码逻辑,并通过内存缓存实现高响应的模块。与其他合约节点组成可信计算网络。 + +3)路由节点。各个合约节点的路由信息。一般单个路由节点可支持最高1000合约节点。可视情况部署多个路由节点,并在路由节点之间配置实现更大规模的节点组网。 + +一般地,同一虚拟机下,会部署\ **合约节点与账本节点**\ 。 + +.. figure:: _static/imgs/deploytopology.png + :alt: deploytopology + + deploytopology + +-------------- + +智能合约节点安装 +---------------- + +打开\ `安装包下载链接 `__ +其中,下载\ ``bdserver-lite.zip``\ 或\ ``bdserver.zip``\ ,其中,\ ``bdserver.zip``\ 包含更多示例和文档。 +下载之后解压并启动。 + +.. code:: bash + + unzip -d ./bdserver bdserver-lite.zip + cd bdserver + chmod +x *.sh + sh cmstart.sh + +-------------- + +路由准入节点安装 +---------------- + +打开\ `安装包下载链接 `__ +其中,下载\ ``bdserver-cluster.zip``\ 。 下载之后解压并启动。 + +.. code:: bash + + unzip -d ./bdcluster bdserver-cluster.zip + cd bdcluster + chmod +x *.sh + sh ncstart.sh + +-------------- + +文件说明 +-------- + +智能合约节点 +~~~~~~~~~~~~ + +.. figure:: _static/imgs/dirstructure.png + :alt: bdserver目录 + + bdserver目录 + +该目录下的文件说明: + +1.cmstart.sh +该脚本用于启动合约引擎。合约引擎默认监听8080端口,可通过修改cmstart.sh来修改合约引擎的监听端口。 + +2.BDWareProjectDir 该目录存放了本节点的所有合约项目。 + +3.WebContent 该目录存放了本节点的前端代码。 + +4.cp, 该目录存放了yjs.jar,为启动合约实例所需的jar。 + +5.bdserver.jar 对外提供http/websocket的服务器逻辑。 + +6.updateContract.sh 用于升级的脚本。 + +路由准入节点 +~~~~~~~~~~~~ + +安装脚本会自动下载安装并解压为bdcluster目录。 该目录下的文件说明: + +1.ncstart.sh +该脚本用于启动节点准入中心。默认监听1718端口。可通过修改ncstart.sh来修改监听的端口。 + +2.WebContent 该目录存放了准入中心的前端代码。 + +3.bdcluster.jar 准入中心的后端。 + +-------------- + +升级流程 +-------- + +合约节点 +~~~~~~~~ + +在命令行中输入: + +.. code:: bash + + sh updateContract.sh + +亦可通过\ `public.internetapi.cn `__\ ,下载最新文件,单独升级yjs.zip/bdserver-jar.zip/AgentWebContent来升级。 + +.. _路由准入节点-1: + +路由准入节点 +~~~~~~~~~~~~ + +.. code:: bash + + sh updateCluster.sh + +亦可通过\ `public.internetapi.cn `__\ ,下载最新文件,单独升级bdserver-cluster.zip/ClusterWebContent.zip来升级。 + +-------------- + +使用说明 +-------- + +通过参考界面使用 +~~~~~~~~~~~~~~~~ + +当保留了WebContent目录的情况下,可使用浏览器进行配置。 +更多请使用见左侧文档\ `BDContract参考界面使用说明 <./IDEUsage.html>`__\ 。 + +BDWare OnlineIDE +^^^^^^^^^^^^^^^^ + +打开\ `BDWare OnlineIDE <../OnlineIDE.html>`__\ 。 + +BDWare NodePortal +^^^^^^^^^^^^^^^^^ + +打开\ `BDWare NodePortal <../NodePortal.html>`__\ 。 + +如需组网,使用跨节点功能,则需安装路由准入中心。并按以下步骤进行配置。涉及两组公私钥。 +第一组公私钥为合约节点的、有NodeManager权限的公私钥。 +第二组公私钥为路由准入节点的、有CenterManager权限的公私钥。 + +1.打开NodePortal.html,复制该节点的NodeManager公私钥。 + +2.打开CenterPortal.html,点击右上角,将上述的NodeManager公私钥导入;并选择“NodeManager”进行身份认证。 + +3.在CenterPortal.html中切换CenterManager的公私钥,点左侧的“用户管理”,通过NodeManager的认证请求。 + +4.使用NodeManager权限的公私钥打开NodePortal.html,点击:“节点管理”菜单,并配置加入网络。 +其中,加入网络的格式为:ws://centerportal的ip:端口+1。 |配置示例| + +通过SDK使用 +~~~~~~~~~~~ + +基础知识 +^^^^^^^^ + +`Websocket `__ + +`Sm2加密的使用 `__ + +SDK下载 +^^^^^^^ + +1. Java版本的客户端下载:\ `BDWareJavaClient <_static/BDWareJavaClient.zip>`__\ 。具体使用说明请下载后解压,查看README.md,并参考\ `ContractAPI <./ContractAPI.html>`__\ 。 + +2.Javascript版本的客户端下载:\ `BDWareWebClient <_static/BDWareWebClient.zip>`__\ 。具体使用说明请下载后解压,查看README.md,并参考\ `ContractAPI <./ContractAPI.html>`__\ 。 + +3.配置工具\ `BDWareConfigTool <_static/BDWareConfigTool.zip>`__\ 。具体说明请下载后解压,使用以下命令查看帮助: + +.. code:: bash + + java -jar java-client.jar -h + +.. |配置示例| image:: _static/imgs/config.png + diff --git a/source/Introduction.rst b/source/Introduction.rst new file mode 100644 index 0000000..d12c18f --- /dev/null +++ b/source/Introduction.rst @@ -0,0 +1,253 @@ +BDContract介绍 +============== + +-------------- + +什么是BDContract? +----------------- + +北大数瑞是面向大数据场景的数据资源、IoT资源、云资源的管理、调度平台。BDContract是一个可信计算框架,计算逻辑以智能合约的方式表达。通过”随机“和”冗余计算“的方式实现智能合约的可信执行。BDContract在保证智能合约的可用性、可靠性的同时,着重提升执行效率和安全性。 + +-------------- + +特点 +---- + +0. 支持多种执行模式,权衡可用性、可靠性、正确性和效率。 +1. 接入各种数据源。 +2. 支持合约的细粒度监测。 +3. 支持合约的状态。 +4. 访问控制。 +5. 支撑跨语言调用。 + +-------------- + +更新日志 +-------- + +- **v1.4.5** 2021年6月29日 + + - 稳定性提升 + - HTTP服务端的URIPath优化 + - 支持以Http方式进行静态资源文件加载 + +- **v1.4.4** 2021年6月15日 + + - 修复了getContractMeta时没优先返回RUNNING/HANGED的合约的问题 + - 实现了HomomorphicEncrypt的逻辑 + +- **v1.4.3** 2021年6月9日 + + - 修复SSL Renegotiate Bug + - 实现内存不足时自动Hangup-Resume + - 实现contract meta的硬盘持久化 + +- **v1.4.1** 2021年5月26日 + + - 实现了事件机制中的事件语义,支持“至少一次”、“至多一次”和“只有一次” + - 优化了合约模板 + - 增加模板配置文件 + - 优化了MockTemplate注解 + +- **v1.4.0** 2021年5月9日 + + - 优化了ACTemplate + - 完善了DoRepo的配置联动 + +- **v1.3.9** 2021年4月22日 + + - 修复了doipConfig在updateConfig中不支持的bug + - test-tool支持了sudo + - 优化了contract-template中的ACTemplate模板 + +- **v1.3.6** 2021年4月21日 + + - 修复了docker中无法获取cpuid的问题 + +- **v1.3.6** 2021年4月16日 + + - 修复了部分bug + - 修复了GRPCPool线程数量不足导致排队的bug + - 修复了requestID分配在压力测试下可能重复的bug + +- **v1.3.5** 2021年3月31日 + + - 修复了部分bug + - http的合约调用部分增加了简单拥塞控制策略 + - 稳定性提升 + +- **v1.3.0** 2021年2月1日 + + - 优化心跳机制 + - 修复部分Bug + - 更新SM2/SM3库 + - 更新前端签名计算方式 + +- **v1.2.0** 2020年12月11日 + + - 优化了多节点执行模式 + - 优化了合约master路由的逻辑 + - 修复了部分bug + - 修复文件系统相关的漏洞 + +- **v1.1.0** 2020年9月 + + - 支持https,并更新了该部分文档 + +- **v1.0.9** 2020年8月27日 + + - 完善IO相关工具类的文档 + - 优化合约模板:DAC持久化 + +- **v1.0.7** 2020年8月13日 + + - 优化合约日志、账本接口 + - 优化相关接口的文档 + - 提供合约模板的websocket接口 + - 自动编译bug修复 + +- **v1.0.5** 2020年7月25日 + + - 弱化NC的中心化作用,集群点对点连接。 + - 优化bdwareclient + - TODO MemoryDurable + +- **v1.0.2** 2020年7月22日 + + - 修复CentOS7下Too Many Opened Files的Bug + - 修复权限Bug + - 增加权限说明 + - 修复MySQLUtil的bug + - 升级BDLedger版本 + +- **v1.0.1** 2020年7月5日 + + - 更新了NodePortal/CenterPortal的UI。 + - 修改了编译流程,在NodePortal中可查看编译结果,在OnlineIDE中可手动/启动时编译 + - 修改了合约分发逻辑,以编译后ypk作为分发的文件 + - 支持public目录下的ypk在多节点模式下执行时,合约故障自动恢复 + +- **v0.99** 2020年6月22日 + + - 自定义合约方法的计费 + - 新增了GasExample、Incentives示例 + - 在客户端实现了“校验多点结果”,并优化了结果返回的方式 + - 修复断线重连后无权限提示 + +- **v0.97** 2020年5月25日 + + - cpu等资源的计量:gas机制 + - onlineIDE.html 支持上传多个文件 + - udp方式组网进行多点执行[无定序消息] + - bdwareclient.html,修复只包含计算逻辑的调用示例生成前缀错误 + +- **v0.95** 2020年5月19日 + + - 修复了onlineIDE.html在的pathname有前缀时不能正确跳转bdwareclient的bug。 + - 修复了bdwareclient的pathname有前缀时自动提取url的bug。 + - 启用了合约的权限 + - 增加了NodePortal.html/OnlineIDE.html和bdwareclient.html中无权限时的提醒 + +- **v0.90** 2020年5月9日 + + - 更改了yjs.jar/bdserver.jar的打包方式 + - 更新了install.sh/update.sh + - onlineIDE的修改后提醒 + - onlineIDE标签页自适应宽度 + - 文件接口隔离 + +- **v0.8** 2020年4月26日 + + - 完善文档界面和优化SDK提供方式 + - 数瑞Web客户端,客户端中所有的数据处理和如何对处理后的数据进行渲染均来自合约调用,实现可信Web应用。 + +- **v0.78** 2020年4月13日 + + - 合约调用DAC示例 + - 支持动态修改IO权限 + - 支持合约状态自定义备份(定时)策略 + - 修复部分页面bug + - 日志展示优化 + - 优化账本日志展示 + - 启用部分权限访问控制 + +- **v0.7** 2020年3月25日 + + - 支持多种角色的访问控制 + - 更新了UI + +- **v0.6** 2020年2月14日 + + - 优化了合约进程间的通讯 + - 尝试接入P2P网络 + +- **v0.5** 2019年12月10日 + + - 完善了3种智能合约状态记录-回放策略 + - 支持了最简单的多点执行算法(不同步) + +- **v0.45** 2019年9月2日 + + - 初步实现PBFT算法 + +- **v0.4** 2019年5月10日 + + - 支持memory dump + +- **v0.35** 2019年4月26日 + + - 实现合约的静态分析框架 + - 支持事件的发布-订阅 + +- **v0.3** 2019年1月8日 + + - 支持账本数据的接入 + - 合约状态上链 + +- **v0.2** 2018年10月9日 + + - 支持Python包的自动生成 + - 支持合约打包为ypk + - 支持文件、数据库等数据的接入 + +- **v0.1** 2018年8月6日 + + - 定义了智能合约的语法 + - 基于nashorn引擎,实现了智能合约的执行 + +-------------- + +使用开源项目说明 +---------------- + +BDWareContract项目站在了许多巨人的肩膀上,感谢这些开源项目。 + +本项目的智能合约后端使用了以下开源库。 + +================================================================ =================================================================================================================== ================================================== +名称 Licence类型 说明 +================================================================ =================================================================================================================== ================================================== +`Project Nashorn `__ `GPLv2 `__ 使用了该项目的编译器,可以将js函数编译为java字节码 +`ASM OW2 `__ `BSD `__ with attribution 基于asm的TreeAPI与VisitorAPI实现合约的静态分析框架 +`Netty `__ `Apache License 2.0 `__ 使用netty作为Http/Websocket的服务端 +`gRPC `__ `Apache License 2.0 `__ 使用gRPC与BDWareLedger通讯 +`RocksDB `__ `GPLv2 `__ 后台数据库 +`ANTLR `__ `BSD `__ 对合约脚本的词法分析与语法分析 +`SM2Java `__ `无 `__ 国密SM2 Java语言实现 +================================================================ =================================================================================================================== ================================================== + +本项目的智能合约前端使用了以下开源库。 + +========================================================= =========================================================================== ========================== +名称 Licence类型 说明 +========================================================= =========================================================================== ========================== +`Bootstrap `__ `MIT `__ 前端的排版、样式 +`jQuery `__ `MIT `__ 用于操作DOM的javascript库 +`jQueryUI `__ `MIT `__ 前端UI构件库 +`DataTables `__ `MIT `__ 表格样式 +`CodeMirror `__ `MIT `__ 代码编辑框样式 +`eCharts `__ `ApacheV2 `__ 统计图表 +`sm-crypto `__ `MIT `__ 国密SM2 javascript语言实现 +========================================================= =========================================================================== ========================== + +本项目的文档使用\ `Sphinx `__\ 生成,感谢\ `readthedocs `__\ 提供文档样式。 diff --git a/source/YJSAPI.rst b/source/YJSAPI.rst new file mode 100644 index 0000000..9561766 --- /dev/null +++ b/source/YJSAPI.rst @@ -0,0 +1,1739 @@ +YJS SDK +======= + +YJS Build-in API +---------------- + +内置对象 Global +~~~~~~~~~~~~~~~ + +内置对象 requester +~~~~~~~~~~~~~~~~~~ + +该内置对象在export function里面会有值,仅当合约调用签名验证通过。 + +执行合约 executeContract +~~~~~~~~~~~~~~~~~~~~~~~~ + +参数: + +.. code:: bash + + action:executeContract; + contractID:合约的id或名称均可; + operation:调用合约的方法名; + arg: 参数;格式为JSON字符串,有action与arg两个字段。 + +可选参数: + +.. code:: bash + + requestID:字符串类型,自行生成,用于查询hash + +使用示例: + +.. code:: javascript + + + function testExecutorContract(arg){ + var ret = JSON.parse(executeContract("ElemeProvider","queryDB",arg)); + if (ret.status == "Success"){ + return JSON.parse(ret.result); + }else return null; + } + +订阅事件主题 subscribe +~~~~~~~~~~~~~~~~~~~~~~ + +参数 + +.. code:: bash + + contractID:字符串类型 合约id或名称均可。 + event:字符串类型 + handler:方法名,该方法必须接受Event(内含字段topic和content)类型的唯一变量为参数;可以不是export方法 + +使用示例: + +.. code:: javascript + + export function init(arg) { + YancloudUtil.subscribe("topic", handler); + print("Handler: " + handler); + } + + function handler(e) { + print("topic: " + e.topic); + print("content: " + e.content); + } + +发布事件 pubEvent +~~~~~~~~~~~~~~~~~ + +参数 + +.. code:: bash + + topic:字符串类型,发布的事件主题 + content:字符串类型,发布的事件内容 + +使用示例: + +.. code:: javascript + + export function pub1(arg) { + YancloudUtil.pubEvent("topic", arg); + return "done"; + } + +也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名发布事件 + +.. code:: javascript + + event topic; + export function pub2(arg) { + topic(arg); + return "done"; + } + +该写法与上面的\ ``pub1``\ 等价。 + +发布带语义事件 pubEventConstraint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +参数 + +.. code:: bash + + topic:字符串类型,发布的事件主题 + content:字符串类型,发布的事件内容 + semantics:枚举类型,作为字符串输入,事件语义 + +事件语义参数 + AT_LEAST_ONCE:至少一次,默认语义 + +AT_MOST_ONCE:至多一次 + ONLY_ONCE:只有一次 + +使用示例: + +.. code:: javascript + + export function pub1(arg) { + YancloudUtil.pubEventConstraint("topic", arg, "AT_MOST_ONCE"); + return "done"; + } + +也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名按声明的语义发布事件 + +.. code:: javascript + + event AT_MOST_ONCE topic; + export function pub2(arg) { + topic(arg); + return "done"; + } + +该写法与上面的\ ``pub1``\ 等价。 + +事先声明的事件无论是否声明语义,都可以用后缀s作为方法名的方式调用,发布任意语义的事件: + +.. code:: javascript + + event topic; + export function pub3(arg) { + topics(arg, "AT_MOST_ONCE"); + return "done"; + } + +该写法与上面的\ ``pub1, pub2``\ 等价。 + +*不带事件语义声明事件时,语义默认为至少一次(AT_LEAST_ONCE)。* + +访问资源文件 +~~~~~~~~~~~~ + +通过Global.Resources去加载ypk内部的资源文件。 + +loadAsInputStream +^^^^^^^^^^^^^^^^^ + +参数: + +.. code:: bash + + path:字符串类型 需要加载文件的地址 + +使用示例: + +.. code:: javascript + + var file = Global.Resources.loadAsInputStream("/deleteit.txt"); + +loadAsScanner +^^^^^^^^^^^^^ + +参数: + +.. code:: bash + + path:字符串类型 需要加载文件的地址 + +使用示例: + +.. code:: javascript + + var scanner = Global.Resources.loadAsScanner("/local.txt"); + +YancloudUtil +~~~~~~~~~~~~ + +提供了一些内置的工具方法。 + +getKeyPair +^^^^^^^^^^ + +参数: + +:: + + 无 + +使用示例: + +:: + + var keyPair = YancloudUtil.getKeyPair(); + //该类型为SM2KeyPair类型, + print(keyPair.getPublicKeyStr()); + print(keyPair.getPrivateKeyStr()); + print(keyPair.toJson()); + +YJS Build-in Annotation +----------------------- + +@Access +~~~~~~~ + +设置合约的调用是否需要签名,这里分为两种,需签名和无签名。 +其中,“verified”表示需要签名。其他则表示无需签名。 + +:: + + @Access("verified") + export function easy(arg){ + return "true"; + } + +@LogType +~~~~~~~~ + +LogType注解通过参数的方式声明合约或函数的需要记录的日志类型。 + +其中,Arg表示日志中记录合约执行的参数;Result表示记录合约执行的返回结果;Branch表示记录合约执行分支。 + +例如 ,通过如下LogType注解来声明函数 + +:: + + @LogType("Arg","Result","Branch") + export function easy(arg){ + Global.a = "a"; + Global.b = "b"; + if(arg > 0) + return Global.a; + else + return Global.b; + } + +@LogLocation +~~~~~~~~~~~~ + +该注解可以修饰\ ``contract``\ 或\ ``function``\ 。 +设置日志存储的位置。参数中指定为“dataware”则存储在账本和本地,如果没有指定为“dataware”则仅存储在本地。 +例如,通过如下LogLocation设置存储位置。 + +在BaaS平台中,可以指定账本名称,BaaS平台默认账本为default,使用 +``@LogLocation("bdledger:default")``\ 。如想保存到自定义的账本,比如,“abc”账本,就使用 +``@LogLocation("bdledger:abc")`` + +:: + + @LogLocation("dataware") + export function easy(arg){ + Global.a = "a"; + } + +@Permission +~~~~~~~~~~~ + +该注解只能修饰\ ``contract`` +设置合约中调用的工具类的权限,包括File、Http、MySQL、MongoDB、RocksDB等工具类。如果合约中用到了以上工具类,需要在注解中添加对应的授权字段,默认只有YJS自带的YancloudUtil;如果没有添加则会抛出“未授权工具类”的异常。 +这6种工具类的详细说明在本小节后续中有说明。 + +:: + + @Permission("Http","File") + contract HttpPermission { + export function main(args){ + var http=HttpUtil.httpGet(args); + var dir="adf/adfas/"; + var file=FileUtil.getDir(dir); + return YancloudUtil.currentTimeMillis(); + } + } + +@Description +~~~~~~~~~~~~ + +该注解可以修饰\ ``contract``\ 或\ ``function``\ 。 +传入合约及函数的简介,可用于生成说明文档中关于exported函数的介绍。 + +:: + + @Description("返回数据条目,无需参数") + export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); + } + +@Param +~~~~~~ + +该注解可以修饰\ ``function``\ 。 +提供调用函数的参数示例,也为生成说明文档中的返回结果提供默认参数。 + +:: + + @Param({"offset":0,"count":100}) + export function get(args){ + var offset = args.offset; + var count = args.count; + ... + } + +@MockTemplate +~~~~~~~~~~~~~ + +该注解可以修饰\ ``function``\ 。 +提供函数的返回模拟数据模板,用于描述返回值的格式.若加此注解在debug方式调用时,返回按照此格式生成的模拟数据。 + +####支持的字段类型 + +:: + + @integer 整数 + @string 字符串 + @boolean 布尔值 + @date @time @datatime + @word 单词 @cword 中文单词 + @first @last 英文姓,名 + @cfirst @clast @cname 中文姓,名,全名 + @url @domin @ip @email + @region @province @city @county 地区,省,市,县 + …… + 详细格式可以参考http://mockjs.com/examples.html + +####注意:模板的格式为{‘result’:模板} + +.. code:: json + + //返回一个对象包含如下字段 + @MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) + //返回 + {"password":"3ZLc","name":"William Young","id":36097783842688,"email":"d.fuunwe@gqnr.to"}" + + + //返回元素个数为1-5个之间的一个数组,数组的每个元素都是上述格式的一个对象 + {'result|1-5':[{'id':'@integer','email':'@email','password':'@string','name':'@name'}]} + //返回 + [ + {"password":"dO]wW","name":"Jeffrey Lopez","id":1783453207480410,"email":"a.ckokgxrga@hgiesugi.bb"}, + {"password":"BQYRL","name":"Brian Moore","id":4310212972071102,"email":"k.lbpxocydrh@msgnjtox.na"}, + {"password":"Gw1","name":"Susan Jackson","id":7766580783668916,"email":"h.zjgusl@htce.cr"} + ] + +:: + + @MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) + export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); + } + +@Result +~~~~~~~ + +该注解可以修饰\ ``function``\ 。 +提供函数的返回结果示例,若加此注解则生成说明文档时将直接返回此结果而不使用默认参数调用函数。 + +:: + + @Result(666) + export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); + } + +@Cost +~~~~~ + +该注解可以修饰\ ``function``\ 。 提供函数的cpu计量功能。 + +:: + + @Cost({"countGas":true}) + export function .... + +IO工具类 +-------- + +概览 +~~~~ + +================================================================= ================================== +IO工具类名称 说明 +================================================================= ================================== +`FileUtil <./YJSAPI.html#fileutil>`__ 文件操作相关的类 +`LedgerUtil <./YJSAPI.html#ledgerutil>`__ 账本操作相关的类 +`HttpUtil <./YJSAPI.html#httputil>`__ Http接口相关的类 +`DOIPUtil <./YJSAPI.html#doiputil>`__ DoIP相关的类 +`MySQLUtil <./YJSAPI.html#mysqlutil>`__ 连接mysql数据库 +`MongoDBUtil <./YJSAPI.html#mongodbutil>`__ MongoDB连接相关的类 +`RocksDBUtil <./YJSAPI.html#rocksdbutil>`__ RocksDB(基于本地文件的k-v数据库) +`BDWareTimeSeriesDBUtil <./YJSAPI.html#BDWareTimeSeriesDBUtil>`__ 基于本地文件的时间序列数据库 +================================================================= ================================== + +FileUtil +~~~~~~~~ + +可以使用@Permission(“File”)来引入FileUtil对象。 + +:: + + @Permission("File") + contract FileSample { + ... + } + +该对象支持以下方法: + +copyTo +^^^^^^ + +可以复制文件和目录。第一个参数是source,第二个参数是destination。 + +参数 +'''' + +==== ==== ============ +序号 参数 说明 +==== ==== ============ +1 src 类型为String +2 dest 类型为String +==== ==== ============ + +使用示例 +'''''''' + +.. code:: javascript + + var ret = FileUtil.copyTo("./source.txt","./dest.txt"); + +getContent +^^^^^^^^^^ + +获取文件的文本内容,当文件不存在时,返回\ ``undefined``\ 。 + +.. _参数-1: + +参数 +'''' + +==== ==== ============ +序号 参数 说明 +==== ==== ============ +1 path 类型为String +==== ==== ============ + +.. _使用示例-1: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = FileUtil.getContent("./source.txt"); + +getDir +^^^^^^ + +获取文件所在的文件夹名,输入参数为字符串。 + +.. _参数-2: + +参数 +'''' + +==== ==== ============ +序号 参数 说明 +==== ==== ============ +1 path 类型为String +==== ==== ============ + +.. _使用示例-2: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = FileUtil.getDir("./parent/src.txt"); + // ret 为 "./parent/"; + +getFileName +^^^^^^^^^^^ + +获取文件名。输入参数为字符串。 + +.. _参数-3: + +参数 +'''' + +==== ==== ============ +序号 参数 说明 +==== ==== ============ +1 path 类型为String +==== ==== ============ + +.. _使用示例-3: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = FileUtil.getFileName("./parent/src.txt"); + // ret 为 "src.txt" + +openFileAsPrinter +^^^^^^^^^^^^^^^^^ + +以PrintStream的形式打开文件。 +返回结果是\ ``java.io.PrintStream``\ 类型。 + +.. _参数-4: + +参数 +'''' + +==== ======== ===================================== +序号 参数 说明 +==== ======== ===================================== +1 path 文件名,类型为String +2 isAppend 类型为boolean,表示是否往文件末尾添加 +==== ======== ===================================== + +.. _使用示例-4: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = FileUtil.openFileAsPrinter("./parent/src.txt",true); + ret.println("hello"); + ret.close(); + +LedgerUtil +~~~~~~~~~~ + +可以使用@Permission(“Ledger”)来引入LedgerUtil对象。 + +:: + + @Permission("Ledger") + contract LedgerExample{ + ... + } + +getClient +^^^^^^^^^ + +获取一个连接客户端,一个参数,为对象类型。 +返回结果为LedgerClient类型,用于后续的查询账本等操作。 + +.. _参数-5: + +参数 +'''' + +==== ======= ==================== +序号 参数 说明 +==== ======= ==================== +1 address 包含ip和端口两个字段 +==== ======= ==================== + +.. _使用示例-5: + +使用示例 +'''''''' + +.. code:: javascript + + var address = {}; + address.ip = "127.0.0.1"; + address.port = 18091; + var ledgerClient = LedgerUtil.getClient(address); + +queryByHash +^^^^^^^^^^^ + +根据Hash查询Transaction。 +返回结果为对象,包含from、to、type和data四个字段,均为String类型。 +其中data为按utf-8编码解析字节数组,如果存证时用的不是utf8编码,可能返回乱码。 + +.. _参数-6: + +参数 +'''' + +==== ====== ================================================ +序号 参数 说明 +==== ====== ================================================ +1 client 通过getClient方法获得的对象 +2 info 对象类型,有两个字段ledger和hash,均为字符串类型 +==== ====== ================================================ + +.. _使用示例-6: + +使用示例 +'''''''' + +.. code:: javascript + + // ... ledgerClient = LedgerUtil.getClient(...); + var info = {}; + info.ledger = "bdcontract"; + info.hash = "4d3b75750835092a50085127702669615b602e53"; + var ret = LedgerUtil.queryByHash(ledgerClient,info); + print(ret.from); + print(ret.to); + print(ret.type); + print(ret.data); + +sendTransaction +^^^^^^^^^^^^^^^ + +存证数据。 + +.. _参数-7: + +参数 +'''' + +==== ====== ========================================================================== +序号 参数 说明 +==== ====== ========================================================================== +1 client 通过getClient方法获得的对象 +2 info 对象类型,有from:raw-latex:`\to`:raw-latex:`\data三个字段`,均为String类型 +==== ====== ========================================================================== + +.. _使用示例-7: + +使用示例 +'''''''' + +.. code:: javascript + + // ... ledgerClient = LedgerUtil.getClient(...); + var info = {}; + info.ledger = "bdcontract"; + info.from = "b60e8dd61c5d32be8058bb8eb970870f07233155"; + info.to = "b60e8dd61c5d32be8058bb8eb970870f07233155"; + info.data = "hello world"; + var ret = LedgerUtil.sendTransaction(ledgerClient,info); + //ret为存证的哈希值 + print(ret); + +HttpUtil +~~~~~~~~ + +可以使用@Permission(“Http”)来引入HttpUtil对象。 + +:: + + @Permission("Http") + contract HttpExample{ + ... + } + +createAPIGate +^^^^^^^^^^^^^ + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +.. _参数-8: + +参数 +'''' + +==== ==== ============================== +序号 参数 说明 +==== ==== ============================== +1 ip 字符串类型,ip,端口默认为6161 +==== ==== ============================== + +.. _使用示例-8: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = HttpUtil.createAPIGate("192.168.4.4"); + ret.get("com.tencent.mm","sendMsg","msg"); + print(ret); + +.. _createapigate-1: + +createAPIGate +^^^^^^^^^^^^^ + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +.. _参数-9: + +参数 +'''' + +==== ==== ================ +序号 参数 说明 +==== ==== ================ +1 ip 字符串类型,ip +2 port 字符串类型,端口 +==== ==== ================ + +.. _使用示例-9: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = HttpUtil.createAPIGate("192.168.4.4", "6161"); + ret.get("com.tencent.mm","sendMsg","msg"); + print(ret); + +get +^^^ + +发起Http的get请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +.. _参数-10: + +参数 +'''' + +==== ==== =================== +序号 参数 说明 +==== ==== =================== +1 url 字符串,表示url类型 +==== ==== =================== + +.. _使用示例-10: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = HttpUtil.get("https://www.baidu.com"); + print(ret.responseCode); + print(ret.response); + +post +^^^^ + +发起Http的post请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +.. _参数-11: + +参数 +'''' + +==== ==== ====================================================================== +序号 参数 说明 +==== ==== ====================================================================== +1 args 对象类型,有url,headers和data三个字段。其中,args.headers为对象类型。 +==== ==== ====================================================================== + +.. _使用示例-11: + +使用示例 +'''''''' + +.. code:: javascript + + var req = {}; + req.url = "https://www.baidu.com"; + req.data = "hello"; + req.header = {}; + req.header.Accept = "application/json"; + req.header["Content-Type"] = "application/json"; + var ret = HttpUtil.post(req); + print(ret.resposeCode); + print(ret.response); + +DOIPUtil +~~~~~~~~ + +可以使用@Permission(“DOIP”)来引入DOIPUtil对象。 + +:: + + @Permission("DOIP") + contract DOIPExample{ + ... + } + +call +^^^^ + +调用一个DO + +.. _参数-12: + +参数 +'''' + +==== ==== ========================== +序号 参数 说明 +==== ==== ========================== +1 arg0 字符串类型, 目标DO标识 +2 arg1 字符串类型, 输入参数字符串 +==== ==== ========================== + +.. _使用示例-12: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.call("86.5000.470/do.hello","inputString"); + +create +^^^^^^ + +向一个Repository创建一个字符串类型DO + +.. _参数-13: + +参数 +'''' + +==== ==== ============================ +序号 参数 说明 +==== ==== ============================ +1 arg0 字符串类型, 目标Repo标识 +2 arg1 对象类型,包括doID,doBody字段 +==== ==== ============================ + +.. _使用示例-13: + +使用示例 +'''''''' + +.. code:: javascript + + var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); + var ret = DOIPUtil.create("86.5000.470/repo.localTcpRepo",digitalObject); + +delete +^^^^^^ + +从一个Repository中删除DO + +.. _参数-14: + +参数 +'''' + +==== ==== ======================= +序号 参数 说明 +==== ==== ======================= +1 arg0 字符串类型 目标DO标识 +2 arg1 字符串类型 目标Repo标识 +==== ==== ======================= + +.. _使用示例-14: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.delete("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo"); + +hello +^^^^^ + +获取目标Repository的DOIP服务信息 + +.. _参数-15: + +参数 +'''' + +==== ==== ======================= +序号 参数 说明 +==== ==== ======================= +1 arg0 字符串类型 目标Repo标识 +==== ==== ======================= + +.. _使用示例-15: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.hello("86.5000.470/repo.localTcpRepo"); + +listOperation +^^^^^^^^^^^^^ + +获取目标DO支持的DOIP操作 + +.. _参数-16: + +参数 +'''' + +==== ==== ===================== +序号 参数 说明 +==== ==== ===================== +1 arg0 字符串类型 目标DO标识 +==== ==== ===================== + +.. _使用示例-16: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.listOperation("86.5000.470/do.hello"); + +register +^^^^^^^^ + +向LHS注册一个DO,返回分配的标识 + +.. _参数-17: + +参数 +'''' + +==== ==== =========================== +序号 参数 说明 +==== ==== =========================== +1 arg0 字符串类型 DO所在Repo标识 +2 arg1 字符串类型 DO格式描述字符串 +==== ==== =========================== + +.. _使用示例-17: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.register("86.5000.470/repo.localTcpRepo","String"); + +reregister +^^^^^^^^^^ + +修改LHS中DO的注册信息 + +.. _参数-18: + +参数 +'''' + +==== ==== =========================== +序号 参数 说明 +==== ==== =========================== +1 arg0 字符串类型 目标DO标识 +2 arg1 字符串类型 DO所在Repo标识 +3 arg2 字符串类型 DO格式描述字符串 +==== ==== =========================== + +.. _使用示例-18: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.reregister("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo","String"); + +retrieve +^^^^^^^^ + +获取一个DO + +.. _参数-19: + +参数 +'''' + +==== ==== ===================== +序号 参数 说明 +==== ==== ===================== +1 arg0 字符串类型 目标DO标识 +==== ==== ===================== + +.. _使用示例-19: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.retrieve("86.5000.470/do.hello"); + +test +~~~~ + +测试DOIPUtils是否可用 ##### 参数 + +==== ==== ===================== +序号 参数 说明 +==== ==== ===================== +1 arg0 字符串类型 任意字符串 +==== ==== ===================== + +.. _使用示例-20: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = DOIPUtil.test("hello"); + +update +^^^^^^ + +更新目标DO + +.. _参数-20: + +参数 +'''' + +==== ==== ========================== +序号 参数 说明 +==== ==== ========================== +1 arg0 JS对象,包括doID,doBody字段 +==== ==== ========================== + +.. _使用示例-21: + +使用示例 +'''''''' + +.. code:: javascript + + var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); + var ret = DOIPUtil.update(digitalObject); + +SQLUtil +~~~~~~~ + +可以使用@Permission(“SQL”)来引入SQLUtil对象。 +可支持MySQL/PostgreSQL/Oracle/GuassDB200等SQL数据库。 +需要将对应的jdbc的jar上传到项目中。 +例如,要使用mysql,可上传mysql-connector-java-8.0.24.jar + +:: + + @Permission("SQL") + oracle MySQLExample{ + ... + } + +initDriver +^^^^^^^^^^ + +.. _参数-21: + +参数 +'''' + +==== =========== ========== +序号 参数 说明 +==== =========== ========== +1 driverClass 字符串类型 +==== =========== ========== + +.. _使用示例-22: + +使用示例 +'''''''' + +.. code:: javascript + + //使用mysql + SQLUtil.initDriver("com.mysql.cj.jdbc.Driver"); + //使用postgresql + SQLUtil.initDriver("org.postgresql.Driver"); + //使用oracle + SQLUtil.initDriver("oracle.jdbc.OracleDriver"); + +getConnection +^^^^^^^^^^^^^ + +.. _参数-22: + +参数 +'''' + +==== ======= ==================== +序号 参数 说明 +==== ======= ==================== +1 URL 字符串类型,jdbc连接 +2 usrName 字符串类型,用户名 +3 pwd 字符串类型,密码 +==== ======= ==================== + +.. _使用示例-23: + +使用示例 +'''''''' + +.. code:: javascript + + var url = "jdbc:mysql://xx.xx.xx:port/tableName"; + var usrName = "xxx"; + var pwd = "xxx"; + //配置好用户名和密码,url格式为ip或域名+端口,中间以”:”隔开。 + var conn = SQLUtil.getConnection(url,usrName,pwd); + //获取数据库连接 + var sql = "select * from newele.data"; + //创建查询语句 + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var waimailist = []; + //解析查询结果 + var meta = resultSet.getMetaData(); + for (;resultSet.next();){ + var line = {}; + for (var j=1;j<=meta.getColumnCount();j++){ + line[meta.getColumnName(j)] = resultSet.getString(j); + } + waimailist.push(line); + } + +其中,getConnection方法返回的对象通过反射机制绑定到了Java的一个java.util.Connection对象。因此,可以查看: +https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html +以了解如何进行Mysql数据库操作。 + +MongoDBUtil +~~~~~~~~~~~ + +可以使用@Permission(“MongoDB”)来引入MongoDBUtil对象。 + +:: + + @Permission("MongoDB") + contract MongoDBExample{ + ... + } + +.. _getconnection-1: + +getConnection +^^^^^^^^^^^^^ + +.. _参数-23: + +参数 +'''' + +==== ======= ========================= +序号 参数 说明 +==== ======= ========================= +1 URL 字符串类型 数据库的URL +2 port 整数类型 端口号 +3 dbName 字符串类型 数据库的名称 +4 usrName 字符串类型 数据库的用户名 +5 pwd 字符串类型 数据库的密码 +==== ======= ========================= + +.. _使用示例-24: + +使用示例 +'''''''' + +**注意:port为整型,其他参数为String类型** + +.. code:: javascript + + var client = MongoDBUtil.getConnection(url,port,dbName,usrName,pwd); + //获取数据库对象 + var db = client.getDatabase("yancloud"); + var collection = db.getCollection("containers"); + var iter = collection.find().iterator(); + var ret =""; + for (;iter.hasNext();){ + ret+=iter.next().toJson(); + ret+="\n"; + } + +其中,getMongoDBClient对象通过反射机制绑定到了Java的一个com.mongodb.MongoClient对象。因此,可以查看: +https://mongodb.github.io/mongo-java-driver/3.4/javadoc/com/mongodb/MongoClient.html + +以了解该对象的更多方法和使用方式。 + +RocksDBUtil +~~~~~~~~~~~ + +使用@Permission(“RocksDB”)来引入RocksDBUtil对象。 + +:: + + @Permission("RocksDB") + contract RocksDBSample { + ... + } + +loadDB +^^^^^^ + +通过loadDB来加载一个RocksDB数据库。 加载后,可进行get/delete/put等操作。 + +.. _参数-24: + +参数 +'''' + +==== ======== =========================== +序号 参数 说明 +==== ======== =========================== +1 path 字符串类型 数据库部署的路径 +2 readOnly 布尔类型 数据库只读 +==== ======== =========================== + +.. _使用示例-25: + +使用示例 +'''''''' + +:: + + @Permission("RocksDB") + @Description("这是个使用RocksDB的参考代码") + contract RocksDBSample{ + function onCreate(){ + Global.rocksdb = RocksDBUtil.loadDB("./dbdir/","false"); + } + @Description("示例参数: {\"key\":\"abc\",\"value\":\"def\"}") + export function put(arg){ + arg = JSON.parse(arg); + Global.rocksdb.put(arg.key,arg.value); + return "success"; + } + @Description("示例参数: \"abc\"}") + export function get(arg){ + return Global.rocksdb.get(arg); + return "failed"; + } + @Description("示例参数: \"abc\"") + export function deleteKey(arg){ + return Global.rocksdb.delete(arg); + } + @Description("遍历KV库,无需参数") + export function iter(arg){ + var iter = Global.rocksdb.newIterator(); + var obj = undefined; + var ret = { + }; + for (iter.seekToFirst();(obj=Global.rocksdb.getNext(iter))!=undefined;){ + ret[obj.key]=obj.value; + } + return JSON.stringify(ret) + } + } + +BDWareTimeSeriesDBUtil +~~~~~~~~~~~~~~~~~~~~~~ + +使用示例 + +:: + + @Permission("BDWareTimeSeriesDB") + contract BDWareTimeDBExample{ + function onCreate(arg){ + Global.dbutil = BDWareTimeSeriesDBUtil.getConnection(); + } + + export function put(arg){ + //第一个参数为表名,第二个参数为要放的value,时间戳自动打。 + Global.dbutil.put("defaultTable",arg); + return "success"; + } + @Param + export function getCount(arg){ + return Global.dbutil.getCount("defaultTable"); + } + @Param(1617254937373) + export function queryByStartTime(arg){ + var startDate = java.lang.Long.valueOf(arg); + //查询从开始时刻startDate到最新的数据 + var list = Global.dbutil.query("defaultTable",startDate); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } + + @Description("示例参数: {\"offset\":1,\"len\":1}") + @Param({"offset":1,"len":1}) + export function queryByOffset(arg){ + var offsetLen = JSON.parse(arg); + //可配合getCount使用,查询第offset至offset+len条数据 + var list = Global.dbutil.queryByOffset("defaultTable",offsetLen.offset,offsetLen.len); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } + } + +加解密工具类 +------------ + +SM2 +~~~ + +可以使用@Permission(“SM2”)来引入SM2Util对象。 + +:: + + @Permission("SM2") + contract SM2Sample { + ... + } + +generateKeyPair +^^^^^^^^^^^^^^^ + +生成公私钥。 + +.. _参数-25: + +参数 +'''' + +无参数。 + +.. _使用示例-26: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = SM2Util.generateKeyPair(); + print(ret.publicKey); + print(ret.privateKey); + return JSON.stringify(ret); + +sign +^^^^ + +签名。 + +.. _参数-26: + +参数 +'''' + +==== ======= =========================== +序号 参数 说明 +==== ======= =========================== +1 content 字符串类型 要进行签名的内容 +2 keyPair sm2 +==== ======= =========================== + +.. _使用示例-27: + +使用示例 +'''''''' + +:: + + var keypair = SM2Util.generateKeyPair(); + var ret = SM2Util.sign("Hello",keypair); + print(ret.status); + //如果status是success + print(ret.signature); + //如果status是failed + print(ret.message); + +verify +^^^^^^ + +验签。 + +.. _参数-27: + +参数 +'''' + +==== ========= ======================= +序号 参数 说明 +==== ========= ======================= +1 content 字符串类型 待验签的内容 +2 signature 字符串类型 签名 +3 publicKey 字符串类型 公钥 +==== ========= ======================= + +.. _使用示例-28: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = SM2Util.verify("Hello","....签名","...公钥"); + // 验证通过时,result为true,status为success + // 失败时,result为failed,status为failed + print(ret.status); + print(ret.result); + +encrypt +^^^^^^^ + +sm2加密。 + +.. _参数-28: + +参数 +'''' + +==== ========= ======================= +序号 参数 说明 +==== ========= ======================= +1 content 字符串类型 待验签的内容 +3 publicKey 字符串类型 公钥 +==== ========= ======================= + +.. _使用示例-29: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = SM2Util.encrypt("Hello","...公钥"); + print(ret); + +decrypt +^^^^^^^ + +sm2解密。 + +.. _参数-29: + +参数 +'''' + +==== ========== ======================= +序号 参数 说明 +==== ========== ======================= +1 content 字符串类型 待验签的内容 +3 privateKey 字符串类型 公钥 +==== ========== ======================= + +.. _使用示例-30: + +使用示例 +'''''''' + +.. code:: javascript + + var ret = SM2Util.decrypt("Hello","...私钥"); + print(ret); + +多线程工具类 +------------ + +AsyncUtil +~~~~~~~~~ + +可以使用@Permission(“Async”)来引入AsyncUtil对象。 + +:: + + @Permission("Async") + contract AsyncExample{ + export function longTimeTask(arg){ + var a = { + }; + a.count = 100; + AsyncUtil.postFunction(taskFun,a); + } + function taskFun(arg){ + Global.progress = 0; + for (var i=0;i``,\ ````\ 等标签。2.会以标签中的\ ``fromContract``\ 属性,去调用executeCurrentContract(“loadResources”)方法。 +典型的yjs的loadResources方法如下。3.获取所有script会进行eval,link会当css加载。 + +:: + + //在某个yjs文件中声明。 + export function loadResource(arg){ + return Global.Resources.loadAsString(arg); + } + +.. figure:: ./_static/imgs/clientLoadProcess.png + :alt: 前端加载流程图 + + 前端加载流程图 + +前端框架预置函数说明 +~~~~~~~~~~~~~~~~~~~~ + +前端的javascript在html中已加载了jquery(使用$.)和vue2。 +为避免冲突,本版不支持再加载vue2/vue3脚本。 +前端通过executeContract/executeCurrentContract与后端交互。 + +executeContract +^^^^^^^^^^^^^^^ + +调用某个合约的某个函数。会自动使用当前的global.sm2Key进行签名。参数说明及示例: + +.. code:: javascript + + executeContract(contracID,operation,arg,callback); + //其中,contractID为string类型,为被调用的合约名称/合约ID。 + //operation为string类型,合约函数 + //arg为string类型,表示参数 + //callback为函数类型,接受返回结果的回调函数。 + +executeCurrentContract +^^^^^^^^^^^^^^^^^^^^^^ + +执行当前合约的某个函数。会自动使用当前的global.sm2Key进行签名。参数说明及示例: + +.. code:: javascript + + executeContract(operation,arg,callback); + //operation为string类型,合约函数 + //arg为string类型,表示参数 + //callback为函数类型,接受返回结果的回调函数。 diff --git a/source/YJSInDepth.rst b/source/YJSInDepth.rst new file mode 100644 index 0000000..1174ed2 --- /dev/null +++ b/source/YJSInDepth.rst @@ -0,0 +1,302 @@ +YJS语法 +======= + +-------------- + +概述 +---- + +YJS源文件包括任意数量的\ **import声明**\ 和一个\ **contract定义**\ 。 + +-------------- + +import声明 +---------- + +与JavaScript(ES6)类似,YJS也支持import声明语句,在全局层面,开发者可以使用如下import声明来导入其他文件。 + +:: + + import "filename"; + +内容 +~~~~ + +import声明语句将包含在“filename”文件中的所有全局符号(单元)导入到当前文件,且全局范围内有效。 + +路径 +~~~~ + +**filename**\ 通常用\ **/**\ 做目录分隔符来表示文件的路径,例如,从同一目录下导入\ **x.yjs**\ 文件到当前文件,可以使用\ **import +“x.yjs”**\ 语句;从其他目录下导入\ **x.yjs**\ 使用\ **import +“lib/x.yjs”**\ 语句。 + +-------------- + +Contract定义 +------------ + +示例 +~~~~ + +以下是一个合约示例,用于JSON处理,此YJS源文件以合约名称命名。 + +:: + + contract ScoreAdder{ + //arg = {"action":"main","arg":"[{\"score\":20},{\"score\":20}]"} + export function main(arg){ + //JSON is a build-in object. + var point = JSON.parse(arg); + var s = 0; + print(point[0].score); + print(point.length); + for (var i=0;i`__\ 中渲染。 +首先在合约中import以下模块。 + +.. code:: javascript + + module Viewable{ + export function loadResource(arg){ + return Global.Resources.loadAsString(arg); + } + export function needRender(arg){ + return true; + } + } + +同时,import以后,定义一个getMainFrame方法,以便数瑞客户端识别主页: + +.. code:: javascript + + export function getMainFrame(arg){ + return "/html/main.html"; + } + +该方法的返回结果为一个资源文件的路径。 +示例的资源文件“/html/main.html”如下: + +.. code:: html + +
+ Data from contract: + + + +
+ +示例的资源文件“/html/hello.js”如下: + +.. code:: javascript + + var queryDataFromContract = function(){ + //第一个参数为函数名,第二个为参数,第三个参数为回调。 + var data = executeCurrentContract("query","abc",function(argg){ + $("#resultText")[0].innerHTML = argg.result; + }); + } + +参考示例: + +YJS-Python +~~~~~~~~~~ + +TODO diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-横版.png b/source/_static/02-logos/北大数瑞logo-镂空反白-横版.png new file mode 100644 index 0000000..ab47958 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-横版.png differ diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-横版@2x.png b/source/_static/02-logos/北大数瑞logo-镂空反白-横版@2x.png new file mode 100644 index 0000000..1e47d6f Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-横版@2x.png differ diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-横版@3x.png b/source/_static/02-logos/北大数瑞logo-镂空反白-横版@3x.png new file mode 100644 index 0000000..4678a9a Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-横版@3x.png differ diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-竖版.png b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版.png new file mode 100644 index 0000000..3b8e931 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版.png differ diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@2x.png b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@2x.png new file mode 100644 index 0000000..1fe4458 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@2x.png differ diff --git a/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@3x.png b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@3x.png new file mode 100644 index 0000000..65e3c1a Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo-镂空反白-竖版@3x.png differ diff --git a/source/_static/02-logos/北大数瑞logo深色背景-横版.png b/source/_static/02-logos/北大数瑞logo深色背景-横版.png new file mode 100644 index 0000000..6657c8e Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo深色背景-横版.png differ diff --git a/source/_static/02-logos/北大数瑞logo深色背景-横版@2x.png b/source/_static/02-logos/北大数瑞logo深色背景-横版@2x.png new file mode 100644 index 0000000..8f47df3 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo深色背景-横版@2x.png differ diff --git a/source/_static/02-logos/北大数瑞logo深色背景-横版@3x.png b/source/_static/02-logos/北大数瑞logo深色背景-横版@3x.png new file mode 100644 index 0000000..a64dac0 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo深色背景-横版@3x.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版-深色背景.png b/source/_static/02-logos/北大数瑞logo竖版-深色背景.png new file mode 100644 index 0000000..81e793a Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版-深色背景.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版-深色背景@2x.png b/source/_static/02-logos/北大数瑞logo竖版-深色背景@2x.png new file mode 100644 index 0000000..7a6ae50 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版-深色背景@2x.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版-深色背景@3x.png b/source/_static/02-logos/北大数瑞logo竖版-深色背景@3x.png new file mode 100644 index 0000000..1a4b696 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版-深色背景@3x.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版.png b/source/_static/02-logos/北大数瑞logo竖版.png new file mode 100644 index 0000000..062258b Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版@2x.png b/source/_static/02-logos/北大数瑞logo竖版@2x.png new file mode 100644 index 0000000..32a5e10 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版@2x.png differ diff --git a/source/_static/02-logos/北大数瑞logo竖版@3x.png b/source/_static/02-logos/北大数瑞logo竖版@3x.png new file mode 100644 index 0000000..ea02f33 Binary files /dev/null and b/source/_static/02-logos/北大数瑞logo竖版@3x.png differ diff --git a/source/_static/02-logos/北大数睿logo横版.png b/source/_static/02-logos/北大数睿logo横版.png new file mode 100644 index 0000000..b72352b Binary files /dev/null and b/source/_static/02-logos/北大数睿logo横版.png differ diff --git a/source/_static/02-logos/北大数睿logo横版@2x.png b/source/_static/02-logos/北大数睿logo横版@2x.png new file mode 100644 index 0000000..d022b52 Binary files /dev/null and b/source/_static/02-logos/北大数睿logo横版@2x.png differ diff --git a/source/_static/02-logos/北大数睿logo横版@3x.png b/source/_static/02-logos/北大数睿logo横版@3x.png new file mode 100644 index 0000000..70c0436 Binary files /dev/null and b/source/_static/02-logos/北大数睿logo横版@3x.png differ diff --git a/source/_static/imgs/analysis.png b/source/_static/imgs/analysis.png new file mode 100644 index 0000000..88ac1d3 Binary files /dev/null and b/source/_static/imgs/analysis.png differ diff --git a/source/_static/imgs/analysis1.png b/source/_static/imgs/analysis1.png new file mode 100644 index 0000000..4e5774d Binary files /dev/null and b/source/_static/imgs/analysis1.png differ diff --git a/source/_static/imgs/analysis2.png b/source/_static/imgs/analysis2.png new file mode 100644 index 0000000..4b0ab0d Binary files /dev/null and b/source/_static/imgs/analysis2.png differ diff --git a/source/_static/imgs/analysis3.png b/source/_static/imgs/analysis3.png new file mode 100644 index 0000000..a1bb383 Binary files /dev/null and b/source/_static/imgs/analysis3.png differ diff --git a/source/_static/imgs/analysisExecuteResult.png b/source/_static/imgs/analysisExecuteResult.png new file mode 100644 index 0000000..80b52cd Binary files /dev/null and b/source/_static/imgs/analysisExecuteResult.png differ diff --git a/source/_static/imgs/authList.jpg b/source/_static/imgs/authList.jpg new file mode 100644 index 0000000..741d070 Binary files /dev/null and b/source/_static/imgs/authList.jpg differ diff --git a/source/_static/imgs/authMan.jpg b/source/_static/imgs/authMan.jpg new file mode 100644 index 0000000..df1041e Binary files /dev/null and b/source/_static/imgs/authMan.jpg differ diff --git a/source/_static/imgs/authMana.jpg b/source/_static/imgs/authMana.jpg new file mode 100644 index 0000000..1fb6be4 Binary files /dev/null and b/source/_static/imgs/authMana.jpg differ diff --git a/source/_static/imgs/authNodeManager.jpg b/source/_static/imgs/authNodeManager.jpg new file mode 100644 index 0000000..ce63e83 Binary files /dev/null and b/source/_static/imgs/authNodeManager.jpg differ diff --git a/source/_static/imgs/authorizationOrNot.jpg b/source/_static/imgs/authorizationOrNot.jpg new file mode 100644 index 0000000..7ca81fc Binary files /dev/null and b/source/_static/imgs/authorizationOrNot.jpg differ diff --git a/source/_static/imgs/bash-api.png b/source/_static/imgs/bash-api.png new file mode 100644 index 0000000..3d6cc3b Binary files /dev/null and b/source/_static/imgs/bash-api.png differ diff --git a/source/_static/imgs/centerManager.jpg b/source/_static/imgs/centerManager.jpg new file mode 100644 index 0000000..eabae32 Binary files /dev/null and b/source/_static/imgs/centerManager.jpg differ diff --git a/source/_static/imgs/centerNodeList.png b/source/_static/imgs/centerNodeList.png new file mode 100644 index 0000000..e8668f9 Binary files /dev/null and b/source/_static/imgs/centerNodeList.png differ diff --git a/source/_static/imgs/centerNodePage.png b/source/_static/imgs/centerNodePage.png new file mode 100644 index 0000000..07e78d8 Binary files /dev/null and b/source/_static/imgs/centerNodePage.png differ diff --git a/source/_static/imgs/centerNodePreview.png b/source/_static/imgs/centerNodePreview.png new file mode 100644 index 0000000..111c9ea Binary files /dev/null and b/source/_static/imgs/centerNodePreview.png differ diff --git a/source/_static/imgs/centerNodeUnitCreate.png b/source/_static/imgs/centerNodeUnitCreate.png new file mode 100644 index 0000000..314f71e Binary files /dev/null and b/source/_static/imgs/centerNodeUnitCreate.png differ diff --git a/source/_static/imgs/centerNodeUnits.png b/source/_static/imgs/centerNodeUnits.png new file mode 100644 index 0000000..fa7e86d Binary files /dev/null and b/source/_static/imgs/centerNodeUnits.png differ diff --git a/source/_static/imgs/checkUser.jpg b/source/_static/imgs/checkUser.jpg new file mode 100644 index 0000000..9c94318 Binary files /dev/null and b/source/_static/imgs/checkUser.jpg differ diff --git a/source/_static/imgs/checkUser.png b/source/_static/imgs/checkUser.png new file mode 100644 index 0000000..2282d10 Binary files /dev/null and b/source/_static/imgs/checkUser.png differ diff --git a/source/_static/imgs/chooseInstance.png b/source/_static/imgs/chooseInstance.png new file mode 100644 index 0000000..dd58914 Binary files /dev/null and b/source/_static/imgs/chooseInstance.png differ diff --git a/source/_static/imgs/clientLoadProcess.png b/source/_static/imgs/clientLoadProcess.png new file mode 100644 index 0000000..df9efc1 Binary files /dev/null and b/source/_static/imgs/clientLoadProcess.png differ diff --git a/source/_static/imgs/closePermission.png b/source/_static/imgs/closePermission.png new file mode 100644 index 0000000..2df7c24 Binary files /dev/null and b/source/_static/imgs/closePermission.png differ diff --git a/source/_static/imgs/codeManage1-1.png b/source/_static/imgs/codeManage1-1.png new file mode 100644 index 0000000..2af24cb Binary files /dev/null and b/source/_static/imgs/codeManage1-1.png differ diff --git a/source/_static/imgs/codeManage1-2.png b/source/_static/imgs/codeManage1-2.png new file mode 100644 index 0000000..57d5727 Binary files /dev/null and b/source/_static/imgs/codeManage1-2.png differ diff --git a/source/_static/imgs/codeManage1.png b/source/_static/imgs/codeManage1.png new file mode 100644 index 0000000..aff2b9a Binary files /dev/null and b/source/_static/imgs/codeManage1.png differ diff --git a/source/_static/imgs/codeManage2.png b/source/_static/imgs/codeManage2.png new file mode 100644 index 0000000..dd4fad0 Binary files /dev/null and b/source/_static/imgs/codeManage2.png differ diff --git a/source/_static/imgs/codeManage3.png b/source/_static/imgs/codeManage3.png new file mode 100644 index 0000000..7676d76 Binary files /dev/null and b/source/_static/imgs/codeManage3.png differ diff --git a/source/_static/imgs/codeManage4.png b/source/_static/imgs/codeManage4.png new file mode 100644 index 0000000..ad0606d Binary files /dev/null and b/source/_static/imgs/codeManage4.png differ diff --git a/source/_static/imgs/codeManage5.png b/source/_static/imgs/codeManage5.png new file mode 100644 index 0000000..8b9c382 Binary files /dev/null and b/source/_static/imgs/codeManage5.png differ diff --git a/source/_static/imgs/codeManage6.png b/source/_static/imgs/codeManage6.png new file mode 100644 index 0000000..03ade62 Binary files /dev/null and b/source/_static/imgs/codeManage6.png differ diff --git a/source/_static/imgs/codeManage7.png b/source/_static/imgs/codeManage7.png new file mode 100644 index 0000000..4a48550 Binary files /dev/null and b/source/_static/imgs/codeManage7.png differ diff --git a/source/_static/imgs/codeManage8.png b/source/_static/imgs/codeManage8.png new file mode 100644 index 0000000..57ad15e Binary files /dev/null and b/source/_static/imgs/codeManage8.png differ diff --git a/source/_static/imgs/codeManageMenu.png b/source/_static/imgs/codeManageMenu.png new file mode 100644 index 0000000..ddaf7d1 Binary files /dev/null and b/source/_static/imgs/codeManageMenu.png differ diff --git a/source/_static/imgs/config.png b/source/_static/imgs/config.png new file mode 100644 index 0000000..111d0ca Binary files /dev/null and b/source/_static/imgs/config.png differ diff --git a/source/_static/imgs/contract.jpg b/source/_static/imgs/contract.jpg new file mode 100644 index 0000000..a165388 Binary files /dev/null and b/source/_static/imgs/contract.jpg differ diff --git a/source/_static/imgs/contractList.jpg b/source/_static/imgs/contractList.jpg new file mode 100644 index 0000000..6cf8be2 Binary files /dev/null and b/source/_static/imgs/contractList.jpg differ diff --git a/source/_static/imgs/contractLog.jpg b/source/_static/imgs/contractLog.jpg new file mode 100644 index 0000000..de245e6 Binary files /dev/null and b/source/_static/imgs/contractLog.jpg differ diff --git a/source/_static/imgs/contractMode.png b/source/_static/imgs/contractMode.png new file mode 100644 index 0000000..b32397b Binary files /dev/null and b/source/_static/imgs/contractMode.png differ diff --git a/source/_static/imgs/contracteveryLog.jpg b/source/_static/imgs/contracteveryLog.jpg new file mode 100644 index 0000000..65d683b Binary files /dev/null and b/source/_static/imgs/contracteveryLog.jpg differ diff --git a/source/_static/imgs/dashboard.jpg b/source/_static/imgs/dashboard.jpg new file mode 100644 index 0000000..23c862b Binary files /dev/null and b/source/_static/imgs/dashboard.jpg differ diff --git a/source/_static/imgs/deploytopology.png b/source/_static/imgs/deploytopology.png new file mode 100644 index 0000000..c326fac Binary files /dev/null and b/source/_static/imgs/deploytopology.png differ diff --git a/source/_static/imgs/dirstructure.png b/source/_static/imgs/dirstructure.png new file mode 100644 index 0000000..e2c6098 Binary files /dev/null and b/source/_static/imgs/dirstructure.png differ diff --git a/source/_static/imgs/docs.png b/source/_static/imgs/docs.png new file mode 100644 index 0000000..828ecf9 Binary files /dev/null and b/source/_static/imgs/docs.png differ diff --git a/source/_static/imgs/everyLog.jpg b/source/_static/imgs/everyLog.jpg new file mode 100644 index 0000000..fcc7c56 Binary files /dev/null and b/source/_static/imgs/everyLog.jpg differ diff --git a/source/_static/imgs/executeResult.png b/source/_static/imgs/executeResult.png new file mode 100644 index 0000000..21b9e51 Binary files /dev/null and b/source/_static/imgs/executeResult.png differ diff --git a/source/_static/imgs/favicon.ico b/source/_static/imgs/favicon.ico new file mode 100644 index 0000000..56aa953 Binary files /dev/null and b/source/_static/imgs/favicon.ico differ diff --git a/source/_static/imgs/fork1.png b/source/_static/imgs/fork1.png new file mode 100644 index 0000000..931a43b Binary files /dev/null and b/source/_static/imgs/fork1.png differ diff --git a/source/_static/imgs/fork2.png b/source/_static/imgs/fork2.png new file mode 100644 index 0000000..6f0d531 Binary files /dev/null and b/source/_static/imgs/fork2.png differ diff --git a/source/_static/imgs/fork3.png b/source/_static/imgs/fork3.png new file mode 100644 index 0000000..81702dc Binary files /dev/null and b/source/_static/imgs/fork3.png differ diff --git a/source/_static/imgs/genReadme.png b/source/_static/imgs/genReadme.png new file mode 100644 index 0000000..dd3347a Binary files /dev/null and b/source/_static/imgs/genReadme.png differ diff --git a/source/_static/imgs/http-api.png b/source/_static/imgs/http-api.png new file mode 100644 index 0000000..be7b2f9 Binary files /dev/null and b/source/_static/imgs/http-api.png differ diff --git a/source/_static/imgs/ide_screenshots1.1.png b/source/_static/imgs/ide_screenshots1.1.png new file mode 100644 index 0000000..7588fb1 Binary files /dev/null and b/source/_static/imgs/ide_screenshots1.1.png differ diff --git a/source/_static/imgs/ide_screenshots2.2.png b/source/_static/imgs/ide_screenshots2.2.png new file mode 100644 index 0000000..a4a766d Binary files /dev/null and b/source/_static/imgs/ide_screenshots2.2.png differ diff --git a/source/_static/imgs/index.png b/source/_static/imgs/index.png new file mode 100644 index 0000000..5cc7516 Binary files /dev/null and b/source/_static/imgs/index.png differ diff --git a/source/_static/imgs/intanceExecute.png b/source/_static/imgs/intanceExecute.png new file mode 100644 index 0000000..bd66b1f Binary files /dev/null and b/source/_static/imgs/intanceExecute.png differ diff --git a/source/_static/imgs/licence.jpg b/source/_static/imgs/licence.jpg new file mode 100644 index 0000000..22010d6 Binary files /dev/null and b/source/_static/imgs/licence.jpg differ diff --git a/source/_static/imgs/licence.png b/source/_static/imgs/licence.png new file mode 100644 index 0000000..cca1c2d Binary files /dev/null and b/source/_static/imgs/licence.png differ diff --git a/source/_static/imgs/log.jpg b/source/_static/imgs/log.jpg new file mode 100644 index 0000000..075d0b0 Binary files /dev/null and b/source/_static/imgs/log.jpg differ diff --git a/source/_static/imgs/log1.png b/source/_static/imgs/log1.png new file mode 100644 index 0000000..04e05a0 Binary files /dev/null and b/source/_static/imgs/log1.png differ diff --git a/source/_static/imgs/log2.png b/source/_static/imgs/log2.png new file mode 100644 index 0000000..33773f7 Binary files /dev/null and b/source/_static/imgs/log2.png differ diff --git a/source/_static/imgs/log3.png b/source/_static/imgs/log3.png new file mode 100644 index 0000000..a2bde90 Binary files /dev/null and b/source/_static/imgs/log3.png differ diff --git a/source/_static/imgs/logMenu.png b/source/_static/imgs/logMenu.png new file mode 100644 index 0000000..9fd8fc5 Binary files /dev/null and b/source/_static/imgs/logMenu.png differ diff --git a/source/_static/imgs/logo.png b/source/_static/imgs/logo.png new file mode 100644 index 0000000..79d515e Binary files /dev/null and b/source/_static/imgs/logo.png differ diff --git a/source/_static/imgs/logo2.png b/source/_static/imgs/logo2.png new file mode 100644 index 0000000..ab47958 Binary files /dev/null and b/source/_static/imgs/logo2.png differ diff --git a/source/_static/imgs/memoryDump.png b/source/_static/imgs/memoryDump.png new file mode 100644 index 0000000..44356a2 Binary files /dev/null and b/source/_static/imgs/memoryDump.png differ diff --git a/source/_static/imgs/node.jpg b/source/_static/imgs/node.jpg new file mode 100644 index 0000000..9827b89 Binary files /dev/null and b/source/_static/imgs/node.jpg differ diff --git a/source/_static/imgs/nodeConfig.png b/source/_static/imgs/nodeConfig.png new file mode 100644 index 0000000..1954dc2 Binary files /dev/null and b/source/_static/imgs/nodeConfig.png differ diff --git a/source/_static/imgs/nodeConfigChange.png b/source/_static/imgs/nodeConfigChange.png new file mode 100644 index 0000000..1f771a9 Binary files /dev/null and b/source/_static/imgs/nodeConfigChange.png differ diff --git a/source/_static/imgs/nodeInfo.jpg b/source/_static/imgs/nodeInfo.jpg new file mode 100644 index 0000000..2282d10 Binary files /dev/null and b/source/_static/imgs/nodeInfo.jpg differ diff --git a/source/_static/imgs/nodeInstancesList.png b/source/_static/imgs/nodeInstancesList.png new file mode 100644 index 0000000..e7e3fd1 Binary files /dev/null and b/source/_static/imgs/nodeInstancesList.png differ diff --git a/source/_static/imgs/nodeInstancesPage.png b/source/_static/imgs/nodeInstancesPage.png new file mode 100644 index 0000000..35e8478 Binary files /dev/null and b/source/_static/imgs/nodeInstancesPage.png differ diff --git a/source/_static/imgs/nodeLicence.png b/source/_static/imgs/nodeLicence.png new file mode 100644 index 0000000..940bab1 Binary files /dev/null and b/source/_static/imgs/nodeLicence.png differ diff --git a/source/_static/imgs/nodeUnits.png b/source/_static/imgs/nodeUnits.png new file mode 100644 index 0000000..502d271 Binary files /dev/null and b/source/_static/imgs/nodeUnits.png differ diff --git a/source/_static/imgs/nodeUserManager.jpg b/source/_static/imgs/nodeUserManager.jpg new file mode 100644 index 0000000..24a4612 Binary files /dev/null and b/source/_static/imgs/nodeUserManager.jpg differ diff --git a/source/_static/imgs/nullPermission.png b/source/_static/imgs/nullPermission.png new file mode 100644 index 0000000..7573bdb Binary files /dev/null and b/source/_static/imgs/nullPermission.png differ diff --git a/source/_static/imgs/opList.jpg b/source/_static/imgs/opList.jpg new file mode 100644 index 0000000..52098d9 Binary files /dev/null and b/source/_static/imgs/opList.jpg differ diff --git a/source/_static/imgs/operator.jpg b/source/_static/imgs/operator.jpg new file mode 100644 index 0000000..9417d67 Binary files /dev/null and b/source/_static/imgs/operator.jpg differ diff --git a/source/_static/imgs/permissionShow.png b/source/_static/imgs/permissionShow.png new file mode 100644 index 0000000..34223df Binary files /dev/null and b/source/_static/imgs/permissionShow.png differ diff --git a/source/_static/imgs/pic1.png b/source/_static/imgs/pic1.png new file mode 100644 index 0000000..804b056 Binary files /dev/null and b/source/_static/imgs/pic1.png differ diff --git a/source/_static/imgs/pic2.png b/source/_static/imgs/pic2.png new file mode 100644 index 0000000..f4b8520 Binary files /dev/null and b/source/_static/imgs/pic2.png differ diff --git a/source/_static/imgs/plicence.jpg b/source/_static/imgs/plicence.jpg new file mode 100644 index 0000000..5250e6d Binary files /dev/null and b/source/_static/imgs/plicence.jpg differ diff --git a/source/_static/imgs/projectdir.png b/source/_static/imgs/projectdir.png new file mode 100644 index 0000000..4298746 Binary files /dev/null and b/source/_static/imgs/projectdir.png differ diff --git a/source/_static/imgs/roleAuth.jpg b/source/_static/imgs/roleAuth.jpg new file mode 100644 index 0000000..b00e6ce Binary files /dev/null and b/source/_static/imgs/roleAuth.jpg differ diff --git a/source/_static/imgs/set.jpg b/source/_static/imgs/set.jpg new file mode 100644 index 0000000..56ddd88 Binary files /dev/null and b/source/_static/imgs/set.jpg differ diff --git a/source/_static/imgs/shortcut.png b/source/_static/imgs/shortcut.png new file mode 100644 index 0000000..bd940ee Binary files /dev/null and b/source/_static/imgs/shortcut.png differ diff --git a/source/_static/imgs/shortcut3.png b/source/_static/imgs/shortcut3.png new file mode 100644 index 0000000..e000d9b Binary files /dev/null and b/source/_static/imgs/shortcut3.png differ diff --git a/source/_static/imgs/timeTravel.png b/source/_static/imgs/timeTravel.png new file mode 100644 index 0000000..a9317a8 Binary files /dev/null and b/source/_static/imgs/timeTravel.png differ diff --git a/source/_static/imgs/timetravel2.png b/source/_static/imgs/timetravel2.png new file mode 100644 index 0000000..495ff0a Binary files /dev/null and b/source/_static/imgs/timetravel2.png differ diff --git a/source/_static/imgs/timetravel3.png b/source/_static/imgs/timetravel3.png new file mode 100644 index 0000000..c227866 Binary files /dev/null and b/source/_static/imgs/timetravel3.png differ diff --git a/source/_static/imgs/timetravel4.png b/source/_static/imgs/timetravel4.png new file mode 100644 index 0000000..d3347cc Binary files /dev/null and b/source/_static/imgs/timetravel4.png differ diff --git a/source/_static/imgs/trustful.png b/source/_static/imgs/trustful.png new file mode 100644 index 0000000..f09d767 Binary files /dev/null and b/source/_static/imgs/trustful.png differ diff --git a/source/_static/imgs/updatePermission.png b/source/_static/imgs/updatePermission.png new file mode 100644 index 0000000..7998271 Binary files /dev/null and b/source/_static/imgs/updatePermission.png differ diff --git a/source/_static/imgs/userActive.jpg b/source/_static/imgs/userActive.jpg new file mode 100644 index 0000000..0ea95ac Binary files /dev/null and b/source/_static/imgs/userActive.jpg differ diff --git a/source/_static/imgs/userAll.jpg b/source/_static/imgs/userAll.jpg new file mode 100644 index 0000000..ef58c6d Binary files /dev/null and b/source/_static/imgs/userAll.jpg differ diff --git a/source/_static/imgs/userApplyGraph.jpg b/source/_static/imgs/userApplyGraph.jpg new file mode 100644 index 0000000..343e946 Binary files /dev/null and b/source/_static/imgs/userApplyGraph.jpg differ diff --git a/source/_static/imgs/userList.jpg b/source/_static/imgs/userList.jpg new file mode 100644 index 0000000..927e5fd Binary files /dev/null and b/source/_static/imgs/userList.jpg differ diff --git a/source/_static/imgs/userManager.jpg b/source/_static/imgs/userManager.jpg new file mode 100644 index 0000000..05903ec Binary files /dev/null and b/source/_static/imgs/userManager.jpg differ diff --git a/source/_static/imgs/websocket-api.png b/source/_static/imgs/websocket-api.png new file mode 100644 index 0000000..9e38a75 Binary files /dev/null and b/source/_static/imgs/websocket-api.png differ diff --git a/source/_static/js/createWS.js b/source/_static/js/createWS.js new file mode 100644 index 0000000..3638f73 --- /dev/null +++ b/source/_static/js/createWS.js @@ -0,0 +1,169 @@ +var createWssocket = function(wsurl, onopen, handler) { + console.log("[createWS.js] createWssocket : "); + var retsocket = {}; + var wssocket = new WebSocket(wsurl); + wssocket.onerror = function(error) { + console.log(error); + }; + wssocket.onopen = onopen; + var onmessage = function(event) { + var obj = JSON.parse(event.data); + switch (obj.action) { + case 'sendNextSegment': + retsocket.sendNextSegment(); + break; + case 'sendSeg': + retsocket.receiveSeg(obj);C + break; + default: + handler(event, wssocket); + } + }; + var reconnect = function(error) { + setTimeout(function() { + console.log("[createWS.js] try to reconnect"); + wssocket = new WebSocket(wsurl); + wssocket.onclose = reconnect; + wssocket.onmessage = onmessage; + //wssocket.onopen = onopen; + }, 1000); + }; + wssocket.onclose = reconnect; + + retsocket.receiveSeg = function(obj) { + if (obj.cid == 'start') { + retsocket.toReceive = ""; + } + retsocket.toReceive += obj.data; + if (obj.cid == 'done') { + console.log("[receiveSeg] Received AllData:" + retsocket.toReceive); + var event = {}; + event.data = retsocket.toReceive; + retsocket.toReceive = ""; + handler(event); + } + }; + wssocket.onmessage = onmessage; + + retsocket.isSending = false; + retsocket.sendList = []; + retsocket.monitor = function() { + if (!retsocket.isSending) { + if (retsocket.sendList.length > 0) { + retsocket.send(retsocket.sendList.pop()); + } + } + setTimeout(retsocket.monitor, 1000); + }; + // TODO: we don't need monitor at all? + retsocket.monitor(); + retsocket.send = function(str) { + if (retsocket.isSending) { + retsocket.sendList.push(str); + return; + } + if (str.length > 1024) { + retsocket.isSending = true; + retsocket.toSend = str.substr(1024); + var obj = {}; + obj.isSegment = true; + obj.data = str.substr(0, 1024); + wssocket.send(JSON.stringify(obj)); + } else + wssocket.send(str); + }; + retsocket.sendNextSegment = function() { + var str = retsocket.toSend; + if (str.length > 1024) { + retsocket.toSend = str.substr(1024); + var obj = {}; + obj.isSegment = true; + obj.data = str.substr(0, 1024); + wssocket.send(JSON.stringify(obj)); + } else { + retsocket.toSend = ""; + var obj = {}; + obj.isSegment = false; + obj.data = str; + wssocket.send(JSON.stringify(obj)); + retsocket.isSending = false; + if (retsocket.sendList.length > 0) { + retsocket.send(retsocket.sendList.pop()); + } + } + }; + retsocket.isOpen = function() { + return wssocket.readyState; + } + return retsocket; +}; + +var aesDecrypt = function(data) { + data = cryptico.b64to256(data); + var encryptedBlocks = cryptico.string2bytes(data); + var exkey = global.aesKey.slice(0); + aes.ExpandKey(exkey); + aes.Decrypt(encryptedBlocks, exkey); + return cryptico.bytes2string(encryptedBlocks); + +}; +var aesEncrypt = function(data, aesKey) { + var key = aesKey; + var exkey = key.slice(0); + aes.ExpandKey(exkey); + var blocks = my.string2bytes(data); + blocks = my.pad16(blocks); + aes.Encrypt(blocks, exkey); + ciphertext = cryptico.bytes2string(blocks); + ciphertext = cryptico.b256to64(ciphertext); + return ciphertext; +}; +var rsaEncrypt = function(data, rsaKey) { + var rsa = new RSAKey(); + rsa.setPublic(rsaKey.n, rsaKey.e1); + var result = rsa.encrypt(data); + return result; +}; +var loadRSAKey = function(rsaKey) { + var str = cryptico.b64to256(rsaKey); + str = str.split(","); + var ret = {}; + ret.n = str[0]; + ret.e1 = str[1]; + ret.e2 = str[2]; + return ret; +}; +var testRSA = function() { + pubKey = loadRSAKey(global.privKey); + reqContent = {}; + reqContent.action = "main"; + reqContent.arg = "[{\"score\":20},{\"score\":20}]"; + reqContent.contractID = "abc"; + eReq = encryptReq(reqContent, pubKey); + url = "http://localhost:8080/SCIDE/SCManager?action=executeContractEncrypted&contractRequest=" + + encodeURIComponent(JSON.stringify(eReq)); +}; + +var encryptReq = function(reqContent, pubKey) { + // global.pubKey = loadRSAKey(global.privKey); + var aes = {}; + aes.key = cryptico.generateAESKey(); + var aesObj = JSON.stringify(aes); + var rsa = new RSAKey(); + rsa.setPrivate(pubKey.n, pubKey.e1, pubKey.e2); + var encrypedReq = {}; + encrypedReq.action = rsa.decrypt(aesObj); + encrypedReq.contractID = reqContent.contractID; + reqContent.contractID = undefined; + encrypedReq.arg = JSON.stringify(reqContent); + encrypedReq.arg = aesEncrypt(encrypedReq.arg, aes.key); + encrypedReq.requester = pubKey.n + "," + pubKey.e1 + "," + "0"; + encrypedReq.requester = cryptico.b256to64(encrypedReq.requester); + return encrypedReq; +}; +// global.aesKey = cryptico.generateAESKey(); +// +// var url = "ws://" + +// document.location.host+(document.location.pathname.replace("scide.html", +// "SCExecutor")); +// global.wssocket = createWssocket(url, WSHandler); diff --git a/source/_static/js/sm2.js b/source/_static/js/sm2.js new file mode 100644 index 0000000..6034ccc --- /dev/null +++ b/source/_static/js/sm2.js @@ -0,0 +1,2101 @@ +window.sm2 = function(t) { + function i(r) { + if (e[r]) return e[r].exports; + var n = e[r] = { + i: r, + l: !1, + exports: {} + }; + return t[r].call(n.exports, n, n.exports, i), + n.l = !0, + n.exports + } + var e = {}; + return i.m = t, + i.c = e, + i.d = function(t, e, r) { + i.o(t, e) || Object.defineProperty(t, e, { + configurable: !1, + enumerable: !0, + get: r + }) + }, + i.n = function(t) { + var e = t && t.__esModule ? + function() { + return t. + default + }: + function() { + return t + }; + return i.d(e, "a", e), + e + }, + i.o = function(t, i) { + return Object.prototype.hasOwnProperty.call(t, i) + }, + i.p = "", + i(i.s = 3) +} ([function(t, i, e) { (function() { + function e(t, i, e) { + null != t && ("number" == typeof t ? this.fromNumber(t, i, e) : null == i && "string" != typeof t ? this.fromString(t, 256) : this.fromString(t, i)) + } + function r() { + return new e(null) + } + function n(t, i, e, r, n, s) { + for (; --s >= 0;) { + var o = i * this[t++] + e[r] + n; + n = Math.floor(o / 67108864), + e[r++] = 67108863 & o + } + return n + } + function s(t, i, e, r, n, s) { + for (var o = 32767 & i, + h = i >> 15; --s >= 0;) { + var u = 32767 & this[t], + a = this[t++] >> 15, + f = h * u + a * o; + u = o * u + ((32767 & f) << 15) + e[r] + (1073741823 & n), + n = (u >>> 30) + (f >>> 15) + h * a + (n >>> 30), + e[r++] = 1073741823 & u + } + return n + } + function o(t, i, e, r, n, s) { + for (var o = 16383 & i, + h = i >> 14; --s >= 0;) { + var u = 16383 & this[t], + a = this[t++] >> 14, + f = h * u + a * o; + u = o * u + ((16383 & f) << 14) + e[r] + n, + n = (u >> 28) + (f >> 14) + h * a, + e[r++] = 268435455 & u + } + return n + } + function h(t) { + return pi.charAt(t) + } + function u(t, i) { + var e = yi[t.charCodeAt(i)]; + return null == e ? -1 : e + } + function a(t) { + for (var i = this.t - 1; i >= 0; --i) t[i] = this[i]; + t.t = this.t, + t.s = this.s + } + function f(t) { + this.t = 1, + this.s = t < 0 ? -1 : 0, + t > 0 ? this[0] = t: t < -1 ? this[0] = t + this.DV: this.t = 0 + } + function l(t) { + var i = r(); + return i.fromInt(t), + i + } + function c(t, i) { + var r; + if (16 == i) r = 4; + else if (8 == i) r = 3; + else if (256 == i) r = 8; + else if (2 == i) r = 1; + else if (32 == i) r = 5; + else { + if (4 != i) return void this.fromRadix(t, i); + r = 2 + } + this.t = 0, + this.s = 0; + for (var n = t.length, + s = !1, + o = 0; --n >= 0;) { + var h = 8 == r ? 255 & t[n] : u(t, n); + h < 0 ? "-" == t.charAt(n) && (s = !0) : (s = !1, 0 == o ? this[this.t++] = h: o + r > this.DB ? (this[this.t - 1] |= (h & (1 << this.DB - o) - 1) << o, this[this.t++] = h >> this.DB - o) : this[this.t - 1] |= h << o, (o += r) >= this.DB && (o -= this.DB)) + } + 8 == r && 0 != (128 & t[0]) && (this.s = -1, o > 0 && (this[this.t - 1] |= (1 << this.DB - o) - 1 << o)), + this.clamp(), + s && e.ZERO.subTo(this, this) + } + function p() { + for (var t = this.s & this.DM; this.t > 0 && this[this.t - 1] == t;)--this.t + } + function y(t) { + if (this.s < 0) return "-" + this.negate().toString(t); + var i; + if (16 == t) i = 4; + else if (8 == t) i = 3; + else if (2 == t) i = 1; + else if (32 == t) i = 5; + else { + if (4 != t) return this.toRadix(t); + i = 2 + } + var e, r = (1 << i) - 1, + n = !1, + s = "", + o = this.t, + u = this.DB - o * this.DB % i; + if (o-->0) for (u < this.DB && (e = this[o] >> u) > 0 && (n = !0, s = h(e)); o >= 0;) u < i ? (e = (this[o] & (1 << u) - 1) << i - u, e |= this[--o] >> (u += this.DB - i)) : (e = this[o] >> (u -= i) & r, u <= 0 && (u += this.DB, --o)), + e > 0 && (n = !0), + n && (s += h(e)); + return n ? s: "0" + } + function v() { + var t = r(); + return e.ZERO.subTo(this, t), + t + } + function g() { + return this.s < 0 ? this.negate() : this + } + function m(t) { + var i = this.s - t.s; + if (0 != i) return i; + var e = this.t; + if (0 != (i = e - t.t)) return this.s < 0 ? -i: i; + for (; --e >= 0;) if (0 != (i = this[e] - t[e])) return i; + return 0 + } + function d(t) { + var i, e = 1; + return 0 != (i = t >>> 16) && (t = i, e += 16), + 0 != (i = t >> 8) && (t = i, e += 8), + 0 != (i = t >> 4) && (t = i, e += 4), + 0 != (i = t >> 2) && (t = i, e += 2), + 0 != (i = t >> 1) && (t = i, e += 1), + e + } + function T() { + return this.t <= 0 ? 0 : this.DB * (this.t - 1) + d(this[this.t - 1] ^ this.s & this.DM) + } + function b(t, i) { + var e; + for (e = this.t - 1; e >= 0; --e) i[e + t] = this[e]; + for (e = t - 1; e >= 0; --e) i[e] = 0; + i.t = this.t + t, + i.s = this.s + } + function F(t, i) { + for (var e = t; e < this.t; ++e) i[e - t] = this[e]; + i.t = Math.max(this.t - t, 0), + i.s = this.s + } + function B(t, i) { + var e, r = t % this.DB, + n = this.DB - r, + s = (1 << n) - 1, + o = Math.floor(t / this.DB), + h = this.s << r & this.DM; + for (e = this.t - 1; e >= 0; --e) i[e + o + 1] = this[e] >> n | h, + h = (this[e] & s) << r; + for (e = o - 1; e >= 0; --e) i[e] = 0; + i[o] = h, + i.t = this.t + o + 1, + i.s = this.s, + i.clamp() + } + function x(t, i) { + i.s = this.s; + var e = Math.floor(t / this.DB); + if (e >= this.t) return void(i.t = 0); + var r = t % this.DB, + n = this.DB - r, + s = (1 << r) - 1; + i[0] = this[e] >> r; + for (var o = e + 1; o < this.t; ++o) i[o - e - 1] |= (this[o] & s) << n, + i[o - e] = this[o] >> r; + r > 0 && (i[this.t - e - 1] |= (this.s & s) << n), + i.t = this.t - e, + i.clamp() + } + function w(t, i) { + for (var e = 0, + r = 0, + n = Math.min(t.t, this.t); e < n;) r += this[e] - t[e], + i[e++] = r & this.DM, + r >>= this.DB; + if (t.t < this.t) { + for (r -= t.s; e < this.t;) r += this[e], + i[e++] = r & this.DM, + r >>= this.DB; + r += this.s + } else { + for (r += this.s; e < t.t;) r -= t[e], + i[e++] = r & this.DM, + r >>= this.DB; + r -= t.s + } + i.s = r < 0 ? -1 : 0, + r < -1 ? i[e++] = this.DV + r: r > 0 && (i[e++] = r), + i.t = e, + i.clamp() + } + function S(t, i) { + var r = this.abs(), + n = t.abs(), + s = r.t; + for (i.t = s + n.t; --s >= 0;) i[s] = 0; + for (s = 0; s < n.t; ++s) i[s + r.t] = r.am(0, n[s], i, s, 0, r.t); + i.s = 0, + i.clamp(), + this.s != t.s && e.ZERO.subTo(i, i) + } + function k(t) { + for (var i = this.abs(), e = t.t = 2 * i.t; --e >= 0;) t[e] = 0; + for (e = 0; e < i.t - 1; ++e) { + var r = i.am(e, i[e], t, 2 * e, 0, 1); (t[e + i.t] += i.am(e + 1, 2 * i[e], t, 2 * e + 1, r, i.t - e - 1)) >= i.DV && (t[e + i.t] -= i.DV, t[e + i.t + 1] = 1) + } + t.t > 0 && (t[t.t - 1] += i.am(e, i[e], t, 2 * e, 0, 1)), + t.s = 0, + t.clamp() + } + function D(t, i, n) { + var s = t.abs(); + if (! (s.t <= 0)) { + var o = this.abs(); + if (o.t < s.t) return null != i && i.fromInt(0), + void(null != n && this.copyTo(n)); + null == n && (n = r()); + var h = r(), + u = this.s, + a = t.s, + f = this.DB - d(s[s.t - 1]); + f > 0 ? (s.lShiftTo(f, h), o.lShiftTo(f, n)) : (s.copyTo(h), o.copyTo(n)); + var l = h.t, + c = h[l - 1]; + if (0 != c) { + var p = c * (1 << this.F1) + (l > 1 ? h[l - 2] >> this.F2: 0), + y = this.FV / p, + v = (1 << this.F1) / p, + g = 1 << this.F2, + m = n.t, + T = m - l, + b = null == i ? r() : i; + for (h.dlShiftTo(T, b), n.compareTo(b) >= 0 && (n[n.t++] = 1, n.subTo(b, n)), e.ONE.dlShiftTo(l, b), b.subTo(h, h); h.t < l;) h[h.t++] = 0; + for (; --T >= 0;) { + var F = n[--m] == c ? this.DM: Math.floor(n[m] * y + (n[m - 1] + g) * v); + if ((n[m] += h.am(0, F, n, T, 0, l)) < F) for (h.dlShiftTo(T, b), n.subTo(b, n); n[m] < --F;) n.subTo(b, n) + } + null != i && (n.drShiftTo(l, i), u != a && e.ZERO.subTo(i, i)), + n.t = l, + n.clamp(), + f > 0 && n.rShiftTo(f, n), + u < 0 && e.ZERO.subTo(n, n) + } + } + } + function I(t) { + var i = r(); + return this.abs().divRemTo(t, null, i), + this.s < 0 && i.compareTo(e.ZERO) > 0 && t.subTo(i, i), + i + } + function E(t) { + this.m = t + } + function O(t) { + return t.s < 0 || t.compareTo(this.m) >= 0 ? t.mod(this.m) : t + } + function q(t) { + return t + } + function A(t) { + t.divRemTo(this.m, null, t) + } + function R(t, i, e) { + t.multiplyTo(i, e), + this.reduce(e) + } + function V(t, i) { + t.squareTo(i), + this.reduce(i) + } + function M() { + if (this.t < 1) return 0; + var t = this[0]; + if (0 == (1 & t)) return 0; + var i = 3 & t; + return i = i * (2 - (15 & t) * i) & 15, + i = i * (2 - (255 & t) * i) & 255, + i = i * (2 - ((65535 & t) * i & 65535)) & 65535, + i = i * (2 - t * i % this.DV) % this.DV, + i > 0 ? this.DV - i: -i + } + function _(t) { + this.m = t, + this.mp = t.invDigit(), + this.mpl = 32767 & this.mp, + this.mph = this.mp >> 15, + this.um = (1 << t.DB - 15) - 1, + this.mt2 = 2 * t.t + } + function C(t) { + var i = r(); + return t.abs().dlShiftTo(this.m.t, i), + i.divRemTo(this.m, null, i), + t.s < 0 && i.compareTo(e.ZERO) > 0 && this.m.subTo(i, i), + i + } + function L(t) { + var i = r(); + return t.copyTo(i), + this.reduce(i), + i + } + function P(t) { + for (; t.t <= this.mt2;) t[t.t++] = 0; + for (var i = 0; i < this.m.t; ++i) { + var e = 32767 & t[i], + r = e * this.mpl + ((e * this.mph + (t[i] >> 15) * this.mpl & this.um) << 15) & t.DM; + for (e = i + this.m.t, t[e] += this.m.am(0, r, t, i, 0, this.m.t); t[e] >= t.DV;) t[e] -= t.DV, + t[++e]++ + } + t.clamp(), + t.drShiftTo(this.m.t, t), + t.compareTo(this.m) >= 0 && t.subTo(this.m, t) + } + function H(t, i) { + t.squareTo(i), + this.reduce(i) + } + function N(t, i, e) { + t.multiplyTo(i, e), + this.reduce(e) + } + function U() { + return 0 == (this.t > 0 ? 1 & this[0] : this.s) + } + function z(t, i) { + if (t > 4294967295 || t < 1) return e.ONE; + var n = r(), + s = r(), + o = i.convert(this), + h = d(t) - 1; + for (o.copyTo(n); --h >= 0;) if (i.sqrTo(n, s), (t & 1 << h) > 0) i.mulTo(s, o, n); + else { + var u = n; + n = s, + s = u + } + return i.revert(n) + } + function j(t, i) { + var e; + return e = t < 256 || i.isEven() ? new E(i) : new _(i), + this.exp(t, e) + } + function X() { + var t = r(); + return this.copyTo(t), + t + } + function Z() { + if (this.s < 0) { + if (1 == this.t) return this[0] - this.DV; + if (0 == this.t) return - 1 + } else { + if (1 == this.t) return this[0]; + if (0 == this.t) return 0 + } + return (this[1] & (1 << 32 - this.DB) - 1) << this.DB | this[0] + } + function K() { + return 0 == this.t ? this.s: this[0] << 24 >> 24 + } + function G() { + return 0 == this.t ? this.s: this[0] << 16 >> 16 + } + function Y(t) { + return Math.floor(Math.LN2 * this.DB / Math.log(t)) + } + function W() { + return this.s < 0 ? -1 : this.t <= 0 || 1 == this.t && this[0] <= 0 ? 0 : 1 + } + function J(t) { + if (null == t && (t = 10), 0 == this.signum() || t < 2 || t > 36) return "0"; + var i = this.chunkSize(t), + e = Math.pow(t, i), + n = l(e), + s = r(), + o = r(), + h = ""; + for (this.divRemTo(n, s, o); s.signum() > 0;) h = (e + o.intValue()).toString(t).substr(1) + h, + s.divRemTo(n, s, o); + return o.intValue().toString(t) + h + } + function Q(t, i) { + this.fromInt(0), + null == i && (i = 10); + for (var r = this.chunkSize(i), n = Math.pow(i, r), s = !1, o = 0, h = 0, a = 0; a < t.length; ++a) { + var f = u(t, a); + f < 0 ? "-" == t.charAt(a) && 0 == this.signum() && (s = !0) : (h = i * h + f, ++o >= r && (this.dMultiply(n), this.dAddOffset(h, 0), o = 0, h = 0)) + } + o > 0 && (this.dMultiply(Math.pow(i, o)), this.dAddOffset(h, 0)), + s && e.ZERO.subTo(this, this) + } + function $(t, i, r) { + if ("number" == typeof i) if (t < 2) this.fromInt(1); + else for (this.fromNumber(t, r), this.testBit(t - 1) || this.bitwiseTo(e.ONE.shiftLeft(t - 1), ht, this), this.isEven() && this.dAddOffset(1, 0); ! this.isProbablePrime(i);) this.dAddOffset(2, 0), + this.bitLength() > t && this.subTo(e.ONE.shiftLeft(t - 1), this); + else { + var n = new Array, + s = 7 & t; + n.length = 1 + (t >> 3), + i.nextBytes(n), + s > 0 ? n[0] &= (1 << s) - 1 : n[0] = 0, + this.fromString(n, 256) + } + } + function tt() { + var t = this.t, + i = new Array; + i[0] = this.s; + var e, r = this.DB - t * this.DB % 8, + n = 0; + if (t-->0) for (r < this.DB && (e = this[t] >> r) != (this.s & this.DM) >> r && (i[n++] = e | this.s << this.DB - r); t >= 0;) r < 8 ? (e = (this[t] & (1 << r) - 1) << 8 - r, e |= this[--t] >> (r += this.DB - 8)) : (e = this[t] >> (r -= 8) & 255, r <= 0 && (r += this.DB, --t)), + 0 != (128 & e) && (e |= -256), + 0 == n && (128 & this.s) != (128 & e) && ++n, + (n > 0 || e != this.s) && (i[n++] = e); + return i + } + function it(t) { + return 0 == this.compareTo(t) + } + function et(t) { + return this.compareTo(t) < 0 ? this: t + } + function rt(t) { + return this.compareTo(t) > 0 ? this: t + } + function nt(t, i, e) { + var r, n, s = Math.min(t.t, this.t); + for (r = 0; r < s; ++r) e[r] = i(this[r], t[r]); + if (t.t < this.t) { + for (n = t.s & this.DM, r = s; r < this.t; ++r) e[r] = i(this[r], n); + e.t = this.t + } else { + for (n = this.s & this.DM, r = s; r < t.t; ++r) e[r] = i(n, t[r]); + e.t = t.t + } + e.s = i(this.s, t.s), + e.clamp() + } + function st(t, i) { + return t & i + } + function ot(t) { + var i = r(); + return this.bitwiseTo(t, st, i), + i + } + function ht(t, i) { + return t | i + } + function ut(t) { + var i = r(); + return this.bitwiseTo(t, ht, i), + i + } + function at(t, i) { + return t ^ i + } + function ft(t) { + var i = r(); + return this.bitwiseTo(t, at, i), + i + } + function lt(t, i) { + return t & ~i + } + function ct(t) { + var i = r(); + return this.bitwiseTo(t, lt, i), + i + } + function pt() { + for (var t = r(), i = 0; i < this.t; ++i) t[i] = this.DM & ~this[i]; + return t.t = this.t, + t.s = ~this.s, + t + } + function yt(t) { + var i = r(); + return t < 0 ? this.rShiftTo( - t, i) : this.lShiftTo(t, i), + i + } + function vt(t) { + var i = r(); + return t < 0 ? this.lShiftTo( - t, i) : this.rShiftTo(t, i), + i + } + function gt(t) { + if (0 == t) return - 1; + var i = 0; + return 0 == (65535 & t) && (t >>= 16, i += 16), + 0 == (255 & t) && (t >>= 8, i += 8), + 0 == (15 & t) && (t >>= 4, i += 4), + 0 == (3 & t) && (t >>= 2, i += 2), + 0 == (1 & t) && ++i, + i + } + function mt() { + for (var t = 0; t < this.t; ++t) if (0 != this[t]) return t * this.DB + gt(this[t]); + return this.s < 0 ? this.t * this.DB: -1 + } + function dt(t) { + for (var i = 0; 0 != t;) t &= t - 1, + ++i; + return i + } + function Tt() { + for (var t = 0, + i = this.s & this.DM, + e = 0; e < this.t; ++e) t += dt(this[e] ^ i); + return t + } + function bt(t) { + var i = Math.floor(t / this.DB); + return i >= this.t ? 0 != this.s: 0 != (this[i] & 1 << t % this.DB) + } + function Ft(t, i) { + var r = e.ONE.shiftLeft(t); + return this.bitwiseTo(r, i, r), + r + } + function Bt(t) { + return this.changeBit(t, ht) + } + function xt(t) { + return this.changeBit(t, lt) + } + function wt(t) { + return this.changeBit(t, at) + } + function St(t, i) { + for (var e = 0, + r = 0, + n = Math.min(t.t, this.t); e < n;) r += this[e] + t[e], + i[e++] = r & this.DM, + r >>= this.DB; + if (t.t < this.t) { + for (r += t.s; e < this.t;) r += this[e], + i[e++] = r & this.DM, + r >>= this.DB; + r += this.s + } else { + for (r += this.s; e < t.t;) r += t[e], + i[e++] = r & this.DM, + r >>= this.DB; + r += t.s + } + i.s = r < 0 ? -1 : 0, + r > 0 ? i[e++] = r: r < -1 && (i[e++] = this.DV + r), + i.t = e, + i.clamp() + } + function kt(t) { + var i = r(); + return this.addTo(t, i), + i + } + function Dt(t) { + var i = r(); + return this.subTo(t, i), + i + } + function It(t) { + var i = r(); + return this.multiplyTo(t, i), + i + } + function Et() { + var t = r(); + return this.squareTo(t), + t + } + function Ot(t) { + var i = r(); + return this.divRemTo(t, i, null), + i + } + function qt(t) { + var i = r(); + return this.divRemTo(t, null, i), + i + } + function At(t) { + var i = r(), + e = r(); + return this.divRemTo(t, i, e), + new Array(i, e) + } + function Rt(t) { + this[this.t] = this.am(0, t - 1, this, 0, 0, this.t), + ++this.t, + this.clamp() + } + function Vt(t, i) { + if (0 != t) { + for (; this.t <= i;) this[this.t++] = 0; + for (this[i] += t; this[i] >= this.DV;) this[i] -= this.DV, + ++i >= this.t && (this[this.t++] = 0), + ++this[i] + } + } + function Mt() {} + function _t(t) { + return t + } + function Ct(t, i, e) { + t.multiplyTo(i, e) + } + function Lt(t, i) { + t.squareTo(i) + } + function Pt(t) { + return this.exp(t, new Mt) + } + function Ht(t, i, e) { + var r = Math.min(this.t + t.t, i); + for (e.s = 0, e.t = r; r > 0;) e[--r] = 0; + var n; + for (n = e.t - this.t; r < n; ++r) e[r + this.t] = this.am(0, t[r], e, r, 0, this.t); + for (n = Math.min(t.t, i); r < n; ++r) this.am(0, t[r], e, r, 0, i - r); + e.clamp() + } + function Nt(t, i, e) {--i; + var r = e.t = this.t + t.t - i; + for (e.s = 0; --r >= 0;) e[r] = 0; + for (r = Math.max(i - this.t, 0); r < t.t; ++r) e[this.t + r - i] = this.am(i - r, t[r], e, 0, 0, this.t + r - i); + e.clamp(), + e.drShiftTo(1, e) + } + function Ut(t) { + this.r2 = r(), + this.q3 = r(), + e.ONE.dlShiftTo(2 * t.t, this.r2), + this.mu = this.r2.divide(t), + this.m = t + } + function zt(t) { + if (t.s < 0 || t.t > 2 * this.m.t) return t.mod(this.m); + if (t.compareTo(this.m) < 0) return t; + var i = r(); + return t.copyTo(i), + this.reduce(i), + i + } + function jt(t) { + return t + } + function Xt(t) { + for (t.drShiftTo(this.m.t - 1, this.r2), t.t > this.m.t + 1 && (t.t = this.m.t + 1, t.clamp()), this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3), this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); t.compareTo(this.r2) < 0;) t.dAddOffset(1, this.m.t + 1); + for (t.subTo(this.r2, t); t.compareTo(this.m) >= 0;) t.subTo(this.m, t) + } + function Zt(t, i) { + t.squareTo(i), + this.reduce(i) + } + function Kt(t, i, e) { + t.multiplyTo(i, e), + this.reduce(e) + } + function Gt(t, i) { + var e, n, s = t.bitLength(), + o = l(1); + if (s <= 0) return o; + e = s < 18 ? 1 : s < 48 ? 3 : s < 144 ? 4 : s < 768 ? 5 : 6, + n = s < 8 ? new E(i) : i.isEven() ? new Ut(i) : new _(i); + var h = new Array, + u = 3, + a = e - 1, + f = (1 << e) - 1; + if (h[1] = n.convert(this), e > 1) { + var c = r(); + for (n.sqrTo(h[1], c); u <= f;) h[u] = r(), + n.mulTo(c, h[u - 2], h[u]), + u += 2 + } + var p, y, v = t.t - 1, + g = !0, + m = r(); + for (s = d(t[v]) - 1; v >= 0;) { + for (s >= a ? p = t[v] >> s - a & f: (p = (t[v] & (1 << s + 1) - 1) << a - s, v > 0 && (p |= t[v - 1] >> this.DB + s - a)), u = e; 0 == (1 & p);) p >>= 1, + --u; + if ((s -= u) < 0 && (s += this.DB, --v), g) h[p].copyTo(o), + g = !1; + else { + for (; u > 1;) n.sqrTo(o, m), + n.sqrTo(m, o), + u -= 2; + u > 0 ? n.sqrTo(o, m) : (y = o, o = m, m = y), + n.mulTo(m, h[p], o) + } + for (; v >= 0 && 0 == (t[v] & 1 << s);) n.sqrTo(o, m), + y = o, + o = m, + m = y, + --s < 0 && (s = this.DB - 1, --v) + } + return n.revert(o) + } + function Yt(t) { + var i = this.s < 0 ? this.negate() : this.clone(), + e = t.s < 0 ? t.negate() : t.clone(); + if (i.compareTo(e) < 0) { + var r = i; + i = e, + e = r + } + var n = i.getLowestSetBit(), + s = e.getLowestSetBit(); + if (s < 0) return i; + for (n < s && (s = n), s > 0 && (i.rShiftTo(s, i), e.rShiftTo(s, e)); i.signum() > 0;)(n = i.getLowestSetBit()) > 0 && i.rShiftTo(n, i), + (n = e.getLowestSetBit()) > 0 && e.rShiftTo(n, e), + i.compareTo(e) >= 0 ? (i.subTo(e, i), i.rShiftTo(1, i)) : (e.subTo(i, e), e.rShiftTo(1, e)); + return s > 0 && e.lShiftTo(s, e), + e + } + function Wt(t) { + if (t <= 0) return 0; + var i = this.DV % t, + e = this.s < 0 ? t - 1 : 0; + if (this.t > 0) if (0 == i) e = this[0] % t; + else for (var r = this.t - 1; r >= 0; --r) e = (i * e + this[r]) % t; + return e + } + function Jt(t) { + var i = t.isEven(); + if (this.isEven() && i || 0 == t.signum()) return e.ZERO; + for (var r = t.clone(), n = this.clone(), s = l(1), o = l(0), h = l(0), u = l(1); 0 != r.signum();) { + for (; r.isEven();) r.rShiftTo(1, r), + i ? (s.isEven() && o.isEven() || (s.addTo(this, s), o.subTo(t, o)), s.rShiftTo(1, s)) : o.isEven() || o.subTo(t, o), + o.rShiftTo(1, o); + for (; n.isEven();) n.rShiftTo(1, n), + i ? (h.isEven() && u.isEven() || (h.addTo(this, h), u.subTo(t, u)), h.rShiftTo(1, h)) : u.isEven() || u.subTo(t, u), + u.rShiftTo(1, u); + r.compareTo(n) >= 0 ? (r.subTo(n, r), i && s.subTo(h, s), o.subTo(u, o)) : (n.subTo(r, n), i && h.subTo(s, h), u.subTo(o, u)) + } + return 0 != n.compareTo(e.ONE) ? e.ZERO: u.compareTo(t) >= 0 ? u.subtract(t) : u.signum() < 0 ? (u.addTo(t, u), u.signum() < 0 ? u.add(t) : u) : u + } + function Qt(t) { + var i, e = this.abs(); + if (1 == e.t && e[0] <= vi[vi.length - 1]) { + for (i = 0; i < vi.length; ++i) if (e[0] == vi[i]) return ! 0; + return ! 1 + } + if (e.isEven()) return ! 1; + for (i = 1; i < vi.length;) { + for (var r = vi[i], n = i + 1; n < vi.length && r < gi;) r *= vi[n++]; + for (r = e.modInt(r); i < n;) if (r % vi[i++] == 0) return ! 1 + } + return e.millerRabin(t) + } + function $t(t) { + var i = this.subtract(e.ONE), + n = i.getLowestSetBit(); + if (n <= 0) return ! 1; + var s = i.shiftRight(n); (t = t + 1 >> 1) > vi.length && (t = vi.length); + for (var o = r(), h = 0; h < t; ++h) { + o.fromInt(vi[Math.floor(Math.random() * vi.length)]); + var u = o.modPow(s, this); + if (0 != u.compareTo(e.ONE) && 0 != u.compareTo(i)) { + for (var a = 1; a++> 8 & 255, + di[Ti++] ^= t >> 16 & 255, + di[Ti++] ^= t >> 24 & 255, + Ti >= xi && (Ti -= xi) + } + function ii() { + ti((new Date).getTime()) + } + function ei() { + if (null == mi) { + for (ii(), mi = ui(), mi.init(di), Ti = 0; Ti < di.length; ++Ti) di[Ti] = 0; + Ti = 0 + } + return mi.next() + } + function ri(t) { + var i; + for (i = 0; i < t.length; ++i) t[i] = ei() + } + function ni() {} + function si() { + this.i = 0, + this.j = 0, + this.S = new Array + } + function oi(t) { + var i, e, r; + for (i = 0; i < 256; ++i) this.S[i] = i; + for (e = 0, i = 0; i < 256; ++i) e = e + this.S[i] + t[i % t.length] & 255, + r = this.S[i], + this.S[i] = this.S[e], + this.S[e] = r; + this.i = 0, + this.j = 0 + } + function hi() { + var t; + return this.i = this.i + 1 & 255, + this.j = this.j + this.S[this.i] & 255, + t = this.S[this.i], + this.S[this.i] = this.S[this.j], + this.S[this.j] = t, + this.S[t + this.S[this.i] & 255] + } + function ui() { + return new si + } + var ai, fi = "undefined" != typeof navigator; + fi && "Microsoft Internet Explorer" == navigator.appName ? (e.prototype.am = s, ai = 30) : fi && "Netscape" != navigator.appName ? (e.prototype.am = n, ai = 26) : (e.prototype.am = o, ai = 28), + e.prototype.DB = ai, + e.prototype.DM = (1 << ai) - 1, + e.prototype.DV = 1 << ai; + e.prototype.FV = Math.pow(2, 52), + e.prototype.F1 = 52 - ai, + e.prototype.F2 = 2 * ai - 52; + var li, ci, pi = "0123456789abcdefghijklmnopqrstuvwxyz", + yi = new Array; + for (li = "0".charCodeAt(0), ci = 0; ci <= 9; ++ci) yi[li++] = ci; + for (li = "a".charCodeAt(0), ci = 10; ci < 36; ++ci) yi[li++] = ci; + for (li = "A".charCodeAt(0), ci = 10; ci < 36; ++ci) yi[li++] = ci; + E.prototype.convert = O, + E.prototype.revert = q, + E.prototype.reduce = A, + E.prototype.mulTo = R, + E.prototype.sqrTo = V, + _.prototype.convert = C, + _.prototype.revert = L, + _.prototype.reduce = P, + _.prototype.mulTo = N, + _.prototype.sqrTo = H, + e.prototype.copyTo = a, + e.prototype.fromInt = f, + e.prototype.fromString = c, + e.prototype.clamp = p, + e.prototype.dlShiftTo = b, + e.prototype.drShiftTo = F, + e.prototype.lShiftTo = B, + e.prototype.rShiftTo = x, + e.prototype.subTo = w, + e.prototype.multiplyTo = S, + e.prototype.squareTo = k, + e.prototype.divRemTo = D, + e.prototype.invDigit = M, + e.prototype.isEven = U, + e.prototype.exp = z, + e.prototype.toString = y, + e.prototype.negate = v, + e.prototype.abs = g, + e.prototype.compareTo = m, + e.prototype.bitLength = T, + e.prototype.mod = I, + e.prototype.modPowInt = j, + e.ZERO = l(0), + e.ONE = l(1), + Mt.prototype.convert = _t, + Mt.prototype.revert = _t, + Mt.prototype.mulTo = Ct, + Mt.prototype.sqrTo = Lt, + Ut.prototype.convert = zt, + Ut.prototype.revert = jt, + Ut.prototype.reduce = Xt, + Ut.prototype.mulTo = Kt, + Ut.prototype.sqrTo = Zt; + var vi = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997], + gi = (1 << 26) / vi[vi.length - 1]; + e.prototype.chunkSize = Y, + e.prototype.toRadix = J, + e.prototype.fromRadix = Q, + e.prototype.fromNumber = $, + e.prototype.bitwiseTo = nt, + e.prototype.changeBit = Ft, + e.prototype.addTo = St, + e.prototype.dMultiply = Rt, + e.prototype.dAddOffset = Vt, + e.prototype.multiplyLowerTo = Ht, + e.prototype.multiplyUpperTo = Nt, + e.prototype.modInt = Wt, + e.prototype.millerRabin = $t, + e.prototype.clone = X, + e.prototype.intValue = Z, + e.prototype.byteValue = K, + e.prototype.shortValue = G, + e.prototype.signum = W, + e.prototype.toByteArray = tt, + e.prototype.equals = it, + e.prototype.min = et, + e.prototype.max = rt, + e.prototype.and = ot, + e.prototype.or = ut, + e.prototype.xor = ft, + e.prototype.andNot = ct, + e.prototype.not = pt, + e.prototype.shiftLeft = yt, + e.prototype.shiftRight = vt, + e.prototype.getLowestSetBit = mt, + e.prototype.bitCount = Tt, + e.prototype.testBit = bt, + e.prototype.setBit = Bt, + e.prototype.clearBit = xt, + e.prototype.flipBit = wt, + e.prototype.add = kt, + e.prototype.subtract = Dt, + e.prototype.multiply = It, + e.prototype.divide = Ot, + e.prototype.remainder = qt, + e.prototype.divideAndRemainder = At, + e.prototype.modPow = Gt, + e.prototype.modInverse = Jt, + e.prototype.pow = Pt, + e.prototype.gcd = Yt, + e.prototype.isProbablePrime = Qt, + e.prototype.square = Et, + e.prototype.Barrett = Ut; + var mi, di, Ti; + if (null == di) { + di = new Array, + Ti = 0; + var bi; + if ("undefined" != typeof window && window.crypto) if (window.crypto.getRandomValues) { + var Fi = new Uint8Array(32); + for (window.crypto.getRandomValues(Fi), bi = 0; bi < 32; ++bi) di[Ti++] = Fi[bi] + } else if ("Netscape" == navigator.appName && navigator.appVersion < "5") { + var Bi = window.crypto.random(32); + for (bi = 0; bi < Bi.length; ++bi) di[Ti++] = 255 & Bi.charCodeAt(bi) + } + for (; Ti < xi;) bi = Math.floor(65536 * Math.random()), + di[Ti++] = bi >>> 8, + di[Ti++] = 255 & bi; + Ti = 0, + ii() + } + ni.prototype.nextBytes = ri, + si.prototype.init = oi, + si.prototype.next = hi; + var xi = 256; + i = t.exports = { + default: + e, + BigInteger: e, + SecureRandom: ni + } + }).call(this) +}, +function(t, i, e) { + "use strict"; + function r() { + return T + } + function n() { + var t = new p("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16), + i = new p("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16), + e = new p("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16), + r = new g(t, i, e); + return { + curve: r, + G: r.decodePointHex("0432C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"), + n: new p("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16) + } + } + function s() { + var t = new p(F.bitLength(), m).mod(F.subtract(p.ONE)).add(p.ONE), + i = u(t.toString(16), 64), + e = b.multiply(t); + return { + privateKey: i, + publicKey: "04" + u(e.getX().toBigInteger().toString(16), 64) + u(e.getY().toBigInteger().toString(16), 64) + } + } + function o(t) { + t = unescape(encodeURIComponent(t)); + for (var i = t.length, + e = [], r = 0; r < i; r++) e[r >>> 2] |= (255 & t.charCodeAt(r)) << 24 - r % 4 * 8; + for (var n = [], s = 0; s < i; s++) { + var o = e[s >>> 2] >>> 24 - s % 4 * 8 & 255; + n.push((o >>> 4).toString(16)), + n.push((15 & o).toString(16)) + } + return n.join("") + } + function h(t) { + return Array.prototype.map.call(new Uint8Array(t), + function(t) { + return ("00" + t.toString(16)).slice( - 2) + }).join("") + } + function u(t, i) { + return t.length >= i ? t: new Array(i - t.length + 1).join("0") + t + } + function a(t) { + for (var i = [], e = 0, r = 0; r < 2 * t.length; r += 2) i[r >>> 3] |= parseInt(t[e], 10) << 24 - r % 8 * 4, + e++; + for (var n = [], s = 0; s < t.length; s++) { + var o = i[s >>> 2] >>> 24 - s % 4 * 8 & 255; + n.push((o >>> 4).toString(16)), + n.push((15 & o).toString(16)) + } + return n.join("") + } + function f(t) { + for (var i = [], e = 0, r = 0; r < 2 * t.length; r += 2) i[r >>> 3] |= parseInt(t[e], 10) << 24 - r % 8 * 4, + e++; + try { + for (var n = [], s = 0; s < t.length; s++) { + var o = i[s >>> 2] >>> 24 - s % 4 * 8 & 255; + n.push(String.fromCharCode(o)) + } + return decodeURIComponent(escape(n.join(""))) + } catch(t) { + throw new Error("Malformed UTF-8 data") + } + } + function l(t) { + var i = [], + e = t.length; + e % 2 != 0 && (t = u(t, e + 1)), + e = t.length; + for (var r = 0; r < e; r += 2) i.push(parseInt(t.substr(r, 2), 16)); + return i + } + var c = e(0), + p = c.BigInteger, + y = c.SecureRandom, + v = e(5), + g = v.ECCurveFp, + m = new y, + d = n(), + T = d.curve, + b = d.G, + F = d.n; + t.exports = { + getGlobalCurve: r, + generateEcparam: n, + generateKeyPairHex: s, + parseUtf8StringToHex: o, + parseArrayBufferToHex: h, + leftPad: u, + arrayToHex: a, + arrayToUtf8: f, + hexToArray: l + } +}, +function(t, i, e) { + "use strict"; + function r(t, i) { + if (! (t instanceof i)) throw new TypeError("Cannot call a class as a function") + } + var n = function() { + function t(t, i) { + for (var e = 0; e < i.length; e++) { + var r = i[e]; + r.enumerable = r.enumerable || !1, + r.configurable = !0, + "value" in r && (r.writable = !0), + Object.defineProperty(t, r.key, r) + } + } + return function(i, e, r) { + return e && t(i.prototype, e), + r && t(i, r), + i + } + } (), + s = e(0), + o = s.BigInteger, + h = e(1), + u = function(t, i, e, r, n) { + for (var s = 0; s < n; s++) e[r + s] = t[i + s] + }, + a = { + minValue: -parseInt("10000000000000000000000000000000", 2), + maxValue: parseInt("1111111111111111111111111111111", 2), + parse: function(t) { + if (t < this.minValue) { + for (var i = new Number( - t), e = i.toString(2), r = e.substr(e.length - 31, 31), n = "", s = 0; s < r.length; s++) { + n += "0" == r.substr(s, 1) ? "1": "0" + } + return parseInt(n, 2) + 1 + } + if (t > this.maxValue) { + for (var o = Number(t), h = o.toString(2), u = h.substr(h.length - 31, 31), a = "", f = 0; f < u.length; f++) { + a += "0" == u.substr(f, 1) ? "1": "0" + } + return - (parseInt(a, 2) + 1) + } + return t + }, + parseByte: function(t) { + if (t < 0) { + for (var i = new Number( - t), e = i.toString(2), r = e.substr(e.length - 8, 8), n = "", s = 0; s < r.length; s++) { + n += "0" == r.substr(s, 1) ? "1": "0" + } + return parseInt(n, 2) + 1 + } + if (t > 255) { + var o = Number(t), + h = o.toString(2); + return parseInt(h.substr(h.length - 8, 8), 2) + } + return t + } + }, + f = function() { + function t() { + r(this, t), + this.xBuf = new Array, + this.xBufOff = 0, + this.byteCount = 0, + this.DIGEST_LENGTH = 32, + this.v0 = [1937774191, 1226093241, 388252375, 3666478592, 2842636476, 372324522, 3817729613, 2969243214], + this.v0 = [1937774191, 1226093241, 388252375, -628488704, -1452330820, 372324522, -477237683, -1325724082], + this.v = new Array(8), + this.v_ = new Array(8), + this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + this.X = new Array(68), + this.xOff = 0, + this.T_00_15 = 2043430169, + this.T_16_63 = 2055708042, + arguments.length > 0 ? this.initDigest(arguments[0]) : this.init() + } + return n(t, [{ + key: "init", + value: function() { + this.xBuf = new Array(4), + this.reset() + } + }, + { + key: "initDigest", + value: function(t) { + this.xBuf = [].concat(t.xBuf), + this.xBufOff = t.xBufOff, + this.byteCount = t.byteCount, + u(t.X, 0, this.X, 0, t.X.length), + this.xOff = t.xOff, + u(t.v, 0, this.v, 0, t.v.length) + } + }, + { + key: "getDigestSize", + value: function() { + return this.DIGEST_LENGTH + } + }, + { + key: "reset", + value: function() { + this.byteCount = 0, + this.xBufOff = 0; + for (var t in this.xBuf) this.xBuf[t] = null; + u(this.v0, 0, this.v, 0, this.v0.length), + this.xOff = 0, + u(this.X0, 0, this.X, 0, this.X0.length) + } + }, + { + key: "processBlock", + value: function() { + var t = void 0, + i = this.X, + e = new Array(64); + for (t = 16; t < 68; t++) i[t] = this.p1(i[t - 16] ^ i[t - 9] ^ this.rotate(i[t - 3], 15)) ^ this.rotate(i[t - 13], 7) ^ i[t - 6]; + for (t = 0; t < 64; t++) e[t] = i[t] ^ i[t + 4]; + var r = this.v, + n = this.v_; + u(r, 0, n, 0, this.v0.length); + var s = void 0, + o = void 0, + h = void 0, + f = void 0, + l = void 0; + for (t = 0; t < 16; t++) l = this.rotate(n[0], 12), + s = a.parse(a.parse(l + n[4]) + this.rotate(this.T_00_15, t)), + s = this.rotate(s, 7), + o = s ^ l, + h = a.parse(a.parse(this.ff_00_15(n[0], n[1], n[2]) + n[3]) + o) + e[t], + f = a.parse(a.parse(this.gg_00_15(n[4], n[5], n[6]) + n[7]) + s) + i[t], + n[3] = n[2], + n[2] = this.rotate(n[1], 9), + n[1] = n[0], + n[0] = h, + n[7] = n[6], + n[6] = this.rotate(n[5], 19), + n[5] = n[4], + n[4] = this.p0(f); + for (t = 16; t < 64; t++) l = this.rotate(n[0], 12), + s = a.parse(a.parse(l + n[4]) + this.rotate(this.T_16_63, t)), + s = this.rotate(s, 7), + o = s ^ l, + h = a.parse(a.parse(this.ff_16_63(n[0], n[1], n[2]) + n[3]) + o) + e[t], + f = a.parse(a.parse(this.gg_16_63(n[4], n[5], n[6]) + n[7]) + s) + i[t], + n[3] = n[2], + n[2] = this.rotate(n[1], 9), + n[1] = n[0], + n[0] = h, + n[7] = n[6], + n[6] = this.rotate(n[5], 19), + n[5] = n[4], + n[4] = this.p0(f); + for (t = 0; t < 8; t++) r[t] ^= a.parse(n[t]); + this.xOff = 0, + u(this.X0, 0, this.X, 0, this.X0.length) + } + }, + { + key: "processWord", + value: function(t, i) { + var e = t[i] << 24; + e |= (255 & t[++i]) << 16, + e |= (255 & t[++i]) << 8, + e |= 255 & t[++i], + this.X[this.xOff] = e, + 16 == ++this.xOff && this.processBlock() + } + }, + { + key: "processLength", + value: function(t) { + this.xOff > 14 && this.processBlock(), + this.X[14] = this.urShiftLong(t, 32), + this.X[15] = 4294967295 & t + } + }, + { + key: "intToBigEndian", + value: function(t, i, e) { + i[e] = a.parseByte(this.urShift(t, 24)), + i[++e] = a.parseByte(this.urShift(t, 16)), + i[++e] = a.parseByte(this.urShift(t, 8)), + i[++e] = a.parseByte(t) + } + }, + { + key: "doFinal", + value: function(t, i) { + this.finish(); + for (var e = 0; e < 8; e++) this.intToBigEndian(this.v[e], t, i + 4 * e); + return this.reset(), + this.DIGEST_LENGTH + } + }, + { + key: "update", + value: function(t) { + this.xBuf[this.xBufOff++] = t, + this.xBufOff == this.xBuf.length && (this.processWord(this.xBuf, 0), this.xBufOff = 0), + this.byteCount++ + } + }, + { + key: "blockUpdate", + value: function(t, i, e) { + for (; 0 != this.xBufOff && e > 0;) this.update(t[i]), + i++, + e--; + for (; e > this.xBuf.length;) this.processWord(t, i), + i += this.xBuf.length, + e -= this.xBuf.length, + this.byteCount += this.xBuf.length; + for (; e > 0;) this.update(t[i]), + i++, + e-- + } + }, + { + key: "finish", + value: function() { + var t = this.byteCount << 3; + for (this.update(128); 0 != this.xBufOff;) this.update(0); + this.processLength(t), + this.processBlock() + } + }, + { + key: "rotate", + value: function(t, i) { + return t << i | this.urShift(t, 32 - i) + } + }, + { + key: "p0", + value: function(t) { + return t ^ this.rotate(t, 9) ^ this.rotate(t, 17) + } + }, + { + key: "p1", + value: function(t) { + return t ^ this.rotate(t, 15) ^ this.rotate(t, 23) + } + }, + { + key: "ff_00_15", + value: function(t, i, e) { + return t ^ i ^ e + } + }, + { + key: "ff_16_63", + value: function(t, i, e) { + return t & i | t & e | i & e + } + }, + { + key: "gg_00_15", + value: function(t, i, e) { + return t ^ i ^ e + } + }, + { + key: "gg_16_63", + value: function(t, i, e) { + return t & i | ~t & e + } + }, + { + key: "urShift", + value: function(t, i) { + return (t > a.maxValue || t < a.minValue) && (t = a.parse(t)), + t >= 0 ? t >> i: (t >> i) + (2 << ~i) + } + }, + { + key: "urShiftLong", + value: function(t, i) { + var e = void 0, + r = new o; + if (r.fromInt(t), r.signum() >= 0) e = r.shiftRight(i).intValue(); + else { + var n = new o; + n.fromInt(2); + var s = ~i, + h = ""; + if (s < 0) { + for (var u = 64 + s, + a = 0; a < u; a++) h += "0"; + var f = new o; + f.fromInt(t >> i); + var l = new o("10" + h, 2); + h = l.toRadix(10); + e = l.add(f).toRadix(10) + } else h = n.shiftLeft(~i).intValue(), + e = (t >> i) + h + } + return e + } + }, + { + key: "getZ", + value: function(t, i) { + var e = h.parseUtf8StringToHex("1234567812345678"), + r = 4 * e.length; + this.update(r >> 8 & 255), + this.update(255 & r); + var n = h.hexToArray(e); + this.blockUpdate(n, 0, n.length); + var s = h.hexToArray(t.curve.a.toBigInteger().toRadix(16)), + o = h.hexToArray(t.curve.b.toBigInteger().toRadix(16)), + u = h.hexToArray(t.getX().toBigInteger().toRadix(16)), + a = h.hexToArray(t.getY().toBigInteger().toRadix(16)), + f = h.hexToArray(i.substr(0, 64)), + l = h.hexToArray(i.substr(64, 64)); + this.blockUpdate(s, 0, s.length), + this.blockUpdate(o, 0, o.length), + this.blockUpdate(u, 0, u.length), + this.blockUpdate(a, 0, a.length), + this.blockUpdate(f, 0, f.length), + this.blockUpdate(l, 0, l.length); + var c = new Array(this.getDigestSize()); + return this.doFinal(c, 0), + c + } + }]), + t + } (); + t.exports = f +}, +function(t, i, e) { + "use strict"; + function r(t, i) { + var e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1, + r = new g; + t = m.hexToArray(m.parseUtf8StringToHex(t)), + i.length > 128 && (i = i.substr(i.length - 128)); + var n = i.substr(0, 64), + s = i.substr(64); + i = r.createPoint(n, s); + var o = r.initEncipher(i); + r.encryptBlock(t); + var h = m.arrayToHex(t), + u = new Array(32); + return r.doFinal(u), + u = m.arrayToHex(u), + e === B ? o + h + u: o + u + h + } + function n(t, i) { + var e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1, + r = new g; + i = new l(i, 16); + var n = t.substr(0, 64), + s = t.substr(0 + n.length, 64), + o = n.length + s.length, + h = t.substr(o, 64), + u = t.substr(o + 64); + e === B && (h = t.substr(t.length - 64), u = t.substr(o, t.length - o - 64)); + var a = m.hexToArray(u), + f = r.createPoint(n, s); + r.initDecipher(i, f), + r.decryptBlock(a); + var c = new Array(32); + if (r.doFinal(c), m.arrayToHex(c) === h) return m.arrayToUtf8(a); + return "" + } + function s(t, i) { + var e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, + r = e.pointPool, + n = e.der, + s = e.hash, + o = e.publicKey, + f = "string" == typeof t ? m.parseUtf8StringToHex(t) : m.parseArrayBufferToHex(t); + s && (o = o || u(i), f = h(f, o)); + var c = new l(i, 16), + y = new l(f, 16), + v = null, + g = null, + d = null; + do { + do { + var T = void 0; + T = r && r.length ? r.pop() : a(), v = T.k, g = y.add(T.x1).mod(F) + } while ( g . equals ( l . ZERO ) || g.add(v).equals(F)); + d = c.add(l.ONE).modInverse(F).multiply(v.subtract(g.multiply(c))).mod(F) + } while ( d . equals ( l . ZERO )); + return n ? p(g, d) : m.leftPad(g.toString(16), 64) + m.leftPad(d.toString(16), 64) + } + function o(t, i, e) { + var r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {}, + n = r.der, + s = r.hash, + o = "string" == typeof t ? m.parseUtf8StringToHex(t) : m.parseArrayBufferToHex(t); + s && (o = h(o, e)); + var u = void 0, + a = void 0; + if (n) { + var f = y(i); + u = f.r, + a = f.s + } else u = new l(i.substring(0, 64), 16), + a = new l(i.substring(64), 16); + var c = b.decodePointHex(e), + p = new l(o, 16), + v = u.add(a).mod(F); + if (v.equals(l.ZERO)) return ! 1; + var g = T.multiply(a).add(c.multiply(v)), + d = p.add(g.getX().toBigInteger()).mod(F); + return u.equals(d) + } + function h(t, i) { + var e = new v, + r = (new v).getZ(T, i.substr(2, 128)), + n = m.hexToArray(m.arrayToHex(r).toString()), + s = t, + o = m.hexToArray(s), + h = new Array(e.getDigestSize()); + return e.blockUpdate(n, 0, n.length), + e.blockUpdate(o, 0, o.length), + e.doFinal(h, 0), + m.arrayToHex(h).toString() + } + function u(t) { + var i = T.multiply(new l(t, 16)); + return "04" + m.leftPad(i.getX().toBigInteger().toString(16), 64) + m.leftPad(i.getY().toBigInteger().toString(16), 64) + } + function a() { + var t = m.generateKeyPairHex(), + i = b.decodePointHex(t.publicKey); + return t.k = new l(t.privateKey, 16), + t.x1 = i.getX().toBigInteger(), + t + } + var f = e(0), + l = f.BigInteger, + c = e(4), + p = c.encodeDer, + y = c.decodeDer, + v = e(2), + g = e(6), + m = e(1), + d = m.generateEcparam(), + T = d.G, + b = d.curve, + F = d.n, + B = 0; + t.exports = { + generateKeyPairHex: m.generateKeyPairHex, + doEncrypt: r, + doDecrypt: n, + doSignature: s, + doVerifySignature: o, + getPoint: a + } +}, +function(t, i, e) { + "use strict"; + function r(t, i) { + if (!t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return ! i || "object" != typeof i && "function" != typeof i ? t: i + } + function n(t, i) { + if ("function" != typeof i && null !== i) throw new TypeError("Super expression must either be null or a function, not " + typeof i); + t.prototype = Object.create(i && i.prototype, { + constructor: { + value: t, + enumerable: !1, + writable: !0, + configurable: !0 + } + }), + i && (Object.setPrototypeOf ? Object.setPrototypeOf(t, i) : t.__proto__ = i) + } + function s(t, i) { + if (! (t instanceof i)) throw new TypeError("Cannot call a class as a function") + } + function o(t) { + var i = t.toString(16); + if ("-" !== i.substr(0, 1)) i.length % 2 == 1 ? i = "0" + i: i.match(/^[0-7]/) || (i = "00" + i); + else { + var e = i.substr(1), + r = e.length; + r % 2 == 1 ? r += 1 : i.match(/^[0-7]/) || (r += 2); + for (var n = "", + s = 0; s < r; s++) n += "f"; + i = new g(n, 16).xor(t).add(g.ONE).toString(16).replace(/^-/, "") + } + return i + } + function h(t, i) { + if ("8" !== t.substring(i + 2, i + 3)) return 1; + var e = parseInt(t.substring(i + 3, i + 4)); + return 0 === e ? -1 : 0 < e && e < 10 ? e + 1 : -2 + } + function u(t, i) { + var e = h(t, i); + return e < 1 ? "": t.substring(i + 2, i + 2 + 2 * e) + } + function a(t, i) { + var e = u(t, i); + if ("" === e) return - 1; + var r = void 0; + return r = parseInt(e.substring(0, 1)) < 8 ? new g(e, 16) : new g(e.substring(2), 16), + r.intValue() + } + function f(t, i) { + var e = h(t, i); + return e < 0 ? l_len: i + 2 * (e + 1) + } + function l(t, i) { + var e = f(t, i), + r = a(t, i); + return t.substring(e, e + 2 * r) + } + function c(t, i) { + return f(t, i) + 2 * a(t, i) + } + function p(t, i) { + var e = [], + r = f(t, i); + e.push(r); + for (var n = a(t, i), s = r, o = 0;;) { + var h = c(t, s); + if (null === h || h - r >= 2 * n) break; + if (o >= 200) break; + e.push(h), + s = h, + o++ + } + return e + } + var y = function() { + function t(t, i) { + for (var e = 0; e < i.length; e++) { + var r = i[e]; + r.enumerable = r.enumerable || !1, + r.configurable = !0, + "value" in r && (r.writable = !0), + Object.defineProperty(t, r.key, r) + } + } + return function(i, e, r) { + return e && t(i.prototype, e), + r && t(i, r), + i + } + } (), + v = e(0), + g = v.BigInteger, + m = function() { + function t() { + s(this, t), + this.isModified = !0, + this.hTLV = null, + this.hT = "00", + this.hL = "00", + this.hV = "" + } + return y(t, [{ + key: "getLengthHexFromValue", + value: function() { + var t = this.hV.length / 2, + i = t.toString(16); + return i.length % 2 == 1 && (i = "0" + i), + t < 128 ? i: (128 + i.length / 2).toString(16) + i + } + }, + { + key: "getEncodedHex", + value: function() { + return (null == this.hTLV || this.isModified) && (this.hV = this.getFreshValueHex(), this.hL = this.getLengthHexFromValue(), this.hTLV = this.hT + this.hL + this.hV, this.isModified = !1), + this.hTLV + } + }, + { + key: "getFreshValueHex", + value: function() { + return "" + } + }]), + t + } (), + d = function(t) { + function i(t) { + s(this, i); + var e = r(this, (i.__proto__ || Object.getPrototypeOf(i)).call(this)); + return e.hT = "02", + t && t.bigint && (e.hTLV = null, e.isModified = !0, e.hV = o(t.bigint)), + e + } + return n(i, t), + y(i, [{ + key: "getFreshValueHex", + value: function() { + return this.hV + } + }]), + i + } (m), + T = function(t) { + function i(t) { + s(this, i); + var e = r(this, (i.__proto__ || Object.getPrototypeOf(i)).call(this)); + return e.hT = "30", + e.asn1Array = [], + t && t.array && (e.asn1Array = t.array), + e + } + return n(i, t), + y(i, [{ + key: "getFreshValueHex", + value: function() { + for (var t = "", + i = 0; i < this.asn1Array.length; i++) { + t += this.asn1Array[i].getEncodedHex() + } + return this.hV = t, + this.hV + } + }]), + i + } (m); + t.exports = { + encodeDer: function(t, i) { + var e = new d({ + bigint: t + }), + r = new d({ + bigint: i + }); + return new T({ + array: [e, r] + }).getEncodedHex() + }, + decodeDer: function(t) { + var i = p(t, 0), + e = i[0], + r = i[1], + n = l(t, e), + s = l(t, r); + return { + r: new g(n, 16), + s: new g(s, 16) + } + } + } +}, +function(t, i, e) { + "use strict"; + function r(t, i) { + if (! (t instanceof i)) throw new TypeError("Cannot call a class as a function") + } + var n = function() { + function t(t, i) { + for (var e = 0; e < i.length; e++) { + var r = i[e]; + r.enumerable = r.enumerable || !1, + r.configurable = !0, + "value" in r && (r.writable = !0), + Object.defineProperty(t, r.key, r) + } + } + return function(i, e, r) { + return e && t(i.prototype, e), + r && t(i, r), + i + } + } (), + s = e(0), + o = s.BigInteger, + h = new o("3"), + u = function() { + function t(i, e) { + r(this, t), + this.x = e, + this.q = i + } + return n(t, [{ + key: "equals", + value: function(t) { + return t === this || this.q.equals(t.q) && this.x.equals(t.x) + } + }, + { + key: "toBigInteger", + value: function() { + return this.x + } + }, + { + key: "negate", + value: function() { + return new t(this.q, this.x.negate().mod(this.q)) + } + }, + { + key: "add", + value: function(i) { + return new t(this.q, this.x.add(i.toBigInteger()).mod(this.q)) + } + }, + { + key: "subtract", + value: function(i) { + return new t(this.q, this.x.subtract(i.toBigInteger()).mod(this.q)) + } + }, + { + key: "multiply", + value: function(i) { + return new t(this.q, this.x.multiply(i.toBigInteger()).mod(this.q)) + } + }, + { + key: "divide", + value: function(i) { + return new t(this.q, this.x.multiply(i.toBigInteger().modInverse(this.q)).mod(this.q)) + } + }, + { + key: "square", + value: function() { + return new t(this.q, this.x.square().mod(this.q)) + } + }]), + t + } (), + a = function() { + function t(i, e, n, s) { + r(this, t), + this.curve = i, + this.x = e, + this.y = n, + this.z = void 0 === s ? o.ONE: s, + this.zinv = null + } + return n(t, [{ + key: "getX", + value: function() { + return null === this.zinv && (this.zinv = this.z.modInverse(this.curve.q)), + this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)) + } + }, + { + key: "getY", + value: function() { + return null === this.zinv && (this.zinv = this.z.modInverse(this.curve.q)), + this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)) + } + }, + { + key: "equals", + value: function(t) { + return t === this || (this.isInfinity() ? t.isInfinity() : t.isInfinity() ? this.isInfinity() : !!t.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(t.z)).mod(this.curve.q).equals(o.ZERO) && t.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(t.z)).mod(this.curve.q).equals(o.ZERO)) + } + }, + { + key: "isInfinity", + value: function() { + return null === this.x && null === this.y || this.z.equals(o.ZERO) && !this.y.toBigInteger().equals(o.ZERO) + } + }, + { + key: "negate", + value: function() { + return new t(this.curve, this.x, this.y.negate(), this.z) + } + }, + { + key: "add", + value: function(i) { + if (this.isInfinity()) return i; + if (i.isInfinity()) return this; + var e = this.x.toBigInteger(), + r = this.y.toBigInteger(), + n = this.z, + s = i.x.toBigInteger(), + h = i.y.toBigInteger(), + u = i.z, + a = this.curve.q, + f = e.multiply(u).mod(a), + l = s.multiply(n).mod(a), + c = f.subtract(l), + p = r.multiply(u).mod(a), + y = h.multiply(n).mod(a), + v = p.subtract(y); + if (o.ZERO.equals(c)) return o.ZERO.equals(v) ? this.twice() : this.curve.infinity; + var g = f.add(l), + m = n.multiply(u).mod(a), + d = c.square().mod(a), + T = c.multiply(d).mod(a), + b = m.multiply(v.square()).subtract(g.multiply(d)).mod(a), + F = c.multiply(b).mod(a), + B = v.multiply(d.multiply(f).subtract(b)).subtract(p.multiply(T)).mod(a), + x = T.multiply(m).mod(a); + return new t(this.curve, this.curve.fromBigInteger(F), this.curve.fromBigInteger(B), x) + } + }, + { + key: "twice", + value: function() { + if (this.isInfinity()) return this; + if (!this.y.toBigInteger().signum()) return this.curve.infinity; + var i = this.x.toBigInteger(), + e = this.y.toBigInteger(), + r = this.z, + n = this.curve.q, + s = this.curve.a.toBigInteger(), + o = i.square().multiply(h).add(s.multiply(r.square())).mod(n), + u = e.shiftLeft(1).multiply(r).mod(n), + a = e.square().mod(n), + f = a.multiply(i).multiply(r).mod(n), + l = u.square().mod(n), + c = o.square().subtract(f.shiftLeft(3)).mod(n), + p = u.multiply(c).mod(n), + y = o.multiply(f.shiftLeft(2).subtract(c)).subtract(l.shiftLeft(1).multiply(a)).mod(n), + v = u.multiply(l).mod(n); + return new t(this.curve, this.curve.fromBigInteger(p), this.curve.fromBigInteger(y), v) + } + }, + { + key: "multiply", + value: function(t) { + if (this.isInfinity()) return this; + if (!t.signum()) return this.curve.infinity; + for (var i = t.multiply(h), e = this.negate(), r = this, n = i.bitLength() - 2; n > 0; n--) { + r = r.twice(); + var s = i.testBit(n); + s !== t.testBit(n) && (r = r.add(s ? this: e)) + } + return r + } + }]), + t + } (), + f = function() { + function t(i, e, n) { + r(this, t), + this.q = i, + this.a = this.fromBigInteger(e), + this.b = this.fromBigInteger(n), + this.infinity = new a(this, null, null) + } + return n(t, [{ + key: "equals", + value: function(t) { + return t === this || this.q.equals(t.q) && this.a.equals(t.a) && this.b.equals(t.b) + } + }, + { + key: "fromBigInteger", + value: function(t) { + return new u(this.q, t) + } + }, + { + key: "decodePointHex", + value: function(t) { + switch (parseInt(t.substr(0, 2), 16)) { + case 0: + return this.infinity; + case 2: + case 3: + return null; + case 4: + case 6: + case 7: + var i = (t.length - 2) / 2, + e = t.substr(2, i), + r = t.substr(i + 2, i); + return new a(this, this.fromBigInteger(new o(e, 16)), this.fromBigInteger(new o(r, 16))); + default: + return null + } + } + }]), + t + } (); + t.exports = { + ECPointFp: a, + ECCurveFp: f + } +}, +function(t, i, e) { + "use strict"; + function r(t, i) { + if (! (t instanceof i)) throw new TypeError("Cannot call a class as a function") + } + var n = function() { + function t(t, i) { + for (var e = 0; e < i.length; e++) { + var r = i[e]; + r.enumerable = r.enumerable || !1, + r.configurable = !0, + "value" in r && (r.writable = !0), + Object.defineProperty(t, r.key, r) + } + } + return function(i, e, r) { + return e && t(i.prototype, e), + r && t(i, r), + i + } + } (), + s = e(0), + o = s.BigInteger, + h = e(2), + u = e(1), + a = function() { + function t() { + r(this, t), + this.ct = 1, + this.p2 = null, + this.sm3keybase = null, + this.sm3c3 = null, + this.key = new Array(32), + this.keyOff = 0 + } + return n(t, [{ + key: "reset", + value: function() { + this.sm3keybase = new h, + this.sm3c3 = new h; + var t = u.hexToArray(this.p2.getX().toBigInteger().toRadix(16)), + i = u.hexToArray(this.p2.getY().toBigInteger().toRadix(16)); + this.sm3keybase.blockUpdate(t, 0, t.length), + this.sm3c3.blockUpdate(t, 0, t.length), + this.sm3keybase.blockUpdate(i, 0, i.length), + this.ct = 1, + this.nextKey() + } + }, + { + key: "nextKey", + value: function() { + var t = new h(this.sm3keybase); + t.update(this.ct >> 24 & 255), + t.update(this.ct >> 16 & 255), + t.update(this.ct >> 8 & 255), + t.update(255 & this.ct), + t.doFinal(this.key, 0), + this.keyOff = 0, + this.ct++ + } + }, + { + key: "initEncipher", + value: function(t) { + var i = u.generateKeyPairHex(), + e = new o(i.privateKey, 16), + r = i.publicKey; + return this.p2 = t.multiply(e), + this.reset(), + r.length > 128 && (r = r.substr(r.length - 128)), + r + } + }, + { + key: "encryptBlock", + value: function(t) { + this.sm3c3.blockUpdate(t, 0, t.length); + for (var i = 0; i < t.length; i++) this.keyOff === this.key.length && this.nextKey(), + t[i] ^= 255 & this.key[this.keyOff++] + } + }, + { + key: "initDecipher", + value: function(t, i) { + this.p2 = i.multiply(t), + this.reset() + } + }, + { + key: "decryptBlock", + value: function(t) { + for (var i = 0; i < t.length; i++) this.keyOff === this.key.length && this.nextKey(), + t[i] ^= 255 & this.key[this.keyOff++]; + this.sm3c3.blockUpdate(t, 0, t.length) + } + }, + { + key: "doFinal", + value: function(t) { + var i = u.hexToArray(this.p2.getY().toBigInteger().toRadix(16)); + this.sm3c3.blockUpdate(i, 0, i.length), + this.sm3c3.doFinal(t, 0), + this.reset() + } + }, + { + key: "createPoint", + value: function(t, i) { + var e = "04" + t + i; + return u.getGlobalCurve().decodePointHex(e) + } + }]), + t + } (); + t.exports = a +}]); \ No newline at end of file diff --git a/source/conf.py b/source/conf.py new file mode 100644 index 0000000..e89cd4f --- /dev/null +++ b/source/conf.py @@ -0,0 +1,99 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- +project = '北大数瑞大数据区块链' +copyright = '2021, Peking University' +author = 'Peking University' + +# The full version, including alpha/beta/rc tags +release = 'V1.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. + +html_theme = "sphinx_rtd_theme" +html_logo="_static/imgs/logo.png" +html_theme_options = { +'logo_only': True +} + +source_parsers = { + '.md': 'recommonmark.parser.CommonMarkParser', +} + +source_suffix = ['.rst', '.md'] + +# source_suffix = { +# '.rst': 'restructuredtext', +# '.txt': 'markdown', +# '.md': 'markdown' +# } + +extensions = [ + 'recommonmark', + 'sphinx_rtd_theme', + 'sphinx_markdown_tables' +] + +html_favicon = "_static/imgs/favicon.ico" +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'zh_CN' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +#html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +master_doc = 'index' + +latex_elements = { + 'papersize': 'a4paper', + # Additional stuff for the LaTeX preamble. + 'preamble': ''' +\usepackage{xeCJK} +\usepackage{indentfirst} +\setlength{\parindent}{2em} +\setCJKmainfont[BoldFont=STFangsong, ItalicFont=STKaiti]{STSong} +\setCJKsansfont[BoldFont=STHeiti]{STXihei} +\setCJKmonofont{STFangsong} +''', +} diff --git a/source/index.rst b/source/index.rst new file mode 100644 index 0000000..06a22c5 --- /dev/null +++ b/source/index.rst @@ -0,0 +1,18 @@ +.. BDContract documentation master file, created by + sphinx-quickstart on Mon Nov 25 16:23:38 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +北大数瑞大数据区块链 文档 +====================================== + +.. toctree:: + :maxdepth: 3 + :caption: 目录 + + Introduction.rst + InstallTips.rst + IDEUsage.rst + ContractAPI.rst + YJSInDepth.rst + YJSAPI.rst \ No newline at end of file diff --git a/source/markdown/ContractAPI.md b/source/markdown/ContractAPI.md new file mode 100644 index 0000000..3226a25 --- /dev/null +++ b/source/markdown/ContractAPI.md @@ -0,0 +1,3511 @@ +# BDContract SDK +除使用可视化的智能合约在线IDE外,用户还可使用WebSocket接口、Http接口、Bash接口来启动和运行合约. + +- - - + +## WebSocketSDK下载与安装 +合约SDK提供javascript版本与java版本的客户端。 + +java客户端的下载链接为:[java source](./_static/BDWareJavaClient.zip)和[jar](./_static/BDWareConfigTool.zip) +可参考java_source下的README.md及测试用例。 + +javascript的下载链接为:[js SDK](./_static/js/createWS.js) +内置的SM2加密库链接:[sm2 SDK](./_static/js/sm2.js) + +### 建立连接 +建立与节点服务器之间的WebSocket连接. + +#### 参数 + +| 字段 | 值 | +| ---------- | ------------------------------------------------------------ | +| url | 建立WebSocket的服务器URL. 使用`http`协议时, 前缀为`ws://`, 如`"ws://localhost:1717/SCIDE/SCExecutor"`; 使用`https`协议时, 前缀为`wss://` | +| msgHandler | 收到服务器WebSocket回复后的回调函数, 用户可自行编写, 也可参考下面提供的示例 | + +#### 请求示例 + +```javascript +var url = "ws://127.0.0.1:1717/SCIDE/SCExecutor";//与Slave节点建立连接 +//var url = "ws://127.0.0.1:1718/NodeCenterWS";//与Manager节点建立连接 +var msgHandler = function(m){ + console.log("recmsg:"); + console.log(m); +}; +var onOpenHandler=undefined; +wssocket = createWssocket(url,onOpenHandler,msgHandler); +``` + +#### 返回结果示例 + +``` +{ + receiveSeg: [Function (anonymous)], + isSending: false, + sendList: [], + monitor: [Function (anonymous)], + send: [Function (anonymous)], + sendNextSegment: [Function (anonymous)], + isOpen: [Function (anonymous)] +} +``` + + + +### ping + +`ping`服务器测试 + +#### 参数 + +| 字段 | 值 | +| ------ | ---- | +| action | ping | + +#### 请求示例 + +``` +var request = {}; +request.action = "ping"; +wssocket.send(JSON.stringify(request)); +``` + +#### 返回结果示例 + +``` +{ + "action":"pong" +} +``` + +### 登录 + +使用Websocket接口调用需要权限的接口时,不论是连接CenterPortal还是NodePortal必须先**登录**。 +登录的流程有3步: + +- 客户端向服务端建立连接,连接建立完成后发送{"action":"getSessionID"}(可在onOpenHandler中实现) +- 服务端收到请求后,会向客户端返回类似{"action":"onGetSessionID","session":"-4959947809200104526_session"}的结果 +- 客户端收到onGetSessionID后,会使用本地的公私钥对sessionID进行签名,并调用login接口 +- 服务端会返回onLogin的结果,data字段返回的是该公钥对应的角色。 + +- - - + +## 用户角色划分 + +### 合约节点的角色划分 + +在合约节点(NodePortal.html)中分为NodeManager/ContractProvider/ContractInstanceManager/ContractUser四类角色。 + +| 角色 | 说明 | +| ----------------------- | ------------------------------------------------------------ | +| NodeManager | 该节点的管理者,拥有用户管理、节点配置等权限 | +| ContractProvider | 拥有编辑合约、开发合约代码、运行调试等权限 | +| ContractInstanceManager | 拥有启、停合约实例、配置合约实例IO等权限 | +| ContractUser | 拥有查看合约实例列表、调用合约等权限 | +| Anonymous | 匿名用户,可以调用合约,可以申请成为ContractProvider/InstanceManager等角色 | + + +| 接口 | 说明 | 角色 | +| ------------------------------- | -------------------- | ----------------------------------------- | +| changeDumpPeriod | 设置备份周期 | ContractInstanceManager; | +| createLedger | 创建账本 | ContractInstanceManager; | +| dumpContract | 手动备份 | ContractInstanceManager; | +| deleteMemoryFile | 删除镜像 | ContractInstanceManager; | +| forkContract | 迁移合约 | ContractInstanceManager; | +| getDumpPeriod | 获取备份周期 | ContractInstanceManager; | +| killAllContract | 停止全部实例 | ContractInstanceManager; | +| killContractProcess | 停止某一实例 | ContractInstanceManager; | +| listMemoryFiles | 列取某一实例的镜像 | ContractInstanceManager; | +| loadMemory | 加载镜像 | ContractInstanceManager; | +| queryContractInstanceDOI | 查询合约实例信息 | ContractInstanceManager; | +| rebuildHashIndex | | ContractInstanceManager; | +| setPermission | | ContractProvider;ContractInstanceManager; | +| startContract | 启动合约 | ContractInstanceManager; | +| startContractBatched | 废弃 | ContractInstanceManager; | +| startContractByYPK | 启动合约 | ContractInstanceManager; | +| startContractInTempZips | 废弃 | ContractInstanceManager; | +| startContractConfig | 启动合约(集群模式) | ContractInstanceManager; | +| updateContract | | ContractInstanceManager; | +| connectTo | 连接合约实例输出流 | ContractInstanceManager;ContractUser; | +| countContractLogGroupByAction | | ContractInstanceManager;ContractUser; | +| countContractLogGroupByCategory | | ContractInstanceManager;ContractUser; | +| getLastLog | 查询日志 | ContractInstanceManager;ContractUser; | +| getLog | 查询日志 | ContractInstanceManager;ContractUser; | +| getLogSize | 查询日志 | ContractInstanceManager;ContractUser; | +| listAllContractProcess | | ContractInstanceManager;ContractUser; | +| listContractProcess | 查询合约实例列表 | ContractInstanceManager;ContractUser; | +| listLeakContractProcess | | ContractInstanceManager;ContractUser; | +| queryContractLogByDate | | ContractInstanceManager;ContractUser; | +| queryContractLogByKey | | ContractInstanceManager;ContractUser; | +| queryContractLogByOffset | | ContractInstanceManager;ContractUser; | +| queryContractLogDetail | | ContractInstanceManager;ContractUser; | +| queryContractLogSize | | ContractInstanceManager;ContractUser; | +| queryNodeLogByDate | | ContractInstanceManager;ContractUser; | +| queryNodeLogByOffset | | ContractInstanceManager;ContractUser; | +| queryNodeLogSize | | ContractInstanceManager;ContractUser; | +| rebuildContractLogIndex | | ContractInstanceManager;ContractUser; | +| rebuildNodeLogIndex | | ContractInstanceManager;ContractUser; | +| changePublic | | ContractProvider; | +| createFile | 新建文件 | ContractProvider; | +| deleteFile | 删除文件 | ContractProvider; | +| distributeContract | | ContractProvider; | +| downloadContract | | ContractProvider; | +| downloadContractFromOtherHost | | ContractProvider; | +| generateAnnotationSample | | ContractProvider; | +| generateAppDataAnalysis | | ContractProvider; | +| generateAppDataSource | | ContractProvider; | +| generateBDCoinEventProject | | ContractProvider; | +| generateBDCoinProject | | ContractProvider; | +| generateBiddingExample | | ContractProvider; | +| generateCSVProject | | ContractProvider; | +| generateContractExecutor | | ContractProvider; | +| generateDAC4BDOA | | ContractProvider; | +| generateDAC4BDOA_persist | | ContractProvider; | +| generateDACSample | | ContractProvider; | +| generateEmptyProject | | ContractProvider; | +| generateEventPublisher | | ContractProvider; | +| generateEventSubscriber | | ContractProvider; | +| generateGasExample | | ContractProvider; | +| generateHello | | ContractProvider; | +| generateHttpExample | | ContractProvider; | +| generateIncentives | | ContractProvider; | +| generateJSONExample | | ContractProvider; | +| generateLedgerExample | | ContractProvider; | +| generateLedgerProject | | ContractProvider; | +| generateLicenceManager | | ContractProvider; | +| generateLoggerExample | | ContractProvider; | +| generateMySQLExample | | ContractProvider; | +| generateMySQLProject | | ContractProvider; | +| generatePostgreSQLSample | | ContractProvider; | +| generateReadme | | ContractProvider; | +| generateRenderSample | | ContractProvider; | +| generateRocksDBSample | | ContractProvider; | +| generateSM2Example | | ContractProvider; | +| generateStaticResource | | ContractProvider; | +| generateTFLinux | | ContractProvider; | +| generategenerateTFMac | | ContractProvider; | +| getProject | | ContractProvider; | +| getTemplateList | | ContractProvider; | +| importContractInstanceCodeByDOI | | ContractProvider; | +| listFile | | ContractProvider; | +| listProject | | ContractProvider; | +| listProjectPermission | | ContractProvider; | +| listProjects | | ContractProvider; | +| renameFile | | ContractProvider; | +| saveFile | | ContractProvider; | +| startContractAsDebug | | ContractProvider; | +| uploadFile | | ContractProvider; | +| compile | | ContractProvider;ContractInstanceManager; | +| evaluates | | ContractProvider;ContractInstanceManager; | +| executeContractP2PTrustfully | | ContractProvider;ContractInstanceManager; | +| getCodeByID | 查询代码 | ContractProvider;ContractInstanceManager; | +| getControlFlowByFileName | | ContractProvider;ContractInstanceManager; | +| getGasValue | | ContractProvider;ContractInstanceManager; | +| listCompiledFiles | | ContractProvider;ContractInstanceManager; | +| queryContractResourceInfo | | ContractProvider;ContractInstanceManager; | +| queryFreeResourceInfo | | ContractProvider;ContractInstanceManager; | +| staticVerifyContract | | ContractProvider;ContractInstanceManager; | +| writeDyjs | | ContractProvider;ContractInstanceManager; | +| authNodeRole | 授权角色 | NodeManager; | +| changeBDledger | 修改账本配置 | NodeManager; | +| changeIpPort | | NodeManager; | +| changeNodeCenter | 修改集群地址 | NodeManager; | +| changeNodeName | | NodeManager; | +| changeIpPort | | NodeManager; | +| changeDOIPConfig | | NodeManager; | +| changeYJSPath | | NodeManager; | +| countNodeLogGroupByCategory | | NodeManager; | +| countRole | | NodeManager; | +| deleteRole | | NodeManager; | +| downloadUUID | 废弃 | NodeManager; | +| getEncodedUUID | 废弃 | NodeManager; | +| getPeerID | | NodeManager; | +| listAllAuthRole | | NodeManager; | +| listNodeInfos | | NodeManager; | +| listUnAuthRole | | NodeManager; | +| loadConfig | | NodeManager; | +| loadNodeConfig | | NodeManager; | +| lockEdit | | NodeManager; | +| unlockEdit | | NodeManager; | +| updateConfig | | NodeManager; | +| uploadLicence | | NodeManager; | +| applyNodeRole | 申请角色 | 任意角色 | +| executeContract | 调用合约 | 任意角色 | +| getConnCount | | 任意角色 | +| getHashAbstractLocally | | 任意角色 | +| getHashLocally | | 任意角色 | +| getNodeRoleDeprecated | 查询当前角色 | 任意角色 | +| getSessionID | | 任意角色 | +| listAdapters | | 任意角色 | +| listTheContractProcess | | 任意角色 | +| login | 登录 | 任意角色 | +| longStr | | 任意角色 | +| ping | | 任意角色 | +| queryDataByHash | | 任意角色 | +| queryDataByHashLocally | | 任意角色 | +| queryHashByOffset | | 任意角色 | +| queryHashByRequestID | | 任意角色 | +| queryHashSize | | 任意角色 | +| queryLedgers | | 任意角色 | +| queryRole | | 任意角色 | +| queryTransactionByHash | | 任意角色 | +| sendTransaction | | 任意角色 | +| setLogStage | | 任意角色 | + +### 合约准入中心角色划分 + +共分为两类角色:CenterManager和NodeManager。其中,CenterManager拥有对集群设置的权限。 +NodeManager可以增加、删除节点等操作。 + +| 接口 | 说明 | 角色 | +| ----------------------------- | ------------ | -------------------------- | +| authNodeManager | | CenterManager; | +| countActionLogByCategory | | CenterManager; | +| countCMLogByCategory | | CenterManager; | +| delete | | CenterManager; | +| listAllUsers | | CenterManager; | +| listApplyList | | CenterManager; | +| listLicence | | CenterManager; | +| queryActionLog | | CenterManager; | +| queryCMLog | | CenterManager; | +| updateLicence | | CenterManager; | +| addNode | | CenterManager;NodeManager; | +| changeNCFile | | CenterManager;NodeManager; | +| changeOtherNC | | CenterManager;NodeManager; | +| createTrustUnit | 创建可信集群 | CenterManager;NodeManager; | +| deleteTrustUnit | | CenterManager;NodeManager; | +| getNCFile | | CenterManager;NodeManager; | +| getNodeTrustUnits | | CenterManager;NodeManager; | +| getOtherNC | | CenterManager;NodeManager; | +| listContractProcess | | CenterManager;NodeManager; | +| listMultiPointContractProcess | | CenterManager;NodeManager; | +| listNodes | | CenterManager;NodeManager; | +| listTrustUnits | | CenterManager;NodeManager; | +| queryUserStat | | CenterManager;NodeManager; | +| stopMultiPointContractProcess | | CenterManager;NodeManager; | +| applyRole | | NodeManager; | +| executeContract | 调用合约 | 任意角色 | +| executeContractTrustfully | | 任意角色 | +| getManagerPubkey | | 任意角色 | +| getNodeRole | | 任意角色 | +| getNodeSessionID | | 任意角色 | +| getRole | | 任意角色 | +| getSessionID | | 任意角色 | +| login | 登录 | 任意角色 | + +- - - + +## 合约节点Http接口 + +`http://xxx.xxx.xxx.xxx:1717/SCIDE/SCManager`为提供Http接口服务的服务器 URL(`xxx.xxx.xxx.xxx:1717`为BDWare SCIDE运行的IP和端口号) , 用户可通过在URL后附加字段参数, 完成以下功能. +`http://xxx.xxx.xxx.xxx:18000/SCIDE/SCManager` 为提供Http接口服务的服务器 + +URL(`xxx.xxx.xxx.xxx:1717` 为BDWare SCIDE运行的IP和端口号),用户可通过在URL后附加字段参数,完成以下功能: + + +### 用户管理类 + +#### ping + +`ping`服务器测试 + +##### 方法 + +GET + +##### 参数 + + +| 字段 | 值 | +| ------ | ---- | +| action | ping | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=ping +``` + +##### 返回结果示例 + +```json +{"data":"pong"} +``` + + +### 合约代码管理类 + + +#### 下载合约项目 + +##### 方法 + +GET + +##### 参数 + + +| 字段 | 值 | +| ----------- | ---------------- | +| action | downloadContract | +| projectName | 合约项目名 | +| isPrivate | 是否在私有目录下 | +| pubKey | 用户公钥 | +| timestamp | 时间戳 | +| sign | 签名 | + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=downloadContract&projectName=BDCoin&isPrivate=false&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba3 +8b7ff78aa631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 +``` + +#### 上传文件 + +##### 方法 + +POST + + +##### 参数 + + +| 字段 | 值 | +| --------- | ---------------- | +| path | 文件上传路径 | +| fileName | 待上传文件名 | +| isPrivate | 是否在私有目录下 | +| order | 第几个数据包 | +| count | 数据包总数 | +| timestamp | 时间戳 | +| sign | 签名 | + + +##### 请求示例 + + +``` +http://127.0.0.1:18000/SCIDE/Upload?path=/TEST/TEST.yjs&fileName=WechatIMG15.jpeg&isPrivate=true&order=0&count=3&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba36ca83066870cf2c1d5de6df67e24e68dde7934af9b31d94a6084281db3d32d5ce42ab8f75bf799aca05&sign=dd867469f5adf9986e4ea6215febeae50c7d4c3836d002cf8c17050dfca031fd2595ffa8646e9eeae53150d2cbaea690e27d818eaf5cea3632ee1b69c3307a4b631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 +``` + +##### 返回结果示例 + +```json +{"status":"true","data":"success"} +``` + +#### 保存合约脚本 + +向服务器发送请求, 向服务器本地保存合约脚本内容. + +##### 方法 + +GET + + +##### 参数 + +| 字段 | 值 | +| ------- | -------------- | +| action | writeDyjs | +| target | 合约脚本文件名 | +| content | 合约脚本内容 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=writeDyjs&target=testyjs.yjs&content=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onWriteDyjs", + "data": "success" +} +``` + +后续用户可启动并调用该合约. + + + + + + + +### 合约实例管理类 + +#### 查询合约进程 + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=listContractProcess +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onListContractProcess", + "data": "[\n {\n \"id\": \"-562752842\",\n \"name\": \"shortc\",\n \"port\": \"1626\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]" +} +``` + + +#### 启动合约 + +向服务器发送请求, 启动某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------------- | +| action | startContract | +| script | 合约脚本内容, 需进行进行URIEncode | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContract&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D +``` + +##### 返回结果示例 + +```json +{ + "data": "{\"status\":\"Success\",\"result\":\"\"}", + "action": "onStartContract", + "cid": "-562752842", + "executeTime": 1187 +} +``` + + + +#### 调用合约 + +向服务器发送请求, 调用某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------------------- | --------------------------- | +| action | executeContract | +| contractID | 合约ID | +| withDynamicAnalysis | true/false 是否进行动态分析 | +| operation | 调用合约的方法名 | +| arg | 调用合约的参数 | +| pubkey | 可选,调用者公钥 | +| signature | 可选,签名 | + + +其中pubkey为sm2的公钥,计算方式如下: + +```javascript +//sm2 可从sm2.js中加载获得。 +signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); +``` + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=executeContract&contractID=-620602333&operation=main&arg=hhh +``` + +##### 返回结果示例 + +```json +{ + "data": "{\"status\":\"Success\",\"result\":\"3\"}", + "action": "onExecuteResult", + "executeTime": "13" +} +``` + + + + +#### 批量启动合约 + +向服务器发送请求, 启动服务器中保存有合约脚本的一系列合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ------------------------------------ | +| action | startContractBatched | +| fileList | 合约脚本文件列表(Json数组,URLEncode) | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContractBatched&fileList=%5B%20%22EventPuber.yjs%22%2C%20%22EventSuber.yjs%22%2C%20%22LicenceManager.yjs%22%20%5D + +``` + +##### 返回结果示例 + +```json +{"EventPuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","LicenceManager.yjs":"{\"status\":\"Success\",\"result\":\"\"}","EventSuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","action":"onStartContract"} + +``` + + + + +#### 启动Zip包合约 + +向服务器发送请求, 启动服务器中包装为`zip`格式的合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| --------- | ----------------------- | +| action | startContractInTempZips | +| owner | 调用者公钥 | +| path | zip合约(路径及)文件名 | +| signature | 调用者签名 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContractInTempZips&owner=0475c7b061f32477c1e228dd04143daf58a5574dc3f6b02bd2857cc794eb92bfe98606dc314049e77fd8714f57a5a481cb470cc759e688fe60d40fc87092165e55&path=traceTest.zip&signature=650d3cad50509682937c253d84da99230e8ea1bcfb9b10f6d18f8888c7c4b6b4%2C72231a6daa078a3ce657c0a2ed38251b7db56cf725beaf86780d4c240b19ccc2 + +``` + +##### 返回结果示例 + +```json +{"data":"verify failed","action":"onStartContract"} + +``` + + + + +#### 获取合约代码 + +向服务器发送请求, 获取某个ID合约的脚本代码. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ----------- | +| action | getCodeByID | +| contractID | 合约ID | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=getCodeByID&contractID=814046805 + +``` + +##### 返回结果示例 + +```json +{"status":true,"action":"onCodeResult","data":"@LogType(\"Arg\")\ncontract EventSuberAtCHQ{\n\t\n \texport function init(arg){\n\t\tvar result \u003d YancloudUtil.subscribe(\"EventPuberAt3966\",\"abc\",handler);\n // print(\"Handler:\"+handler);\n \t \n \t\treturn result;\n\t}\n \texport function handler(e){\n var ret \u003d \"ReceiveEvent:\";\n\t\tret+\u003d\"\\n\";\n \tprint(ret);\n \tret+\u003dYancloudUtil.executeContract(\"EventPuberAt3966\",\"notify\",\"success\");\n \tprint(ret);\n return ret;\n\t}\n}\n"} + +``` + + + + +#### 保存合约状态 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------ | +| action | dumpContract | +| contractID | 合约ID 或 合约Name= | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/SCManager?action=dumpContract&contractID=counter&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022004ffd1346b936196f5b13953d2f3e11823a0d0a2d2f6fecea258cef8e20d99c0022100bbc219ed1f56799ba28a763b9e9e47063164e7ceecfbfa752de42f44551ffb83 + +``` + +##### 返回结果示例 + +```json +{"data":"success","size":"3.76 KB","time":"0.03s"} + +``` + + + + +#### 获取合约内存文件列表 + +向服务器发送请求, 获取某子文件夹中的所有内存文件列表. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | listMemoryFiles | +| contractID | 合约Id 或 合约Name | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/SCManager?action=listMemoryFiles&contractID=-247468535&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022075c7268e888b0efdef167a3f4dfc6589d771c6be41b3c0a1dc12d057e811f395022100d44f460d0cc3643e169ef08231e75a1e895646c53295c0ef1d15c3b462a53d6b + +``` + +##### 返回结果示例 + +```json +{"data":["2020-09-23.18:40:38","2020-09-24.16:03:41","2020-09-24.16:58:39","2020-09-24.18:25:47","2020-09-24.18:32:37","2020-09-24.20:54:41","2020-09-24.20:57:39","2020-09-24.21:31:07","2020-09-24.21:32:09","2020-09-24.21:36:11","2020-09-28.15:29:15","2020-09-28.20:28:29","2020-09-28.20:39:46","2020-09-28.21:45:31","2020-09-28.21:49:18","2020-09-28.22:27:34","2020-09-28.22:31:09","2020-09-28.22:32:49","2020-10-07.16:51:06","2020-10-07.16:51:23","2020-10-25.21:09:10","2020-12-14.19:06:53","2021-02-02.10:28:56","2021-02-02.10:31:13"],"action":"onListMemoryFiles"} + +``` + +#### 停止合约 + +向服务器发送请求, 停止某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------------- | +| action | killContractProcess | +| id | 合约ID | +| *requestID | 请求ID, String类型 | + +`*`表示可选参数 + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=killContractProcess&id=-1759263594 + +``` + +##### 返回结果示例 + +```json +{"status":false,"action":"onListContractProcess","data":"[\n {\n \"id\": \"-65051856\",\n \"name\": \"EventSuber\",\n \"port\": \"1631\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"814046805\",\n \"name\": \"EventSuberAtCHQ\",\n \"port\": \"1630\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"2023975189\",\n \"name\": \"LicenceService\",\n \"port\": \"1632\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"-620602333\",\n \"name\": \"shortc\",\n \"port\": \"1627\",\n \"times\": \"0 \",\n \"traffic\": \"0.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]"} + +``` + + + + +#### 停止所有合约 + +向服务器发送请求, 停止服务器上启动的所有合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | killAllContract | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=killAllContract + +``` + +##### 返回结果示例 + +```json +{"status":false,"action":"onKillAllContract","data":"Kill:7357,7541,7548,7555,7584,7585,7591,7598,7609,7612,8440,8442,8444,8521,"} + +``` + +#### 静态分析合约 + +向服务器发送请求, 静态分析合约脚本. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------- | +| action | staticVerifyContract | +| contractid | 合约ID | +| script | 请求ID, String类型 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=staticVerifyContract&contractid=943728900&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D&path=static.yjs + +``` + +##### 返回结果示例 + +```json +{"data":"{\"status\":\"Success\",\"result\":\"{\\\"main\\\":\\\"Ret:arg \\\"}\"}","action":"onExecuteResult","cid":"943728900","executeTime":54} + +``` + + + +#### 获取合约静态分析流 + +向服务器发送请求, 获取某个合约的静态分析Control Flow. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------------ | +| action | getControlFlowByFileName | +| path | 合约ID | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=getControlFlowByFileName&path=EventSuber.yjs + +``` + +##### 返回结果示例 + +```json +{"init":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","aload 4","invokedynamic dyn:getProp|getElem|getMethod:YancloudUtil (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B3","stmts":["dup","invokedynamic dyn:getMethod|getProp|getElem:subscribe (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B4","stmts":["swap","ldc XiaomiSmartHomeAtPKU","ldc onAirPurifierModeChange","aload 4","invokedynamic dyn:getProp|getElem|getMethod:handler (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B5","stmts":["invokedynamic dyn:call:\\\u003dYancloudUtil\\,subscribe (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B6","stmts":["\u003dL3\u003d","astore 5"],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B7","stmts":["\u003dL4\u003d","aload 5","areturn"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B8","stmts":["\u003dL5\u003d"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B9","stmts":["\u003dL6\u003d"],"original":" \t\treturn result;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B9","label":{"label":"e"}}]},"handler":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","ldc ReceiveEvent:","aload 2","invokedynamic dyn:getProp|getElem|getMethod:content (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B3","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B4","stmts":["ldc ","invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B5","stmts":["aload 2","invokedynamic dyn:getProp|getElem|getMethod:type (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B6","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B7","stmts":["\u003dL3\u003d","astore 5"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B8","stmts":["\u003dL4\u003d","aload 4","invokedynamic dyn:getMethod|getProp|getElem:print (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B9","stmts":["getstatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime UNDEFINED Lwrp/jdk/nashorn/internal/runtime/Undefined;","aload 5","invokedynamic dyn:call:print (Ljava/lang/Object;Lwrp/jdk/nashorn/internal/runtime/Undefined;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B10","stmts":["pop"],"original":" \tprint(ret);"},{"type":"Continuous","name":"B11","stmts":["\u003dL5\u003d","aload 5","areturn"],"original":" return ret;"},{"type":"Continuous","name":"B12","stmts":["\u003dL6\u003d"],"original":" return ret;"},{"type":"Continuous","name":"B13","stmts":["\u003dL7\u003d"],"original":" return ret;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B8","label":{"label":"e"}},{"from":"B8","to":"B9","label":{"label":"e"}},{"from":"B9","to":"B10","label":{"label":"e"}},{"from":"B10","to":"B11","label":{"label":"e"}},{"from":"B11","to":"B13","label":{"label":"e"}}]}} + +``` + +### 日志查看类 + +#### 合约日志-查询数量 + +##### 方法 + +GET + +contractName为空或是不传入时,则为查询全部合约的条数 + + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------------------ | +| action | queryContractLogSize | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogSize&contractName=NanningDataSource +``` + +##### 返回结果示例 + +```json +{ + "size": 12, + "action": "onQueryContractLogSize", + "status": "success" +} + +``` + +#### 合约日志-根据日期查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------------------------------- | +| action | queryContractLogByDate | +| start | long,必须,起始时间 | +| end | long,非必须,若无end,默认为当前时间 | +| contractName | 字符串,非必须,合约名称 | + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByDate&start=1597296300272&end=1597296305747 +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getMainFrame", + "costTime": "2493", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296300272, + "key": "-8590335427581967208" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "732", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296301030, + "key": "849660532962309239" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4580", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305745, + "key": "-8003529429500512736" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4551", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305746, + "key": "7604666709899222357" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305751, + "key": "-7561786202695627022" + } + ], + "action": "onQueryRecentContractLog" +} +``` + +#### 合约日志-根据偏移量查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | --------------------------------------------- | +| action | queryContractLogByOffset | +| count | long,必须,获取日志条数 | +| offset | long,非必须,若无offset,默认返回最新count条 | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByOffset&count=5&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305842, + "key": "-2390672423847654148" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "isOwner", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305868, + "key": "6056586201629372511" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getApplyList", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305893, + "key": "3882409580676458151" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getAcceptList", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305908, + "key": "-3437513873417136535" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654, + "key": "203156239086062402" + } + ], + "action": "onQueryRecentContractLog" +} +``` + +#### 合约日志-根据key查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------- | +| action | queryContractLogByKey | +| key | long,必须,该日志对应的key | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByKey&key=203156239086062402 +``` + +##### 返回结果 + +```json +{ + "data": { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654 + }, + "action": "onQueryContractLogByKey" +} +``` + +#### 合约日志-按时间段统计调用次数 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------------------------------------------- | +| action | countContractLogGroupByCategory | +| start | long,必须,起始时间 | +| end | 非必须,终止时间,默认为当前 | +| interval | long,非必须,统计间隔 | +| category | 非必须,合约名称以逗号连接,不传入时统计全部合约调用情况 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=countContractLogGroupByCategory&start=1596758400000&interval=86400000 +``` + +##### 返回结果 + +```json +{ + "start": 1596758400000, + "interval": 86400000, + "action": "onCountContractLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 43, + 14 + ] +} +``` + +#### 账本日志-查询数量 + +查询通过本节点去账本上记录的日志数量 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ---------------- | +| action | queryHashSize | +| contractName | 非必须,合约名称 | + + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashSize&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "count": "2", + "action": "onQueryHashSize" +} +``` + + +#### 账本日志-根据偏移量查询 + +查询x条通过本节点去账本上记录的日志的哈希列表 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ----------------------------------------------------------- | +| action | queryHashByOffset | +| count | 整数,必须,表示条数 | +| offset | 整数,非必须,表示偏移量,不传入offset则默认返回最新count条 | +| contractName | 字符串,非必须,表示合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashByOffset&count=1&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "hash": "3a6c60621907146b77146c1f2d48700e47520173", + "date": 1597296314658 + } + ], + "action": "onQueryHash", + "status": "success" +} +``` + +#### 账本日志-根据hash查询详情 + +根据hash来查询日志内容 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------------------- | +| action | queryDataByHash | +| hash | 字符串,可通过queryHashByOffset | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryDataByHash&count=1&contractName=NanningDataSource&hash=3a6c60621907146b77146c1f2d48700e47520173 +``` + +##### 返回结果 + +```json +{ + "from": "0x3034643139323433323966373263656431343866", + "to": "0x65786563757465436f6e74726163740000000000", + "data": "1597296314655 --> {\"extraGas\":\"0\",\"totalGas\":\"0\",\"executionGas\":\"0\",\"signature\":\"4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02\",\"costTime\":\"6\",\"arg\":\" {\\\\\\\"year\\\\\\\":2018,\\\\\\\"category\\\\\\\":\\\\\\\"工业\\\\\\\",\\\\\\\"indexType\\\\\\\":\\\\\\\"营业额\\\\\\\"}\",\"contractID\":\"-1382208250\",\"action\":\"analysisByIndustry\",\"pubKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}", + "requestID": "1597296314629_6067", + "action": "onQueryDataByHash" +} +``` + +#### 账本日志-根据requestID查询Hash + +根据requestID来查询日志内容,需由开发者保证requestID的唯一性 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| --------- | ------------------------ | +| action | queryHashByRequestID | +| requestID | 字符串,在发起调用时生成 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=queryHashByRequestID&requestID=0987654321ab +``` + +#### 节点日志-查询数量 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ---------------------------- | +| action | queryNodeLogSize | +| category | 非必须,不传入时查询全部情况 | + +其中包括:ping、startContract、saveFile等。 + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize + +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize&category=login +``` + +##### 返回结果 + +```json +{ + "size": 177, + "action": "onQueryNodeLogSize", + "status": "success" +} +``` + +#### 节点日志-按日期查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ---------------------------- | +| action | queryNodeLogByDate | +| start | long,必须,起始日期 | +| end | long,非必须 | +| category | 非必须,不传入时查询全部情况 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1597376006441 + +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1596758400000&category=login +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByDate" +} +``` + +#### 节点日志-按偏移量查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | --------------------------------------------- | +| action | queryNodeLogByOffset | +| count | long,必须,获取日志条数 | +| offset | long,非必须,若无offset,默认返回最新count条 | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByOffset&count=5 +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByOffset" +} +``` + +#### 节点日志-按时间段统计调用次数 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------------------------------------- | +| action | countLogGroupByCategory | +| start | long,必须,起始时间 | +| end | 非必须,终止时间,默认为当前 | +| interval | long,非必须,统计间隔 | +| category | 非必须,action以逗号连接,不传入时统计全部调用情况 | + +其中,category中的action为NodePortal的接口的action集合。 +包括:ping、startContract、saveFile等。 + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000 + +http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000&category=ping,startContract +``` + +##### 返回结果 + +```json +{ + "start": 1596758400000, + "interval": 86400000, + "action": "onCountNodeLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 912, + 761 + ] +} +``` + + + + + +#### 输出历史记录日志 + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------ | +| action | printTimeTravelLog | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=printTimeTravelLog + +``` + +##### 返回结果示例 + +```json +{"status":false,"data":"[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa_1572335939893.dyjs\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n"} + +``` + + + + + +#### 输出节点转移日志 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | printTransferLog | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=printTransferLog + +``` + +##### 返回结果示例 + +```json +{"status":false,"data":""} + +``` + + + +### 模板生成类 + + + + + + + +- - - + +## 合约节点WebSocket接口 + +### 用户管理类 + +#### 获取Session + +登录前获取session以便进行签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | getSessionID | + +##### 请求示例 + +``` +var req = {}; +req.action = "getSessionID"; +wssocket.send(JSON.stringify(req)); +``` + + +##### 返回结果 + +```json +{ + "action": "onSessionID", + "session": "9782323_session" +} +``` + +#### 用户登录 + +用户进行公私钥身份验证 + +##### 参数 + +| 字段 | 值 | +| ------ | ----- | +| action | login | + +##### 请求示例 + +``` +var loginParam = {}; +loginParam.pubKey = global.sm2Key.publicKey; +loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); +loginParam.action = "login"; +wssocket.send(JSON.stringify(loginParam)); +``` + +##### 返回结果 + +```json +{ + "action": "onLogin", + "data": "NodeManager,ContractProvider" +} +``` + +#### 申请角色 + +在节点管理员界面申请可以申请称为合约管理员(ContractInstanceManager)、合约使用者(ContractUser)、合约提供者(ContractProvider) + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | applyNodeRole | +|role|申请角色名称| + +##### 请求示例 + +``` +var param = {}; +param.action = "applyNodeRole"; +param.role = "ContractUser"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +``` json +{ + "action": "onApplyRole", + "data": "success" +} + +{ + "action":"onApplyRole", + "data":"already has!" +} +``` + +#### 授权角色 + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------- | +| action | authNodeRole | +| isAccept | bool类型,表示否授权 | +| pubKey | 授权用户公钥 | + + +##### 请求示例 + +``` +var param = {}; +param.action = "authNodeRole"; +param.isAccept = true; +param.pubKey = "xxxxx"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onAuthNodeRole", + "data": "success" +} +``` + +#### 删除用户角色 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------- | +| action | deleteRole | +| role | 删除角色名称 | + +##### 请求示例 + +``` +var deleteInfo = {}; +deleteInfo.pubKey = global.authorizedUsers.[publicKey]; +deleteInfo.action = "deleteRole"; +deleteInfo.role="ContractUser"; +wssocket.send(JSON.stringify(deleteInfo)); +``` + +##### 返回结果 + +```json +{ + "action": "onDeleteRole", + "data": "success" +} +``` + +#### 查看授权用户列表 + +查看准入管理员当前组网中已经授权的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | listAllAuthRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "listAllAuthRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onListAllAuthRole", + "data": + { + "kv":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"NodeManager,ContractProvider,ContractUser,ContractInstanceManager"}], + "time":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"1617178709933"}] + } +} +``` + +#### 查看申请用户列表 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | listUnAuthRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "listUnAuthRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onListUnAuthRole", + "kv": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "ContractProvider,ContractUser" + }], + "time": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "1587398989914" + }] +} +``` + + +##### 参数(删除) + +| 字段 | 值 | +| ------ | ------------- | +| action | queryUserStat | + +##### 请求示例 + +``` +var param = {}; +param.action = "queryUserStat"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 +} +``` + +### 合约代码管理类 + +#### 获取公共合约文件列表 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | listProjects | + +##### 请求示例 + +``` +var request = {}; +request.action = "listProjects"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\",\"BiddingExample\",\"ContractExecutor\"]", + "executeTime":0, + "isPrivate":false +} + +``` + + +#### 获取私有合约文件列表 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listProjects | +| pubKey | 该用户的公钥 | +|isPrivate|true| + +##### 请求示例 + +```javascript +var request = {}; +request.action = "listProjects"; +request.pubKey = "global.sm2.publicKey"; +request.isPrivate=true; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` + + +#### 获取合约实例 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +``` +var request = {}; +request.action = "listContractProcess"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onListContractProcess", + "data":"[{\"id\": \"1658407837\",\"name\": \"BDCoin\",\"port\": \"1617\"}]" +} +``` + + +#### 启动合约 + +##### 参数 + +| 字段 | 值 | +| --------- | ------------- | +| action | startContract | +| owner | pubkey | +| requestID | 当前时间 | +| script | 脚本内容 | +| signature | 签名 | + +##### 请求示例 + +``` +request.action = "startContract"; +request.owner = global.sm2Key.publicKey; +request.requestID = new Date().getTime() + ""; +request.script = global.projectScript; +request.signature = sm2.doSignature("Algorithm|" + request.script + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":\"\",\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStartContract", + "cid":"-506393888", + "executeTime":2496, + "responseID":"1617206735696" +} +``` + +#### 分发合约项目 + +##### 参数 + +| 字段 | 值 | +| ------------- | ------------------ | +| action | distributeContract | +| peersID | 集群中节点peer | +| projectName | 合约名 | +| isPrivate | 是否在私有目录 | +| sponsorPeerID | 发起者ID | +| signature | 签名 | + +##### 请求示例 + +```javascript +request.action = "distributeContract"; +request.peersID = peersID; +request.projectName = global.projects[global.lastClickedProjectId]; +request.isPrivate = $("#privateDir-tab").hasClass("active"); +request.sponsorPeerID = global.peerID; +request.signature = sm2.doSignature("DistributeContract|" + request.projectName + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onDistributeContract", + "progress":"100.00%" +} +``` + +#### 终止合约 + +##### 参数 + +| 字段 | 值 | +| --------- | ------------------- | +| action | killContractProcess | +| id | 合约id | +| requestID | 请求ID | + +##### 请求示例 + +``` +request.action = "killContractProcess"; +request.id = contractid; +request.requestID = new Date().getTime() + ""; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data": "ContractHandler: exit in 3 seconds!", + "action": "onOutputStream" +} +``` + +#### 终止所有合约 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | killAllContract | + +##### 请求示例 + +``` +request.action = "killAllContract"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onKillAllContract", + "data":"Kill:7241,7245," +} +``` + + + +#### 静态分析合约 + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------- | +| action | staticVerifyContract | +| owner | 用户私钥 | +| isPartial | 是否是部分 | +| contractid | contractid | +| script | 脚本内容 | +| path | 合约文件名 | + + +##### 请求示例 + +```javascript +request.action = "staticVerifyContract"; +request.owner = global.sm2Key.privateKey +request.isPartial = false; +request.contractid = contractid; +request.script = global.projectScript; +request.path = global.projectName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json + +{ + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":{\"hello\":\"Ret:\"},\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStaticVerifyResult", + "cid":"verify", + "executeTime":83 +} +``` + + + +#### 删除合约 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------- | +| action | deleteFile | +| file | fileName | + +##### 请求示例 + +```javascript +request.action = "deleteFile"; +request.file = fileName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onDeleteFile", + "data":"success", + "executeTime":0 +} +``` + + + +#### 私有合约传至公共目录 + +##### 参数 + +| 字段 | 值 | +| -------- | ------------ | +| action | changePublic | +| pubkey | 用户公钥 | +| fileName | fileName | + +##### 请求示例 + +```javascript +request.action = "changePublic"; +request.pubkey = pubkey; +request.fileName = fileName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onChangePublic", + "data":"success", + "executeTime":0 +} +``` + + + +#### 上传合约 + +##### 参数 + +| 字段 | 值 | +| -------- | ----------- | +| action | UploadFile | +| isAppend | false | +|fileName|fileName| +| path | path | +|isPrivate|true/false| +| content | fileContent(base64编码) | + +##### 请求示例 + +``` +request.action = "uploadFile"; +request.isAppend = false; +request.fileName = "test1.yjs"; +request.path = "test1"; +text="Y29udHJhY3QgdGVzdDF7CglleHBvcnQgZnVuY3Rpb24gaGVsbG8oYXJnKXsgCiAgICAgICAgcmV0dXJuICJ3b3JsZCI7ICAKICAgIH0gICAKfQ==" +request.content = text; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onUploadFile", + "data":"success", + "executeTime":0 +} +``` + +#### 编译合约 + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------------- | +| action | compile | +| path | string, 待编译的项目名称 | +| privateTab | bool, 是否为私有目录的项目 | + +##### 请求示例 + +```javascript +var req = {"action":"compile","path":"Hello","privateTab":true} +``` + +##### 返回结果 + +```json +{"result":"Hello_2020-08-17-09:09:40.ypk","action":"onCompile"} +``` + +#### 锁定私有目录 + +锁定某个用户的的私有目录编辑功能 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | lockEdit | +| pubKey | string, 要被锁定的公钥 | + +##### 请求示例 + +```javascript +var req = {}; +req.action = "lockEdit"; +req.pubKey = "xxxxxx"; +wssocket.send(JSON.stringify(req)); +``` +```json +{ + "action":"onLockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" +} +``` + + +#### 解锁私有目录 + +解锁某个用户的的私有目录编辑功能 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | unLockEdit | +| pubKey | string, 要被锁定的公钥 | + +##### 请求示例 + +```javascript +var req = {}; +req.action = unlockEdit; +req.pubKey = "xxxxxx"; +wssocket.send(JSON.stringify(req)); +``` +```json +{ + "action":"onUnlockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" +} +``` + + +### 合约实例管理类 + +#### 查询合约进程 + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "listContractProcess"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onListContractProcess", + "data": "[...]" +} +``` + + + +#### 调用合约 + +向服务器发送请求, 调用某个合约. + +##### 参数 + +| 字段 | 值 | +| -------------------- | --------------------------- | +| action | executeContract | +| contractID | 合约ID | +| withDynamicAnalysis | true/false 是否进行动态分析,可选 | +| operation | 调用合约的方法名 | +| arg | 调用合约的参数 | +| pubkey | 调用者公钥,可选 | +| signature | 调用者签名 ,可选 | + +`*`表示可选参数 + +```javascript +//sm2 可从sm2.js中加载获得。 +signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); +``` + +##### 请求示例 + +```javascript +var request = {}; +request.action = "executeContract"; +request.contractID = "2073401446"; +request.operation = "main"; +request.arg = "hhhhh"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "needSeq":false, + "seq":0, + "status":"Success", + "result":"world", + "isInsnLimit":false, + "totalGas":0, + "executionGas":0, + "extraGas":0, + "size":0, + "eventRelated":false, + "responseID":"1617211077264_223", + "action":"onExecuteResult", + "executeTime":"5" +} +``` + +#### 输出历史记录日志(删除) + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------ | +| action | printTimeTravelLog | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "printTimeTravelLog"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "data": "[CMActions] dumpContract :…t/contractExamples/memoryDumps/LicenceManager\n" +} +``` + + + +#### 输出节点转移日志(删除) + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | printTransferLog | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "printTransferLog"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json + { + "status": false, + "data": "" +} +``` + + + +#### 合约状态迁移 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------ | +| action | loadMemory | +| contractName | 合约名称 | +| memoryFile | 合约文件名称 | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "loadMemory"; +request.contractName = "JsonContract"; +request.memoryFile = "2020-03-17.20/42/55"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "data":"success", + "size":"0.00 B", + "action":"onTransferTo", + "time":"0.01s" +} +``` + + + +### 日志查看类 + +#### 查看本地近n日节点日志(删除) + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | listLocalNodeLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalNodeLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" +} +``` + + + +#### 查看本地近n日合约日志(删除) + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listLocalContractLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalContractLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7ba358d9234939623ab51ea94ca685e6a1f36ed81fd9630ccba6473e632f163bb30faffd4c91f21e5bace20101d6d6e36c04ac67eea14cc24b4962b84f57\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" +} +``` + + + + +### 节点配置类 + +#### 获取节点配置信息 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | loadNodeConfig | + +##### 请求示例 + +``` +var param = {}; +param.action = "loadNodeConfig"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +``` +{ + "status": true, + "action": "onLoadNodeConfig", + "data": { + "nodeName": "04BF52213343C147E631B877BCEB17B794230EE551E85F58FA429C4BA03D690778CC384C6916C63DF36CB9E35C7E274FDB4E18491DFE3D611D347856D441CACC5AF9090B515F02AFC2DFBF56461EC83B5A4CD342466360D6CF82E6E40B637430AC4A329CCBC798DAF7D526AF9E3B3600E0BEA1BFAB8C160EF90128FAF67B19E45F37664F1E4B", + "licence": "04AADCC7103CD02626D228AFFBEF53F8242ECA4DDD6F179D30B622440666715CFBB6FD1D3678A2B25812DEA9917073E79A65F7ADE517F784DC76288EFCEB37ECAA1025E6903540702F729DA1C2ECCD93F4E6FAFCE40DF443E7FD74387169D0C6D927C7BB12882D0471C8D3E6F31B0316A42FC38F6DD9978D4351B23B2AD63E2244909E98F51185D32CB99B4AE4E22D3AB4C04027BB", + "expireTime": "Wed Aug 26 09:43:08 CST 2020", + "nodes": "[\"node1\",\"node2\",\"node3\"]", + "yjsPath": "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar", + "nodeCenter": "ws://127.0.0.1:1719/SCIDE/NodeCenter" + } +} + +{ + "status":true, + "action":"onLoadNodeConfig", + "data":{ + "nodeName":"Node_180", + "peerID":"", + "masterAddress":"39.104.201.40:21031", + "licence":"04AADCC7103C", + "doipConfig":"{\\"LHSProxyAddress\\":\\"http://39.104.201.40:21042/\\",\\"ownerHandle\\":\\"86.5000.470/dou.TEST\\",\\"certPath\\":\\"keys/dou.TEST.keystore\\",\\"certPassword\\":\\"123456\\",\\"repoID\\":\\"86.5000.470/doip.vcg9Mu1gSq_bdw\\",\\"listeners\\":\\"[{\\\\\\"url\\\\\\":\\\\\\"tcp://39.104.201.40:21032\\\\\\",\\\\\\"protocolVersion\\\\\\":\\\\\\"2.1\\\\\\",\\\\\\"messageFormat\\\\\\":\\\\\\"packet\\\\\\"}]\\",\\"serviceDescription\\":\\"test local Contract Repository\\",\\"serviceName\\":\\"ContractEngine021\\"}", + "clusterConnected":"false", + "nodePubKey":"0492d974b8a5b473d0ed2c81800917f76e2a1ec3666067888c85fe6922a672223f2083f95402ae13a744df58deabbe7206c4a317dd14296b0d3941a26ca4e34dc5", + "ipPort":"", + "bdledger":"39.108.56.240:18091,39.108.56.12:1809139.104.70.160:18091 47.98.247.70:18091 47.98.248.208:18091 39.104.77.165:18091 47.98.249.131:18091", + "yjsPath":"/data/bdwaas/bdcontract/yjs.jar", + "nodeCenter":"ws://39.104.201.21040/SCIDE/NodeCenter" + } +} +``` + + +#### 修改节点配置 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | updateConfig | +| key | 要改的配置项 | +| val | 要更改的目标值 | + +其中,key的可选项包括: + +| key的示 | val示例 | 说明 | +| ------------- | ----------------------------------- | ------------------------------- | +| yjsPath | /User/xxx/cp/yjs.jar | 合约进程启动所需的jar | +| dataChain | 192.168.1.8:18090,182.173.2.3:18091 | 账本节点的ip与端口 | +| nodeCenter | ws://127.0.0.1:18002 | CenterPortal所在的ip/端口 | +| nodeName | Node_180 | 字符串类型 | +| masterAddress | 192.168.3.2:18001 | 该NodePortal节点的ip和的TCP端口 | + +其中NodePortal的TCP端口为Node的http/ws端口号+1。 + + +#### 修改节点名称 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | changeNodeName | +| data | 新的节点名称 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeNodeName"; +param.data = "NewNodeName"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeNodeName", + "data": true +} +``` + + + +#### 修改节点YJS路径 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------- | +| action | changeYJSPath | +| data | 节点服务器yjs.jar路径 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeYJSPath"; +param.data = "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeYJSPath", + "data": true +} +``` + + + +#### 修改NodeCenter + +##### 参数 + +| 字段 | 值 | +| ------ | ----------------------------------------- | +| action | changeNodeCenter | +| data | 节点服务器要连接的NodeCenterWebSocket路径 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeNodeCenter"; +param.data = "ws://127.0.0.1:1719/SCIDE/NodeCenter"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeNodeCenter", + "data": true +} +``` + + + +#### 修改账本节点 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------- | +| action | changeBDledger | +| data | 数链节点的IP:port,用","隔开 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeBDledger"; +param.data = "39.108.56.240:18091,39.108.56.12:18091"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeBDledger", + "data": true +} +``` + + + +#### 上传节点Licence + +##### 参数 + +| 字段 | 值 | +| ------ | ----------------------- | +| action | uploadLicence | +| data | 节点服务器的Licence内容 | + +##### 请求示例 + +``` +var param = {}; +param.action = "uploadLicence"; +param.data = "04AADCC7103C"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onUploadLicence", + "data": true +} +``` + + + +#### 获取节点ID + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | getNodeID | + +##### 请求示例 + +``` +var param = {}; +param.action = "getNodeID"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onGetNodeID", + "data": "0431…d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d" +} +``` + + + +#### 获取节点所在的可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------------------------------------------ | +| action | getNodeTrustUnits | +| data | 节点ID | +| msgHandler | 收到回复的回调函数, 可使用"建立连接"的msgHandler | +| ws | 节点所属的NodeCenter的WebSocket地址 | + +##### 请求示例 + +``` +centerportalws = createWssocket("ws://127.0.0.1:1718/NodeCenterWS",function() { +var param = {}; +param.action = "getNodeTrustUnits"; +param.data = "0431e311bd70840fe69965e2cabea97fafe99f2133953c01abb9bd7cb62af42f8283f474d203051e920d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d"; +centerportalws.send(JSON.stringify(param)); +}, msgHandler); +``` + +##### 返回结果 + +```json +{ + "data": [{ + "key": "0475c7b061...65e55_4063665700873624164", + "value": "[\"04541429c11b094…40009b4f06d\"]" + }], + "action": "onGetNodeTrustUnits" +} +``` + +### 模板生成类 + +#### 获取合约模板列表 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | getTemplateList | + +##### 请求示例 + +``` javascript +req={}; +req.action = "getTemplateList"; +wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 + +``` json +{ + "data": [ + { + "formDesc": { + "dbPWD": { + "label": "密码", + "type": "input" + }, + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + }, + "dbUserName": { + "label": "用户名", + "type": "input" + }, + "fieldList": { + "label": "字段名", + "type": "tag" + }, + "dbUrl": { + "label": "数据库链接", + "type": "input" + }, + "tableName": { + "label": "表名", + "type": "input" + } + }, + "apiName": "generateMySQLProject" + }, + { + "formDesc": { + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + } + }, + "apiName": "generateEmptyProject" + } + ], + "action": "onTemplateList" +} +``` + +#### 空白合约模板 + +##### 参数 + +| 字段 | 值 | +| ------------ | ----------------------------- | +| action | generateEmptyProject | +| contractName | 字符串类型,合约名称 | +| isPrivate | 布尔类型,是否为私有项目 | +| accessPolicy | 若为"DAC",则实现直接访问控制 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "Empty22"; +req.action = "generateEmptyProject"; +req.accessPolicy = "DAC"; +//wssocket为建立好的连接 +wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\"]", + "executeTime":0, + "isPrivate":false +} +``` + +#### MySQL接入合约 + +##### 参数 + +| 字段 | 值 | +| ------------- | ------------------------------------------------------ | +| action | generateMySQLProject | +| contractName | 字符串类型,合约名称 | +| isPrivate | 布尔类型,是否为私有项目 | +| dbUrl | 字符串类型,数据库的URI | +| dbUserName | 字符串类型,数据库的用户名 | +| dbPWD | 字符串类型,数据库密码 | +| accessPolicy | 若为"DAC",则实现直接访问控制,若为"NAC"则没有访问控制 | +| tableName | 字符串类型,数据库的表名 | +| fieldList | 字符串列表,数据库的字段列表 | +| defaultAccept | 布尔值,表示申请时是否默认有权 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "MySQLFromTemplate"; +req.action = "generateMySQLProject"; +req.pubKey = global.sm2Key.publicKey; +req.isPrivate = true; +req.tableName = "data"; +req.dbUrl = "jdbc:mysql://xxx:xxx/xxx"; +req.dbUserName = "loushuai"; +req.dbPWD = "loushuai"; +req.fieldList = [{"name":"名字","code":"*"}]; +req.basicInfo={"type":"所属分类","name":"资源名称"}; +req.accessPolicy = "DAC"; +req.defaultAccept = true; +//global.wssocket为建立好的连接 +global.wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` +#### CSV接入合约 + +##### 参数 + +| 字段 | 值 | +| ----------------- | ------------------------------------------------------ | +| action | generateCSVProject | +| contractName | 字符串类型,合约名称 | +| base64EncodedData | 字符串类型,通过base64编码后的CSV文件内容 | +| isPrivate | 可选字段,布尔类型,是否为私有项目 | +| accessPolicy | 若为"DAC",则实现直接访问控制,若为"NAC"则没有访问控制 | +| defaultAccept | 可选字段,布尔值,表示申请时是否默认有权 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "CSVFromTemplate"; +req.action = "generateCSVProject"; +req.pubKey = global.sm2Key.publicKey; +req.isPrivate = true; +req.tableName = "data"; +req.accessPolicy = "DAC"; +req.defaultAccept = true; +req.base64EncodedData = "bmFtZSwgc2NvcmUsCmphY2ssIDkwLApsdWN5LCA5MQo="; +//global.wssocket为建立好的连接 +global.wssocket.send(JSON.stringify(req)); +``` +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` + +- - - + +## 路由节点WebSocket接口 + +### 用户管理类 + +#### 获取Session + +登录前获取session以便进行签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | getSessionID | + +##### 请求示例 + +``` +var req = {}; +req.action = "getSessionID"; +wssocket.send(JSON.stringify(req)); +``` + + +##### 返回结果 + +```json +{ + "action": "onSessionID", + "session": "9782323_session" +} +``` + + +#### 用户登录 + +用户进行公私钥身份验证,需先调用"getSessionID"获取sessionID以便于签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ----- | +| action | login | + +##### 请求示例 + +``` +var loginParam = {}; +loginParam.pubKey = global.sm2Key.publicKey; +loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); +loginParam.action = "login"; +wssocket.send(JSON.stringify(loginParam)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onLogin", + "data": "CenterManager" +} +``` + + + +#### 用户获取当前角色(删除) + +用户根据登录时的公钥获取对应的角色,如果是第一次登录则此时的公钥默认称为准入管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | ------- | +| action | getRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "getRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onGetRole", + "data": "CenterManager" +} +``` + +#### 申请角色 + +在准入管理员界面可以申请称为组网中某个节点的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | applyRole | +|role|申请的角色名称| + +##### 请求示例 + +``` +var param = {}; +param.action = "applyRole"; +param.role=" +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onApplyRole", + "data": "failed" +} +``` + + +#### 添加节点 + +##### 参数 + +| 字段 | 值 | +| ---------- | ---------------- | +| action | addNode | +| nodePubKey | 要添加的节点公钥 | + +#### 请求示例 + +``` +var req = {}; +//某节点的publicKey可通过连接该节点,并通过"获取节点配置信息"接口获取 +req.nodePubKey = publicKey; +req.action = "addNode"; +wssocket.send(JSON.stringify(req)); +``` + + +#### 删除用户角色 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | delete | +| pubKey | 对应用户的公钥 | + +##### 请求示例 + +``` +var deleteInfo = {}; +deleteInfo.pubKey = user.publicKey; +deleteInfo.action = "delete"; +wssocket.send(JSON.stringify(deleteInfo)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onDelete", + "data": "success" +} +``` + +#### 查看授权用户列表 + +查看准入管理员当前组网中已经授权的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | listAllUsers | + +##### 请求示例 + +``` +var param = {}; +param.action = "onListAllUsers"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onListAllUsers", + "kv": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": " NodeManager" + }, + "time": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": 1587398989914 + } +} +``` + +#### 查看申请用户列表 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | listApplyList | + +##### 请求示例 + +``` +var param = {}; +param.action = "onListApplyList"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onListApplyList", + "kv": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": " NodeManager" + }, + "time": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": 1587398989914 + } +} +``` + +#### 查看用户类型分布 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | queryUserStat | + +##### 请求示例 + +``` +var param = {}; +param.action = "onQueryUserStat"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 +} +``` + +### 节点管理类 + +#### 查看节点列表 + +查看该用户有权限查看的节点列表(仅准入管理员及合约管理者可用) + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | listNodes | + +##### 请求示例 + +``` +var param = {}; +param.action = "listNodes"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "offline": [{ + "key": "0431e31...40009b4f06d", + "value": "0431e311bd708...b4f06d" + }], + "action": "onListNodes", + "online": [{ + "contracts": [], + "pubKey": "0431e311...09b4f06d", + "nodeName": "NewNodeName", + "udpID": "528822126", + "cimanager": "" + }] +} +``` + + +#### 查看可信执行集群列表 + +查看该用户有权限查看的节点列表(仅中心管理员及合约管理者可用) + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | listTrustUnits | + +##### 请求示例 + +``` +var param = {}; +param.action = "listTrustUnits"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "data": [{ + "key": "0470b2f27f4f6…1cb855f1ecec11", + "value": "[...]" + }], + "action": "onListTrustUnits" +} +``` + + +#### 建立可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | createTrustUnit | +| data | 节点公钥组成的Json数组 | +| Msg | 集群名称 | + +##### 请求示例 + +``` +var param = {}; +param.action = "createTrustUnit"; +param.data = "[\"382r0934309t...\",\"345343rr3f34...\"]"; +param.msg = "newUnit1"; +global.wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onCreateTrustUnit", + "status": "Success" +} +``` + + +#### 删除可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | deleteTrustUnit | +| data | 可信执行集群ID | + +##### 请求示例 + +``` +var param = {}; +param.action = "deleteTrustUnit"; +param.data = "0475d34rf3434..._1583410158761"; +global.wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onDeleteTrustUnit", + "status": "Success" +} +``` + + + +### 日志查看类 + +#### 查看组网管理操作的统计 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | queryActionLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "onQueryActionLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ "action":"onQueryActionLog", + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" +} +``` + + + +#### 查看本地近n日合约日志 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listLocalContractLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalContractLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7b...\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" +} +``` + + +- - - + +## Bash接口 + +已废弃。可使用BDWareConfigTool代替。 +通过命令行发送Socket指令, 执行调用`ContractController`类中方法, 完成以下功能. (需要在本机的`1615`端口运行`ContractManager`实例) + +![Bash接口功能示意图](./_static/imgs/bash-api.png) + +### 指令 + +```bash +java -jar yjs.jar function_name arguments + +``` + +`function_name`为调用的方法名; + +`arguments`为方法参数. + +### 启动合约 + +#### 参数 + +`function_name`为`startContract`; + +`arguments`为启动合约需要的参数, 包括合约类型`type`, 合约ID`id`, 合约脚本`script`. + +#### 指令示例 + +```bash +java -jar yjs.jar startContract "{\"type\":\"Algorigthm\",\"id\":\"656565\",\"script\":\"contract c{function main(arg){return arg/1.0+1;}}\"}" +``` + +### 调用合约 + +#### 参数 + +`function_name`为`executeContract`; + +`arguments`为调用合约需要的参数, 包括调用参数`arg`, 合约ID`contractID`. + +#### 指令示例 + +```bash +java -jar yjs.jar executeContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" +``` + +### 停止合约 + +#### 参数 + +`function_name`为`stopContract`; + +`arguments`为调用合约需要的参数, 即合约ID`contractID`. + +#### 指令示例 + +```bash +java -jar yjs.jar stopContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" +``` + +### 停止全部合约 + +#### 参数 + +`function_name`为`stopAllContracts`. + +#### 指令示例 + +```bash +java -jar yjs.jar stopAllContracts +``` + +### 查询全部合约 + +#### 参数 + +`function_name`为`listContracts`. + +#### 指令示例 + +```bash +java -jar yjs.jar listContracts +``` + \ No newline at end of file diff --git a/source/markdown/IDEUsage.md b/source/markdown/IDEUsage.md new file mode 100644 index 0000000..08568fe --- /dev/null +++ b/source/markdown/IDEUsage.md @@ -0,0 +1,439 @@ +# BDContract管理界面 + +- - - + +## 合约节点管理界面 + +该界面的使用地址为:[NodePortal.html](/NodePortal.html) + + +### 用户管理菜单 +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +#### 概览 +![nodeUserManager](./_static/imgs/nodeUserManager.jpg) +节点用户管理页面一共有四个模块:用户情况、用户活跃统计、授权用户管理、未授权用户管理。 + +#### 用户类型分布 +主要统计当前节点管理员所拥有的四种角色的数量:合约提供者、合约管理员、合约使用者 +![userList](./_static/imgs/userList.jpg) + +#### 用户活跃统计 +![userActive](./_static/imgs/userActive.jpg) +统计30天之内**登录**、**授权**、**申请**的次数 + +#### 当前用户信息 +![nodeInfo](./_static/imgs/nodeInfo.jpg) + * 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录节点管理员界面,可以将自己的公私钥复制到这个文本框中。 + * 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到节点管理员本地 + * 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是还没有在中心管理员认证的节点则默认为**Anonymous** + * 如果不是节点管理员,想要加入某个中心管理员的网络,那么要在中心管理员所在的用户管理中用自己的公私钥导入后进行认证。 + * 如果想要行使更多关于合约的操作,则需要认证不同的角色:合约管理员、合约使用者、合约提供者,然后进行**角色认证** + +#### 授权与非授权用户列表 +![roleAuth](./_static/imgs/roleAuth.jpg) + 在节点管理员认证角色之后,节点管理员登录会在**未授权角色管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以。 + 授权之后将在**授权角色管理**表格中看见授权后的节点列表。如果节点管理员想要移除某个节点的角色,则在授权角色管理列表中**删除**即可。 + +### 合约代码管理菜单 + +![codeManageMenu](./_static/imgs/codeManageMenu.png) + + + +#### 合约文件 + +![codeManage1](./_static/imgs/codeManage1.png) + +在合约代码管理菜单中,用户可以看到公共合约以及个人私有合约。 +![codeManage1-1](./_static/imgs/codeManage1-1.png) + +对于公共合约,节点管理员可以对其中文件进行删除和上传操作,可以对合约项目进行下载和删除操作。 +![codeManage1-2](./_static/imgs/codeManage1-2.png) + +对于私有合约,合约提供者可以对其中文件进行删除和上传操作,可以对合约项目进行下载、删除和传至公共合约目录操作。 + +以下是对合约文件进行操作的示例。 + +#### 上传文件 +![codeManage6](./_static/imgs/codeManage6.png) + +#### 删除 +![codeManage5](./_static/imgs/codeManage5.png) + +#### 传至公共 +![codeManage7](./_static/imgs/codeManage7.png) + +#### 下拉框 + +![codeManage2](./_static/imgs/codeManage2.png) + +四个下拉框中,可以分别对合约状态保存模式、已启动合约实例、节点所在集群以及结果校验方式进行选择。 + + + +#### 按钮操作 + +![codeManage3](./_static/imgs/codeManage3.png) + +#### 启动 + +在文件列表中选择合约文件之后,在合约运行模式中选择“单节点执行”,点击启动按钮,会启动指定文件,并在结果显示框中显示返回结果。 + + + +#### 启动P2P集群合约 + +在文件列表中选择合约文件之后,在合约运行模式中选择该可信合约运行的合约集群,点击启动按钮,会在该集群的所有节点上启动指定文件,并在结果显示框中显示返回结果。 + + + +#### 启动全部 + +在合约运行模式中选择“单节点执行”,点击启动全部按钮,会启动合约文件列表中所有合约。 + + + +#### 停止P2P集群合约 + +在已启动合约实例的下拉框中选择一个合约实例,在合约运行模式中选择该可信合约运行的合约集群,点击停止按钮,会在该集群的所有节点上终止这个合约进程。 + + + +#### 停止 + +在已启动合约实例的下拉框中选择一个合约实例,点击停止按钮,会终止这个合约进程。 + + + +#### 停止全部 + +点击停止全部按钮,会停止该节点上运行的所有合约实例。 + + + +#### 静态分析 + +在合约文件列表中选择合约文件,并在合约实例下拉框中选择合约实例,点击静态分析按钮,会对该合约进行静态分析,并在结果显示框中显示返回结果。 + + + +#### 分发合约 + +在合约文件列表中选择合约项目,并在合约运行模式中选择一个集群,点击分发合约按钮,会将该合约项目打包为ypk分发给这个集群中的所有节点。 + + + + +#### 返回结果 + +![codeManage4](./_static/imgs/codeManage4.png) + +返回结果显示中显示一些操作的返回结果。 + + + +#### 合约权限配置 + +在启动合约之后,如果当前用户的角色可以查看已经启动合约进程,那么在选定查看合约进程时将会在右下方展示当前合约的IO权限。 +![permissionShow](./_static/imgs/permissionShow.png) + +如果选中的合约没有IO权限,则在当前权限的展示框中提示**当前合约没有IO权限** +![nullPermission](./_static/imgs/nullPermission.png) + +当前用户是合约管理员时可以对已有的合约IO权限进行修改。系统会提示修改后合约将有可能不会正常运行,如果还是确定要取消,那么点击**确定** 即可,反之点击**关闭** +![updatePermission](./_static/imgs/updatePermission.png) + +点击关闭或者打开之后,下一次查看同一个合约代码的进程将会默认显示最近一次修改之后的IO权限。 +![closePermission](./_static/imgs/closePermission.png) + +### 合约实例管理菜单 + +![nodeInstancesPage](./_static/imgs/nodeInstancesPage.png) + +合约实例管理菜单显示了该节点当前的所有合约实例, 用户可查看合约实例的状态, 并对合约实例进行执行或状态迁移的操作. + +#### 合约实例列表 + +![nodeInstancesList](./_static/imgs/nodeInstancesList.png) + +该列表显示了当前节点的所有合约实例信息, 包括合约ID, 合约名称, 合约类型合约状态, 合约进程端口, 合约调用次数, 合约流量, 及合约占用内存, 集群合约的结果校验模式. + +#### 合约实例执行 + +![chooseInstance](./_static/imgs/chooseInstance.png) + +用户可在合约实例的选择下拉框中选择合约实例, 对该合约实例进行操作. + +![intanceExecute](./_static/imgs/intanceExecute.png) + +选择合约实例后, 用户可在"方法"的下拉框中选择该合约的方法名, 在"参数"输入框中输入方法的参数, 点击"执行". + +用户还可点击"动态分析执行"进行带有动态分析结果的执行. + +若该合约为单点合约, 则合约在单点执行; 若该合约为集群合约, 则该合约在该集群的所有节点上执行. + +#### 合约实例执行结果 + +![executeResult](./_static/imgs/executeResult.png) + +合约实例的执行完成后的结果显示在"执行结果"区域中, 包括该次执行的ID, 执行成功/失败, 执行时间, 及执行结果. + +![analysisExecuteResult](./_static/imgs/analysisExecuteResult.png) + +若该合约的执行方式为"动态分析执行", 则结果框内除执行结果, 还会显示该次执行的动态分析结果. + +#### 合约状态迁移 + +![memoryDump](./_static/imgs/memoryDump.png) + +对于支持用户手动迁移的合约实例, 用户可点击"本地状态保存"对合约实例的状态进行保存, 或从合约的TimeTravel列表中选择已保存的合约实例, 将合约状态迁移到对应时刻. + + + +### 日志管理菜单 +![logMenu](./_static/imgs/logMenu.png) + +该菜单是对该节点本地节点日志以及合约日志的统计结果展示。 + +其中,节点管理员可以查看节点日志的相关数据;合约管理者及合约使用者可以查看该节点本地合约日志的相关数据。 + + + +#### 日志统计图 + +![log1](./_static/imgs/log1.png) + +#### 各类平台操作百分比 + +该图默认显示近2日各类平台操作占比的饼图,其中平台操作分为登陆类、用户类、日志类、合约类、维护类以及其他类这六类。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比会同步更新。 + + + +#### 各类合约操作百分比 + +合约操作分为启动、终止、静态分析和执行这四类,该图为近2日对各类合约操作占比的饼图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比会同步更新。 + + + + +#### 每日平台使用统计 + +该图为近2日平台操作次数统计的折线图。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日平台使用统计折线图会同步更新。 + + + + +#### 每日合约使用统计 + +该图为近2日对该节点上合约的操作次数统计的折线图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日合约使用统计折线图会同步更新。 + + + + +#### 日志详情 + + + +#### 节点日志详情 +![log2](./_static/imgs/log2.png) + +节点日志详情表是对节点日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比和每日平台使用统计会同步更新。 + + + +#### 合约日志详情 +![log3](./_static/imgs/log3.png) + +合约日志详情表是对合约日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比和每日合约使用统计会同步更新。 + + + +### 节点管理菜单 + +![nodeConfig](./_static/imgs/nodeConfig.png) + +节点管理菜单显示了该节点的配置信息及所属可信执行集群信息. + +#### 节点配置 + +![nodeConfigChange](./_static/imgs/nodeConfigChange.png) + +节点管理员可查看该节点的配置信息, 包括节点名称, 节点YJS路径, 节点的网络中心节点, 节点管理员还可对以上配置进行修改. + +若节点管理员修改了节点的网络中心, 该节点后重新想改节点连接, 整个页面刷新重载. + +#### 节点可信执行集群列表 + +![nodeUnits](./_static/imgs/nodeUnits.png) + +节点管理员可查看节点所属的可信执行集群信息, 包括集群创建者, 集群ID, 集群中节点数目, 集群中节点的信息. + +- - - + +#### 节点Licence配置 + +![nodeLicence](./_static/imgs/nodeLicence.png) + +用户可以查看该节点的Licence及过期时间, 还可申请Licence, 上传Licence, 保存节点UUID. + +## 智能合约在线编辑器 + +### 用户与账号 + +#### 创建账号 + +#### 申请授权 + + +### 创建项目 + +#### 新建文件 + +#### 上传文件 + +### 启动合约 +![contractMode](./_static/imgs/contractMode.png) + +####正常模式 +点击左侧启动按钮,以正常模式启动合约。 + +####debug模式 +点击右侧debug按钮,以debug模式启动合约。目前约定debug模式合约通过executeContract调用正常模式合约时,返回正常模式合约文档中的返回结果示例。 + +### 调用合约 + +###生成文档 +![genReadme](./_static/imgs/genReadme.png) + +启动合约后点击"生成文档"按钮,可以通过各export函数的@Description / @Param / @Result 对合约进行调用及结果返回,从而生成合约的说明文档。 + +- - - + +## 路由准入管理界面 + +### 权限申请与授权 + +### 仪表盘 +仪表盘为提供对准入节点中用户数量,合约数量,节点数量的概览。 + +### 整体视图 +![dashboard](./_static/imgs/dashboard.jpg) +一共分为四个模块,一个模块是用户、合约、节点数量的概览,然后分别是这三个数量的详细分类的数据统计情况。 + +### 节点数目 +![node](./_static/imgs/node.jpg) +当前在线和离线节点统计 + +### 用户类型分布 +![userAll](./_static/imgs/userAll.jpg) +当前准入节点所在组网中的节点管理员、准入管理员的数量和申请中节点的数量 + +### 合约调用情况 +![contract](./_static/imgs/contract.jpg) +当前准入节点所在组网中所有合约中事件、多点执行、ws调用、Http调用的折线统计图。 + +### 用户管理 +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +### 概览 +![centerManager](./_static/imgs/centerManager.jpg) +用户管理页面一共有四个模块。 + + +### 用户类型分布 +主要统计当前中心管理员所管理的网络中有多少节点管理员,多少个中心管理以及申请节点管理员的数量 +![userList](./_static/imgs/userList.jpg) + +### 30天内的申请情况统计 +![userApplyGraph](./_static/imgs/userApplyGraph.jpg) +统计30天之内申请节点管理员的数量和授权成为节点管理员的数量 + +### 当前用户信息 +![authNodeManager](./_static/imgs/authNodeManager.jpg) + * 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录中心管理员界面,可以将自己的公私钥复制到这个文本框中。 + * 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到中心管理员本地 + * 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是中心管理员则拥有中心管理员的一切权限。 + * 如果不是中心管理员或者节点管理员,想要加入当前中心管理员的网络,那么可以在下面的选择框中选中节点管理员,进行**角色认证**。 + +### 授权与非授权用户列表 + 在中心管理员当前用户信息申请之后,中心管理员登录会在**未授权用户管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以,此时这个申请就无效。 +![authMan](./_static/imgs/authMan.jpg) + 授权之后将在**授权用户管理**表格中看见授权后的节点列表。如果中心管理员想要移除某个节点管理员的某项角色,则在授权用户管理列表中选择相应的角色,然后点击**删除**即可删除选中的角色。 +![authMana](./_static/imgs/authMana.jpg) + +### 节点管理 + +![centerNodePage](./_static/imgs/centerNodePage.png) + +节点管理为Manager对连接到自己的Cluster节点进行管理的页面, 仅Manager管理员及合约管理者可见. Manager管理员及合约管理者可在本页面查看节点信息, 并管理可信执行集群. + +### 概览 + +![centerNodePreview](./_static/imgs/centerNodePreview.png) + +概览中显示了该Manager节点所管理的所有节点的统计信息, 包括总节点数量, 总合约数量, 总订阅事件数量, 及可信执行集群数量, 右侧的饼图则为节点的分别处于Online/Offline的数量统计. + +### 节点列表 + +![centerNodeList](./_static/imgs/centerNodeList.png) + +节点列表显示了用户有权限查看的节点信息(Manager管理员可查看全部节点, 合约管理者可查看自己负责管理的Online节点). 包括节点的名称, 状态, 合约数目, 订阅事件数目, 用于节点间P2P通信的PeerID, 用于节点间UDP通信的UDPID, 及节点公钥. + +### 可信执行集群列表 + +![centerNodeUnits](./_static/imgs/centerNodeUnits.png) + +可信执行集群列表显示了用户有权限查看的可信执行集群信息(Manager管理员可查看全部集群, 合约管理者可查看自己创建的集群). 包括集群的创建者, 集群ID, 集群中节点数目, 以及集群中节点的信息. + +用户可点击列表表项的"删除"按钮, 将该集群删除. + +### 创建可信执行集群 + +![centerNodeUnitCreate](./_static/imgs/centerNodeUnitCreate.png) + +用户可以通过多选节点, 创建新的可信执行集群. 用户可以选择的节点为自己有权限查看的节点, 即Manager管理员从全部节点中选择, 合约管理者可从自己负责管理的Online节点中选择). 选择后点击提交, 即可看到创建成功的提示信息, 该集群将随即显示在可信执行集群列表中. 集群名称由创建者选取, 不能含有双引号, 该名称为合约管理者选择集群时的可见标识. + +### 日志管理 +日志管理主要展示准入节点的各项日志信息,一共分为六个模块。 +### 概览 +![log](./_static/imgs/log.jpg) + +### 管理操作分类统计(2日) +![operator](./_static/imgs/operator.jpg) +两日内所有管理类操作的统计饼图,管理类操作主要分为登录类、日志类、维护类、用户类。 + +### 管理操作每日统计(2日) +![everyLog](./_static/imgs/everyLog.jpg) +两日内管理类所有的操作每日操作统计 + +### 合约操作分类统计(2日) +![contractLog](./_static/imgs/contractLog.jpg) +两日内合约操作分类统计饼图,合约操作主要分为连接类和状态更新类。 + +### 合约操作每日统计(2日) +![contracteveryLog](./_static/imgs/contracteveryLog.jpg) +两日内合约操作数量折线统计图。 + +### 管理操作日志列表 +![opList](./_static/imgs/opList.jpg) +管理操作日志的详细信息列表。包括日志时间,管理操作名称,操作对应的节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +### 合约操作日志列表 +![contractList](./_static/imgs/contractList.jpg) +合约操作日志详细信息列表。包括日志产生时间,合约操作名称,合约操作节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +### 设置 + +设置页面是节点证书的状态展示以及配置节点证书 + +### 概览 +![set](./_static/imgs/set.jpg) + +### 证书状态 +![licence](./_static/imgs/licence.jpg) +证书状态主要包括许可到期时间和许可节点数量。 + +### 配置证书 +![plicence](./_static/imgs/plicence.jpg) +配置证书模块可以下载节点ID文件或者输入证书信息进行提交。 diff --git a/source/markdown/InstallTips.md b/source/markdown/InstallTips.md new file mode 100644 index 0000000..a5d6857 --- /dev/null +++ b/source/markdown/InstallTips.md @@ -0,0 +1,190 @@ +# BDContract安装说明 + + +- - - + +## 依赖环境的安装 +1.安装Java1.8环境。 + +例如,在Ubuntu下使用apt-get进行安装: + +```bash +apt-get install openjdk-8-jre +``` +在Centos环境下,使用yum进行安装: + +```bash +yum install java-1.8.0-openjdk +``` + +如果是离线环境,可先下载openjdk的安装包后进行离线安装。 + +Ubuntu下 +```bash +dpkg -i jdk-8uxxxxx.deb +``` + +在Centos环境下,使用yum进行离线安装: +```bash +yum localinstall jdk-8u271-linux-xxx.rpm +``` + +2.安装wget与unzip。 +例如,在Ubuntu下使用apt-get进行安装: + +```bash +apt-get install unzip +apt-get install wget +``` + +- - - + +## 网络拓扑说明 + +部署数瑞智能合约引擎最小仅需一个节点,此时可用作调试、测试,不能通过多节点模式来实现可信的计算。 +单节点部署时,可通过配置账本实现"防抵赖"的计算,但不能实现"难篡改"的计算。 + +多节点部署时可参考下图,包含三种逻辑节点,同一虚拟机可安装一至三种节点。 + +1)账本节点。即数瑞图式账本。 + +2)合约节点。运行代码逻辑,并通过内存缓存实现高响应的模块。与其他合约节点组成可信计算网络。 + +3)路由节点。各个合约节点的路由信息。一般单个路由节点可支持最高1000合约节点。可视情况部署多个路由节点,并在路由节点之间配置实现更大规模的节点组网。 + +一般地,同一虚拟机下,会部署**合约节点与账本节点**。 + +![deploytopology](_static/imgs/deploytopology.png) + +- - - + +## 智能合约节点安装 + +打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest) +其中,下载`bdserver-lite.zip`或`bdserver.zip`,其中,`bdserver.zip`包含更多示例和文档。 +下载之后解压并启动。 + +```bash +unzip -d ./bdserver bdserver-lite.zip +cd bdserver +chmod +x *.sh +sh cmstart.sh +``` + +- - - + +## 路由准入节点安装 + +打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest) +其中,下载`bdserver-cluster.zip`。 +下载之后解压并启动。 + +```bash +unzip -d ./bdcluster bdserver-cluster.zip +cd bdcluster +chmod +x *.sh +sh ncstart.sh +``` + +- - - + +## 文件说明 + +### 智能合约节点 + +![bdserver目录](_static/imgs/dirstructure.png) + +该目录下的文件说明: + +1.cmstart.sh 该脚本用于启动合约引擎。合约引擎默认监听8080端口,可通过修改cmstart.sh来修改合约引擎的监听端口。 + +2.BDWareProjectDir 该目录存放了本节点的所有合约项目。 + +3.WebContent 该目录存放了本节点的前端代码。 + +4.cp, 该目录存放了yjs.jar,为启动合约实例所需的jar。 + +5.bdserver.jar 对外提供http/websocket的服务器逻辑。 + +6.updateContract.sh 用于升级的脚本。 + +### 路由准入节点 + +安装脚本会自动下载安装并解压为bdcluster目录。 +该目录下的文件说明: + +1.ncstart.sh 该脚本用于启动节点准入中心。默认监听1718端口。可通过修改ncstart.sh来修改监听的端口。 + +2.WebContent 该目录存放了准入中心的前端代码。 + +3.bdcluster.jar 准入中心的后端。 + +- - - + +## 升级流程 + +### 合约节点 + +在命令行中输入: + +```bash +sh updateContract.sh +``` + +亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract),下载最新文件,单独升级yjs.zip/bdserver-jar.zip/AgentWebContent来升级。 + +### 路由准入节点 + +```bash +sh updateCluster.sh +``` +亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract),下载最新文件,单独升级bdserver-cluster.zip/ClusterWebContent.zip来升级。 + +- - - + +## 使用说明 + +### 通过参考界面使用 +当保留了WebContent目录的情况下,可使用浏览器进行配置。 +更多请使用见左侧文档[BDContract参考界面使用说明](./IDEUsage.html)。 + +#### BDWare OnlineIDE +打开[BDWare OnlineIDE](../OnlineIDE.html)。 + +#### BDWare NodePortal +打开[BDWare NodePortal](../NodePortal.html)。 + +如需组网,使用跨节点功能,则需安装路由准入中心。并按以下步骤进行配置。涉及两组公私钥。 +第一组公私钥为合约节点的、有NodeManager权限的公私钥。 +第二组公私钥为路由准入节点的、有CenterManager权限的公私钥。 + +1.打开NodePortal.html,复制该节点的NodeManager公私钥。 + +2.打开CenterPortal.html,点击右上角,将上述的NodeManager公私钥导入;并选择"NodeManager"进行身份认证。 + +3.在CenterPortal.html中切换CenterManager的公私钥,点左侧的"用户管理",通过NodeManager的认证请求。 + +4.使用NodeManager权限的公私钥打开NodePortal.html,点击:“节点管理”菜单,并配置加入网络。 +其中,加入网络的格式为:ws://centerportal的ip:端口+1。 +![配置示例](_static/imgs/config.png) + + +### 通过SDK使用 + +#### 基础知识 + +[Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) + +[Sm2加密的使用](https://github.com/JuneAndGreen/sm-crypto) + +#### SDK下载 + +1. Java版本的客户端下载:[BDWareJavaClient](_static/BDWareJavaClient.zip)。具体使用说明请下载后解压,查看README.md,并参考[ContractAPI](./ContractAPI.html)。 + +2.Javascript版本的客户端下载:[BDWareWebClient](_static/BDWareWebClient.zip)。具体使用说明请下载后解压,查看README.md,并参考[ContractAPI](./ContractAPI.html)。 + +3.配置工具[BDWareConfigTool](_static/BDWareConfigTool.zip)。具体说明请下载后解压,使用以下命令查看帮助: + +``` bash +java -jar java-client.jar -h +``` \ No newline at end of file diff --git a/source/markdown/Introduction.md b/source/markdown/Introduction.md new file mode 100644 index 0000000..07c6a65 --- /dev/null +++ b/source/markdown/Introduction.md @@ -0,0 +1,219 @@ +# BDContract介绍 + +- - - + +## 什么是BDContract? + + 北大数瑞是面向大数据场景的数据资源、IoT资源、云资源的管理、调度平台。BDContract是一个可信计算框架,计算逻辑以智能合约的方式表达。通过”随机“和”冗余计算“的方式实现智能合约的可信执行。BDContract在保证智能合约的可用性、可靠性的同时,着重提升执行效率和安全性。 + + +- - - + +## 特点 + +0. 支持多种执行模式,权衡可用性、可靠性、正确性和效率。 +1. 接入各种数据源。 +2. 支持合约的细粒度监测。 +3. 支持合约的状态。 +4. 访问控制。 +5. 支撑跨语言调用。 + + +- - - + +## 更新日志 + +* **v1.4.5** 2021年6月29日 + - 稳定性提升 + - HTTP服务端的URIPath优化 + - 支持以Http方式进行静态资源文件加载 + +* **v1.4.4** 2021年6月15日 + - 修复了getContractMeta时没优先返回RUNNING/HANGED的合约的问题 + - 实现了HomomorphicEncrypt的逻辑 + +* **v1.4.3** 2021年6月9日 + - 修复SSL Renegotiate Bug + - 实现内存不足时自动Hangup-Resume + - 实现contract meta的硬盘持久化 + +* **v1.4.1** 2021年5月26日 + - 实现了事件机制中的事件语义,支持“至少一次”、“至多一次”和“只有一次” + - 优化了合约模板 + - 增加模板配置文件 + - 优化了MockTemplate注解 + +* **v1.4.0** 2021年5月9日 + - 优化了ACTemplate + - 完善了DoRepo的配置联动 + +* **v1.3.9** 2021年4月22日 + - 修复了doipConfig在updateConfig中不支持的bug + - test-tool支持了sudo + - 优化了contract-template中的ACTemplate模板 + +* **v1.3.6** 2021年4月21日 + - 修复了docker中无法获取cpuid的问题 + +* **v1.3.6** 2021年4月16日 + - 修复了部分bug + - 修复了GRPCPool线程数量不足导致排队的bug + - 修复了requestID分配在压力测试下可能重复的bug + +* **v1.3.5** 2021年3月31日 + - 修复了部分bug + - http的合约调用部分增加了简单拥塞控制策略 + - 稳定性提升 + +* **v1.3.0** 2021年2月1日 + - 优化心跳机制 + - 修复部分Bug + - 更新SM2/SM3库 + - 更新前端签名计算方式 + +* **v1.2.0** 2020年12月11日 + - 优化了多节点执行模式 + - 优化了合约master路由的逻辑 + - 修复了部分bug + - 修复文件系统相关的漏洞 + +* **v1.1.0** 2020年9月 + - 支持https,并更新了该部分文档 + + +* **v1.0.9** 2020年8月27日 + - 完善IO相关工具类的文档 + - 优化合约模板:DAC持久化 + + +* **v1.0.7** 2020年8月13日 + - 优化合约日志、账本接口 + - 优化相关接口的文档 + - 提供合约模板的websocket接口 + - 自动编译bug修复 + +* **v1.0.5** 2020年7月25日 + - 弱化NC的中心化作用,集群点对点连接。 + - 优化bdwareclient + - TODO MemoryDurable + +* **v1.0.2** 2020年7月22日 + - 修复CentOS7下Too Many Opened Files的Bug + - 修复权限Bug + - 增加权限说明 + - 修复MySQLUtil的bug + - 升级BDLedger版本 + +* **v1.0.1** 2020年7月5日 + - 更新了NodePortal/CenterPortal的UI。 + - 修改了编译流程,在NodePortal中可查看编译结果,在OnlineIDE中可手动/启动时编译 + - 修改了合约分发逻辑,以编译后ypk作为分发的文件 + - 支持public目录下的ypk在多节点模式下执行时,合约故障自动恢复 + +* **v0.99** 2020年6月22日 + - 自定义合约方法的计费 + - 新增了GasExample、Incentives示例 + - 在客户端实现了"校验多点结果",并优化了结果返回的方式 + - 修复断线重连后无权限提示 + +* **v0.97** 2020年5月25日 + - cpu等资源的计量:gas机制 + - onlineIDE.html 支持上传多个文件 + - udp方式组网进行多点执行[无定序消息] + - bdwareclient.html,修复只包含计算逻辑的调用示例生成前缀错误 + +* **v0.95** 2020年5月19日 + - 修复了onlineIDE.html在的pathname有前缀时不能正确跳转bdwareclient的bug。 + - 修复了bdwareclient的pathname有前缀时自动提取url的bug。 + - 启用了合约的权限 + - 增加了NodePortal.html/OnlineIDE.html和bdwareclient.html中无权限时的提醒 + +* **v0.90** 2020年5月9日 + - 更改了yjs.jar/bdserver.jar的打包方式 + - 更新了install.sh/update.sh + - onlineIDE的修改后提醒 + - onlineIDE标签页自适应宽度 + - 文件接口隔离 + + +* **v0.8** 2020年4月26日 + - 完善文档界面和优化SDK提供方式 + - 数瑞Web客户端,客户端中所有的数据处理和如何对处理后的数据进行渲染均来自合约调用,实现可信Web应用。 + +* **v0.78** 2020年4月13日 + - 合约调用DAC示例 + - 支持动态修改IO权限 + - 支持合约状态自定义备份(定时)策略 + - 修复部分页面bug + - 日志展示优化 + - 优化账本日志展示 + - 启用部分权限访问控制 + + +* **v0.7** 2020年3月25日 + - 支持多种角色的访问控制 + - 更新了UI + +* **v0.6** 2020年2月14日 + - 优化了合约进程间的通讯 + - 尝试接入P2P网络 + +* **v0.5** 2019年12月10日 + - 完善了3种智能合约状态记录-回放策略 + - 支持了最简单的多点执行算法(不同步) + +* **v0.45** 2019年9月2日 + - 初步实现PBFT算法 + +* **v0.4** 2019年5月10日 + - 支持memory dump + +* **v0.35** 2019年4月26日 + - 实现合约的静态分析框架 + - 支持事件的发布-订阅 + +* **v0.3** 2019年1月8日 + - 支持账本数据的接入 + - 合约状态上链 + +* **v0.2** 2018年10月9日 + - 支持Python包的自动生成 + - 支持合约打包为ypk + - 支持文件、数据库等数据的接入 + +* **v0.1** 2018年8月6日 + - 定义了智能合约的语法 + - 基于nashorn引擎,实现了智能合约的执行 + +- - - + +## 使用开源项目说明 +BDWareContract项目站在了许多巨人的肩膀上,感谢这些开源项目。 + +本项目的智能合约后端使用了以下开源库。 + +| 名称 | Licence类型 | 说明 | +| ------ | ---------- | ---- | +| [Project Nashorn](https://openjdk.java.net/projects/nashorn/) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 使用了该项目的编译器,可以将js函数编译为java字节码 | +| [ASM OW2](https://projects.ow2.org/view/asm/) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) with attribution | 基于asm的TreeAPI与VisitorAPI实现合约的静态分析框架 | +| [Netty](https://netty.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用netty作为Http/Websocket的服务端 | +| [gRPC](https://grpc.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用gRPC与BDWareLedger通讯 | +| [RocksDB](https://github.com/facebook/rocksdb) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 后台数据库 | +| [ANTLR](https://github.com/antlr/antlr4) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) | 对合约脚本的词法分析与语法分析 | +| [SM2Java](https://github.com/PopezLotado/SM2Java) | [无](https://github.com/PopezLotado/SM2Java/blob/master/README.md) | 国密SM2 Java语言实现 | + + + +本项目的智能合约前端使用了以下开源库。 + +| 名称 | Licence类型 | 说明 | +| ------ | ---------- | ---- | +| [Bootstrap](https://getbootstrap.com/) | [MIT](https://github.com/twbs/bootstrap/blob/master/LICENSE) | 前端的排版、样式 | +| [jQuery](https://jquery.org/) | [MIT](https://jquery.org/license/) | 用于操作DOM的javascript库 | +| [jQueryUI](https://jqueryui.com/) | [MIT](https://jquery.org/license/) | 前端UI构件库 | +| [DataTables](https://datatables.net/) | [MIT](https://datatables.net/license/mit) | 表格样式 | +| [CodeMirror](https://codemirror.net/) | [MIT](https://codemirror.net/LICENSE) | 代码编辑框样式 | +| [eCharts](https://echarts.apache.org/zh/index.html) | [ApacheV2](https://www.apache.org/licenses/) | 统计图表 | +| [sm-crypto](https://github.com/JuneAndGreen/sm-crypto) | [MIT](https://github.com/JuneAndGreen/sm-crypto/blob/master/LICENCE_MIT) | 国密SM2 javascript语言实现 | + +本项目的文档使用[Sphinx](https://www.sphinx-doc.org/en/master/)生成,感谢[readthedocs](https://readthedocs.org/)提供文档样式。 \ No newline at end of file diff --git a/source/markdown/YJSAPI.md b/source/markdown/YJSAPI.md new file mode 100644 index 0000000..add6503 --- /dev/null +++ b/source/markdown/YJSAPI.md @@ -0,0 +1,1341 @@ +# YJS SDK +## YJS Build-in API + +### 内置对象 Global + + +### 内置对象 requester +该内置对象在export function里面会有值,仅当合约调用签名验证通过。 + + +### 执行合约 executeContract + +参数: + +``` bash +action:executeContract; +contractID:合约的id或名称均可; +operation:调用合约的方法名; +arg: 参数;格式为JSON字符串,有action与arg两个字段。 +``` + +可选参数: + +```bash +requestID:字符串类型,自行生成,用于查询hash +``` + +使用示例: + +```javascript + + function testExecutorContract(arg){ + var ret = JSON.parse(executeContract("ElemeProvider","queryDB",arg)); + if (ret.status == "Success"){ + return JSON.parse(ret.result); + }else return null; + } +``` +### 订阅事件主题 subscribe + +参数 + +``` bash +contractID:字符串类型 合约id或名称均可。 +event:字符串类型 +handler:方法名,该方法必须接受Event(内含字段topic和content)类型的唯一变量为参数;可以不是export方法 +``` + +使用示例: + +```javascript +export function init(arg) { + YancloudUtil.subscribe("topic", handler); + print("Handler: " + handler); +} + +function handler(e) { + print("topic: " + e.topic); + print("content: " + e.content); +} + +``` + +### 发布事件 pubEvent + +参数 + +``` bash +topic:字符串类型,发布的事件主题 +content:字符串类型,发布的事件内容 +``` +使用示例: + +```javascript +export function pub1(arg) { + YancloudUtil.pubEvent("topic", arg); + return "done"; +} +``` + +也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名发布事件 + +```javascript +event topic; +export function pub2(arg) { + topic(arg); + return "done"; +} +``` + +该写法与上面的`pub1`等价。 + +### 发布带语义事件 pubEventConstraint + +参数 + +``` bash +topic:字符串类型,发布的事件主题 +content:字符串类型,发布的事件内容 +semantics:枚举类型,作为字符串输入,事件语义 +``` + +事件语义参数 ++ AT_LEAST_ONCE:至少一次,默认语义 ++ AT_MOST_ONCE:至多一次 ++ ONLY_ONCE:只有一次 + +使用示例: + +```javascript +export function pub1(arg) { + YancloudUtil.pubEventConstraint("topic", arg, "AT_MOST_ONCE"); + return "done"; +} +``` + +也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名按声明的语义发布事件 + +```javascript +event AT_MOST_ONCE topic; +export function pub2(arg) { + topic(arg); + return "done"; +} +``` + +该写法与上面的`pub1`等价。 + +事先声明的事件无论是否声明语义,都可以用后缀s作为方法名的方式调用,发布任意语义的事件: + +```javascript +event topic; +export function pub3(arg) { + topics(arg, "AT_MOST_ONCE"); + return "done"; +} +``` + +该写法与上面的`pub1, pub2`等价。 + +*不带事件语义声明事件时,语义默认为至少一次(AT_LEAST_ONCE)。* + +### 访问资源文件 + +通过Global.Resources去加载ypk内部的资源文件。 + +#### loadAsInputStream + +参数: + + ```bash + path:字符串类型 需要加载文件的地址 + ``` + 使用示例: + + ```javascript + var file = Global.Resources.loadAsInputStream("/deleteit.txt"); + ``` + +#### loadAsScanner + +参数: + + ```bash + path:字符串类型 需要加载文件的地址 + ``` + + 使用示例: + + ```javascript + var scanner = Global.Resources.loadAsScanner("/local.txt"); + ``` +### YancloudUtil + +提供了一些内置的工具方法。 + +#### getKeyPair + +参数: +``` +无 +``` + +使用示例: + +``` +var keyPair = YancloudUtil.getKeyPair(); +//该类型为SM2KeyPair类型, +print(keyPair.getPublicKeyStr()); +print(keyPair.getPrivateKeyStr()); +print(keyPair.toJson()); +``` + + +## YJS Build-in Annotation + +### @Access + +设置合约的调用是否需要签名,这里分为两种,需签名和无签名。 +其中,"verified"表示需要签名。其他则表示无需签名。 + +``` +@Access("verified") +export function easy(arg){ + return "true"; +} +``` + +### @LogType + +LogType注解通过参数的方式声明合约或函数的需要记录的日志类型。 + +其中,Arg表示日志中记录合约执行的参数;Result表示记录合约执行的返回结果;Branch表示记录合约执行分支。 + +例如 ,通过如下LogType注解来声明函数 + +``` +@LogType("Arg","Result","Branch") +export function easy(arg){ + Global.a = "a"; + Global.b = "b"; + if(arg > 0) + return Global.a; + else + return Global.b; +} +``` + +### @LogLocation + +该注解可以修饰`contract`或`function`。 +设置日志存储的位置。参数中指定为“dataware”则存储在账本和本地,如果没有指定为“dataware”则仅存储在本地。 +例如,通过如下LogLocation设置存储位置。 + +在BaaS平台中,可以指定账本名称,BaaS平台默认账本为default,使用 +`@LogLocation("bdledger:default")`。如想保存到自定义的账本,比如,"abc"账本,就使用 +`@LogLocation("bdledger:abc")` + +``` +@LogLocation("dataware") +export function easy(arg){ + Global.a = "a"; +} +``` + + +### @Permission +该注解只能修饰`contract` +设置合约中调用的工具类的权限,包括File、Http、MySQL、MongoDB、RocksDB等工具类。如果合约中用到了以上工具类,需要在注解中添加对应的授权字段,默认只有YJS自带的YancloudUtil;如果没有添加则会抛出"未授权工具类"的异常。 +这6种工具类的详细说明在本小节后续中有说明。 + +``` +@Permission("Http","File") +contract HttpPermission { + export function main(args){ + var http=HttpUtil.httpGet(args); + var dir="adf/adfas/"; + var file=FileUtil.getDir(dir); + return YancloudUtil.currentTimeMillis(); + } +} +``` + +### @Description +该注解可以修饰`contract`或`function`。 +传入合约及函数的简介,可用于生成说明文档中关于exported函数的介绍。 + +``` +@Description("返回数据条目,无需参数") +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` + +### @Param +该注解可以修饰`function`。 +提供调用函数的参数示例,也为生成说明文档中的返回结果提供默认参数。 +``` +@Param({"offset":0,"count":100}) +export function get(args){ + var offset = args.offset; + var count = args.count; + ... +} +``` +### @MockTemplate +该注解可以修饰`function`。 +提供函数的返回模拟数据模板,用于描述返回值的格式.若加此注解在debug方式调用时,返回按照此格式生成的模拟数据。 + + +####支持的字段类型 +``` +@integer 整数 +@string 字符串 +@boolean 布尔值 +@date @time @datatime +@word 单词 @cword 中文单词 +@first @last 英文姓,名 +@cfirst @clast @cname 中文姓,名,全名 +@url @domin @ip @email +@region @province @city @county 地区,省,市,县 +…… +详细格式可以参考http://mockjs.com/examples.html +``` +####注意:模板的格式为{‘result’:模板} +```json +//返回一个对象包含如下字段 +@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) +//返回 +{"password":"3ZLc","name":"William Young","id":36097783842688,"email":"d.fuunwe@gqnr.to"}" + + +//返回元素个数为1-5个之间的一个数组,数组的每个元素都是上述格式的一个对象 +{'result|1-5':[{'id':'@integer','email':'@email','password':'@string','name':'@name'}]} +//返回 +[ + {"password":"dO]wW","name":"Jeffrey Lopez","id":1783453207480410,"email":"a.ckokgxrga@hgiesugi.bb"}, + {"password":"BQYRL","name":"Brian Moore","id":4310212972071102,"email":"k.lbpxocydrh@msgnjtox.na"}, + {"password":"Gw1","name":"Susan Jackson","id":7766580783668916,"email":"h.zjgusl@htce.cr"} +] +``` +``` +@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` +### @Result +该注解可以修饰`function`。 +提供函数的返回结果示例,若加此注解则生成说明文档时将直接返回此结果而不使用默认参数调用函数。 +``` +@Result(666) +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` +### @Cost +该注解可以修饰`function`。 +提供函数的cpu计量功能。 +``` +@Cost({"countGas":true}) +export function .... + + +``` + +## IO工具类 + +### 概览 + +|IO工具类名称|说明| +|---|---| +| [FileUtil](./YJSAPI.html#fileutil) | 文件操作相关的类 | +| [LedgerUtil](./YJSAPI.html#ledgerutil) | 账本操作相关的类 | +| [HttpUtil](./YJSAPI.html#httputil) | Http接口相关的类 | +| [DOIPUtil](./YJSAPI.html#doiputil) | DoIP相关的类 | +| [MySQLUtil](./YJSAPI.html#mysqlutil) | 连接mysql数据库 | +| [MongoDBUtil](./YJSAPI.html#mongodbutil) | MongoDB连接相关的类 | +| [RocksDBUtil](./YJSAPI.html#rocksdbutil) | RocksDB(基于本地文件的k-v数据库) | +| [BDWareTimeSeriesDBUtil](./YJSAPI.html#BDWareTimeSeriesDBUtil) | 基于本地文件的时间序列数据库 | + + +### FileUtil +可以使用@Permission("File")来引入FileUtil对象。 + +``` +@Permission("File") +contract FileSample { +... +} +``` + +该对象支持以下方法: + +#### copyTo + +可以复制文件和目录。第一个参数是source,第二个参数是destination。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | src | 类型为String | +| 2 | dest | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.copyTo("./source.txt","./dest.txt"); +``` + +#### getContent + +获取文件的文本内容,当文件不存在时,返回```undefined```。 + +##### 参数 + +| 序号 | 参数 | 说明 | +| --- | --- | --- | +| 1 | path | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.getContent("./source.txt"); +``` +#### getDir + +获取文件所在的文件夹名,输入参数为字符串。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 类型为String | + +##### 使用示例 +```javascript +var ret = FileUtil.getDir("./parent/src.txt"); +// ret 为 "./parent/"; +``` + +#### getFileName + +获取文件名。输入参数为字符串。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.getFileName("./parent/src.txt"); +// ret 为 "src.txt" +``` + + +#### openFileAsPrinter + +以PrintStream的形式打开文件。 +返回结果是```java.io.PrintStream```类型。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 文件名,类型为String | +| 2 | isAppend| 类型为boolean,表示是否往文件末尾添加 | + +##### 使用示例 + +```javascript +var ret = FileUtil.openFileAsPrinter("./parent/src.txt",true); +ret.println("hello"); +ret.close(); +``` + +### LedgerUtil + +可以使用@Permission("Ledger")来引入LedgerUtil对象。 +``` +@Permission("Ledger") +contract LedgerExample{ +... +} +``` + +#### getClient + +获取一个连接客户端,一个参数,为对象类型。 +返回结果为LedgerClient类型,用于后续的查询账本等操作。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | address | 包含ip和端口两个字段 | + +##### 使用示例 + +```javascript +var address = {}; +address.ip = "127.0.0.1"; +address.port = 18091; +var ledgerClient = LedgerUtil.getClient(address); +``` + +#### queryByHash + +根据Hash查询Transaction。 +返回结果为对象,包含from、to、type和data四个字段,均为String类型。 +其中data为按utf-8编码解析字节数组,如果存证时用的不是utf8编码,可能返回乱码。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | client | 通过getClient方法获得的对象 | +| 2 | info | 对象类型,有两个字段ledger和hash,均为字符串类型 | + +##### 使用示例 + +```javascript +// ... ledgerClient = LedgerUtil.getClient(...); +var info = {}; +info.ledger = "bdcontract"; +info.hash = "4d3b75750835092a50085127702669615b602e53"; +var ret = LedgerUtil.queryByHash(ledgerClient,info); +print(ret.from); +print(ret.to); +print(ret.type); +print(ret.data); +``` + +#### sendTransaction + +存证数据。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | client | 通过getClient方法获得的对象 | +| 2 | info | 对象类型,有from\to\data三个字段,均为String类型 | + +##### 使用示例 + +```javascript +// ... ledgerClient = LedgerUtil.getClient(...); +var info = {}; +info.ledger = "bdcontract"; +info.from = "b60e8dd61c5d32be8058bb8eb970870f07233155"; +info.to = "b60e8dd61c5d32be8058bb8eb970870f07233155"; +info.data = "hello world"; +var ret = LedgerUtil.sendTransaction(ledgerClient,info); +//ret为存证的哈希值 +print(ret); +``` + +### HttpUtil + +可以使用@Permission("Http")来引入HttpUtil对象。 +``` +@Permission("Http") +contract HttpExample{ +... +} +``` + +#### createAPIGate + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | ip | 字符串类型,ip,端口默认为6161 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.createAPIGate("192.168.4.4"); +ret.get("com.tencent.mm","sendMsg","msg"); +print(ret); +``` + +#### createAPIGate + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | ip | 字符串类型,ip| +| 2 | port | 字符串类型,端口 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.createAPIGate("192.168.4.4", "6161"); +ret.get("com.tencent.mm","sendMsg","msg"); +print(ret); +``` + +#### get + +发起Http的get请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | url | 字符串,表示url类型 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.get("https://www.baidu.com"); +print(ret.responseCode); +print(ret.response); +``` + +#### post +发起Http的post请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | args | 对象类型,有url,headers和data三个字段。其中,args.headers为对象类型。| + +##### 使用示例 + +```javascript +var req = {}; +req.url = "https://www.baidu.com"; +req.data = "hello"; +req.header = {}; +req.header.Accept = "application/json"; +req.header["Content-Type"] = "application/json"; +var ret = HttpUtil.post(req); +print(ret.resposeCode); +print(ret.response); +``` + +### DOIPUtil + +可以使用@Permission("DOIP")来引入DOIPUtil对象。 +``` +@Permission("DOIP") +contract DOIPExample{ + ... +} +``` + +#### call +调用一个DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型, 目标DO标识| +| 2 | arg1 | 字符串类型, 输入参数字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.call("86.5000.470/do.hello","inputString"); +``` +#### create +向一个Repository创建一个字符串类型DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型, 目标Repo标识| +| 2 | arg1 | 对象类型,包括doID,doBody字段| + +##### 使用示例 + +```javascript +var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); +var ret = DOIPUtil.create("86.5000.470/repo.localTcpRepo",digitalObject); +``` +#### delete +从一个Repository中删除DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| +| 2 | arg1 | 字符串类型 目标Repo标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.delete("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo"); +``` +#### hello +获取目标Repository的DOIP服务信息 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标Repo标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.hello("86.5000.470/repo.localTcpRepo"); +``` +#### listOperation +获取目标DO支持的DOIP操作 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.listOperation("86.5000.470/do.hello"); +``` +#### register +向LHS注册一个DO,返回分配的标识 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 DO所在Repo标识| +| 2 | arg1 | 字符串类型 DO格式描述字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.register("86.5000.470/repo.localTcpRepo","String"); +``` +#### reregister +修改LHS中DO的注册信息 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| +| 2 | arg1 | 字符串类型 DO所在Repo标识| +| 3 | arg2 | 字符串类型 DO格式描述字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.reregister("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo","String"); +``` +#### retrieve +获取一个DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.retrieve("86.5000.470/do.hello"); +``` +### test +测试DOIPUtils是否可用 +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 任意字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.test("hello"); +``` +#### update +更新目标DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | JS对象,包括doID,doBody字段| + +##### 使用示例 + +```javascript +var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); +var ret = DOIPUtil.update(digitalObject); +``` + + + +### SQLUtil + +可以使用@Permission("SQL")来引入SQLUtil对象。 +可支持MySQL/PostgreSQL/Oracle/GuassDB200等SQL数据库。 +需要将对应的jdbc的jar上传到项目中。 +例如,要使用mysql,可上传mysql-connector-java-8.0.24.jar + +``` +@Permission("SQL") +oracle MySQLExample{ +... +} +``` + +#### initDriver + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | driverClass | 字符串类型 | + +##### 使用示例 + +```javascript + //使用mysql + SQLUtil.initDriver("com.mysql.cj.jdbc.Driver"); + //使用postgresql + SQLUtil.initDriver("org.postgresql.Driver"); + //使用oracle + SQLUtil.initDriver("oracle.jdbc.OracleDriver"); +``` + +#### getConnection + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | URL | 字符串类型,jdbc连接 | +| 2 | usrName | 字符串类型,用户名 | +| 3 | pwd | 字符串类型,密码 | + + +##### 使用示例 + +```javascript +var url = "jdbc:mysql://xx.xx.xx:port/tableName"; +var usrName = "xxx"; +var pwd = "xxx"; +//配置好用户名和密码,url格式为ip或域名+端口,中间以”:”隔开。 +var conn = SQLUtil.getConnection(url,usrName,pwd); +//获取数据库连接 +var sql = "select * from newele.data"; +//创建查询语句 +var statement = conn.createStatement(); +var resultSet = statement.executeQuery(sql); +var waimailist = []; +//解析查询结果 +var meta = resultSet.getMetaData(); +for (;resultSet.next();){ + var line = {}; + for (var j=1;j<=meta.getColumnCount();j++){ + line[meta.getColumnName(j)] = resultSet.getString(j); + } + waimailist.push(line); +} +``` + +其中,getConnection方法返回的对象通过反射机制绑定到了Java的一个java.util.Connection对象。因此,可以查看: + +以了解如何进行Mysql数据库操作。 + + +### MongoDBUtil + +可以使用@Permission("MongoDB")来引入MongoDBUtil对象。 +``` +@Permission("MongoDB") +contract MongoDBExample{ +... +} +``` + +#### getConnection + + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | URL | 字符串类型 数据库的URL | +| 2 | port | 整数类型 端口号 | +| 3 | dbName | 字符串类型 数据库的名称 | +| 4 | usrName | 字符串类型 数据库的用户名 | +| 5 | pwd | 字符串类型 数据库的密码 | + + +##### 使用示例 + +**注意:port为整型,其他参数为String类型** + +```javascript +var client = MongoDBUtil.getConnection(url,port,dbName,usrName,pwd); +//获取数据库对象 +var db = client.getDatabase("yancloud"); +var collection = db.getCollection("containers"); +var iter = collection.find().iterator(); +var ret =""; +for (;iter.hasNext();){ + ret+=iter.next().toJson(); + ret+="\n"; +} +``` + +其中,getMongoDBClient对象通过反射机制绑定到了Java的一个com.mongodb.MongoClient对象。因此,可以查看: + + +以了解该对象的更多方法和使用方式。 + +### RocksDBUtil + +使用@Permission("RocksDB")来引入RocksDBUtil对象。 + +``` +@Permission("RocksDB") +contract RocksDBSample { +... +} +``` + +#### loadDB + +通过loadDB来加载一个RocksDB数据库。 +加载后,可进行get/delete/put等操作。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 字符串类型 数据库部署的路径 | +| 2 | readOnly | 布尔类型 数据库只读 | + +##### 使用示例 + +``` +@Permission("RocksDB") +@Description("这是个使用RocksDB的参考代码") +contract RocksDBSample{ + function onCreate(){ + Global.rocksdb = RocksDBUtil.loadDB("./dbdir/","false"); + } + @Description("示例参数: {\"key\":\"abc\",\"value\":\"def\"}") + export function put(arg){ + arg = JSON.parse(arg); + Global.rocksdb.put(arg.key,arg.value); + return "success"; + } + @Description("示例参数: \"abc\"}") + export function get(arg){ + return Global.rocksdb.get(arg); + return "failed"; + } + @Description("示例参数: \"abc\"") + export function deleteKey(arg){ + return Global.rocksdb.delete(arg); + } + @Description("遍历KV库,无需参数") + export function iter(arg){ + var iter = Global.rocksdb.newIterator(); + var obj = undefined; + var ret = { + }; + for (iter.seekToFirst();(obj=Global.rocksdb.getNext(iter))!=undefined;){ + ret[obj.key]=obj.value; + } + return JSON.stringify(ret) + } +} +``` + +### BDWareTimeSeriesDBUtil + +使用示例 + +``` +@Permission("BDWareTimeSeriesDB") +contract BDWareTimeDBExample{ + function onCreate(arg){ + Global.dbutil = BDWareTimeSeriesDBUtil.getConnection(); + } + + export function put(arg){ + //第一个参数为表名,第二个参数为要放的value,时间戳自动打。 + Global.dbutil.put("defaultTable",arg); + return "success"; + } + @Param + export function getCount(arg){ + return Global.dbutil.getCount("defaultTable"); + } + @Param(1617254937373) + export function queryByStartTime(arg){ + var startDate = java.lang.Long.valueOf(arg); + //查询从开始时刻startDate到最新的数据 + var list = Global.dbutil.query("defaultTable",startDate); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } + + @Description("示例参数: {\"offset\":1,\"len\":1}") + @Param({"offset":1,"len":1}) + export function queryByOffset(arg){ + var offsetLen = JSON.parse(arg); + //可配合getCount使用,查询第offset至offset+len条数据 + var list = Global.dbutil.queryByOffset("defaultTable",offsetLen.offset,offsetLen.len); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } +} + +``` + + +## 加解密工具类 + + +### SM2 +可以使用@Permission("SM2")来引入SM2Util对象。 + +``` +@Permission("SM2") +contract SM2Sample { +... +} +``` + +#### generateKeyPair +生成公私钥。 + +##### 参数 +无参数。 + +##### 使用示例 + +```javascript +var ret = SM2Util.generateKeyPair(); +print(ret.publicKey); +print(ret.privateKey); +return JSON.stringify(ret); +``` + +#### sign + +签名。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 要进行签名的内容 | +| 2 | keyPair | sm2 | + + +##### 使用示例 + +``` +var keypair = SM2Util.generateKeyPair(); +var ret = SM2Util.sign("Hello",keypair); +print(ret.status); +//如果status是success +print(ret.signature); +//如果status是failed +print(ret.message); +``` + +#### verify + +验签。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 待验签的内容 | +| 2 | signature | 字符串类型 签名 | +| 3 | publicKey | 字符串类型 公钥 | + +##### 使用示例 + +```javascript +var ret = SM2Util.verify("Hello","....签名","...公钥"); +// 验证通过时,result为true,status为success +// 失败时,result为failed,status为failed +print(ret.status); +print(ret.result); +``` + +#### encrypt + +sm2加密。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 待验签的内容 | +| 3 | publicKey | 字符串类型 公钥 | + +##### 使用示例 + +```javascript +var ret = SM2Util.encrypt("Hello","...公钥"); +print(ret); +``` +#### decrypt + +sm2解密。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 待验签的内容 | +| 3 | privateKey | 字符串类型 公钥 | + +##### 使用示例 + +```javascript +var ret = SM2Util.decrypt("Hello","...私钥"); +print(ret); +``` + + + +## 多线程工具类 + +### AsyncUtil + +可以使用@Permission("Async")来引入AsyncUtil对象。 +``` +@Permission("Async") +contract AsyncExample{ + export function longTimeTask(arg){ + var a = { + }; + a.count = 100; + AsyncUtil.postFunction(taskFun,a); + } + function taskFun(arg){ + Global.progress = 0; + for (var i=0;i + +* Number + +* Math + +* Date + +* RegExp + +* Error + +* JSON + +## YJS应用框架 + +### ypk项目组成 +如之前描述,ypk中可存放静态资源文件(html/css/js),在智能合约中声明loadResource方法,可返回静态资源文件。 +基于loadResource,本项目提供了一个yjs应用框架。 +该框架可以将合约ypk中的(html/css/js)文件通过executeContract调用,加载至前端并展示。 + +### 函数约定 + +| 序号 | 合约函数名 | 说明 | +|---|---|---| +| 1 | needRender | 不会被调用,有该函数表示需要渲染前端 | +| 2 | getMainFrame | 无参数,返回结果为String类型,表示主页的html文件路径 | +| 3 | loadResource | 参数为String,以文本形式,返回相对路径下的静态资源文件 | + +### 加载流程 +前端加载的参数会解析至global.urlparam。 +包括以下参数: +``` +//global.urlparam对象示例 +{ + "contract":"TrustedStorage0899", //表示合约ID或是合约的名称 + + "keys":{ //表示当前登录者的密钥对 + "privateKey":"ff38dd04710...", + "publicKey":"04fc228..." + }, + "nodeAddr":"022.node.internetapi.cn:21030" //节点的ip+端口 +} +``` + +加载前会先建立与nodeAddr的websocket连接。 +连接建立后,加载流程分为两步: +第一步是用当前的publickey-privatekey登录。登录过程详见`BDContract SDK` 的 `合约节点WebSocket接口` +登录之后,会获取合约的信息。 +并存放于global.currentContract对象。 + +第二步,是根据global.currentContract对象中,是否有needRender方法, +如果有,就会进入加载前端代码的流程。 +具体为1.执行executeCurrentContract("getMainFrame") 获取页面的html,append至mainDIV之后, +会解析所有` + + +``` +示例的资源文件"/html/hello.js"如下: + +```javascript +var queryDataFromContract = function(){ + //第一个参数为函数名,第二个为参数,第三个参数为回调。 + var data = executeCurrentContract("query","abc",function(argg){ + $("#resultText")[0].innerHTML = argg.result; + }); +} +``` + +参考示例: + + + + +### YJS-Python + +TODO + diff --git a/source/markdown_BDWare/ContractAPI.md b/source/markdown_BDWare/ContractAPI.md new file mode 100644 index 0000000..52d24f1 --- /dev/null +++ b/source/markdown_BDWare/ContractAPI.md @@ -0,0 +1,4131 @@ +# BDware SDK +除使用可视化的智能合约在线IDE外,用户还可使用WebSocket接口、Http接口、Bash接口来启动和运行合约. + +- - - + +## WebSocketSDK下载与安装 +合约SDK提供javascript版本与java版本的客户端。 + +java客户端的下载链接为:[java source](./_static/BDWareJavaClient.zip)和[jar](./_static/BDWareConfigTool.zip) +可参考java_source下的README.md及测试用例。 + +javascript的下载链接为:[js SDK](./_static/js/createWS.js) +内置的SM2加密库链接:[sm2 SDK](./_static/js/sm2.js) + +### 建立连接 +建立与节点服务器之间的WebSocket连接. + +#### 参数 + +| 字段 | 值 | +| ---------- | ------------------------------------------------------------ | +| url | 建立WebSocket的服务器URL. 使用`http`协议时, 前缀为`ws://`, 如`"ws://localhost:1717/SCIDE/SCExecutor"`; 使用`https`协议时, 前缀为`wss://` | +| msgHandler | 收到服务器WebSocket回复后的回调函数, 用户可自行编写, 也可参考下面提供的示例 | + +#### 请求示例 + +```javascript +var url = "ws://127.0.0.1:1717/SCIDE/SCExecutor";//与Slave节点建立连接 +//var url = "ws://127.0.0.1:1718/NodeCenterWS";//与Manager节点建立连接 +var msgHandler = function(m){ + console.log("recmsg:"); + console.log(m); +}; +var onOpenHandler=undefined; +wssocket = createWssocket(url,onOpenHandler,msgHandler); +``` + +#### 返回结果示例 + +``` +{ + receiveSeg: [Function (anonymous)], + isSending: false, + sendList: [], + monitor: [Function (anonymous)], + send: [Function (anonymous)], + sendNextSegment: [Function (anonymous)], + isOpen: [Function (anonymous)] +} +``` + + + +### ping + +`ping`服务器测试 + +#### 参数 + +| 字段 | 值 | +| ------ | ---- | +| action | ping | + +#### 请求示例 + +``` +var request = {}; +request.action = "ping"; +wssocket.send(JSON.stringify(request)); +``` + +#### 返回结果示例 + +``` +{ + "action":"pong" +} +``` + +### 登录 + +使用Websocket接口调用需要权限的接口时,不论是连接CenterPortal还是NodePortal必须先**登录**。 +登录的流程有3步: + +- 客户端向服务端建立连接,连接建立完成后发送{"action":"getSessionID"}(可在onOpenHandler中实现) +- 服务端收到请求后,会向客户端返回类似{"action":"onGetSessionID","session":"-4959947809200104526_session"}的结果 +- 客户端收到onGetSessionID后,会使用本地的公私钥对sessionID进行签名,并调用login接口 +- 服务端会返回onLogin的结果,data字段返回的是该公钥对应的角色。 + +- - - + +## 用户角色划分 + +### 合约节点的角色划分 + +在合约节点(NodePortal.html)中分为NodeManager/ContractProvider/ContractInstanceManager/ContractUser四类角色。 + +| 角色 | 说明 | +| ----------------------- | ------------------------------------------------------------ | +| NodeManager | 该节点的管理者,拥有用户管理、节点配置等权限 | +| ContractProvider | 拥有编辑合约、开发合约代码、运行调试等权限 | +| ContractInstanceManager | 拥有启、停合约实例、配置合约实例IO等权限 | +| ContractUser | 拥有查看合约实例列表、调用合约等权限 | +| Anonymous | 匿名用户,可以调用合约,可以申请成为ContractProvider/InstanceManager等角色 | + + +| 接口 | 说明 | 角色 | +| ------------------------------- | -------------------- | ----------------------------------------- | +| changeDumpPeriod | 设置备份周期 | ContractInstanceManager; | +| createLedger | 创建账本 | ContractInstanceManager; | +| dumpContract | 手动备份 | ContractInstanceManager; | +| deleteMemoryFile | 删除镜像 | ContractInstanceManager; | +| forkContract | 迁移合约 | ContractInstanceManager; | +| getDumpPeriod | 获取备份周期 | ContractInstanceManager; | +| killAllContract | 停止全部实例 | ContractInstanceManager; | +| killContractProcess | 停止某一实例 | ContractInstanceManager; | +| listMemoryFiles | 列取某一实例的镜像 | ContractInstanceManager; | +| loadMemory | 加载镜像 | ContractInstanceManager; | +| queryContractInstanceDOI | 查询合约实例信息 | ContractInstanceManager; | +| rebuildHashIndex | | ContractInstanceManager; | +| setPermission | | ContractProvider;ContractInstanceManager; | +| startContract | 启动合约 | ContractInstanceManager; | +| startContractBatched | 废弃 | ContractInstanceManager; | +| startContractByYPK | 启动合约 | ContractInstanceManager; | +| startContractInTempZips | 废弃 | ContractInstanceManager; | +| startContractP2PTrustfully | 启动合约(集群模式) | ContractInstanceManager; | +| updateContract | | ContractInstanceManager; | +| connectTo | 连接合约实例输出流 | ContractInstanceManager;ContractUser; | +| countContractLogGroupByAction | | ContractInstanceManager;ContractUser; | +| countContractLogGroupByCategory | | ContractInstanceManager;ContractUser; | +| getLastLog | 查询日志 | ContractInstanceManager;ContractUser; | +| getLog | 查询日志 | ContractInstanceManager;ContractUser; | +| getLogSize | 查询日志 | ContractInstanceManager;ContractUser; | +| listAllContractProcess | | ContractInstanceManager;ContractUser; | +| listContractProcess | 查询合约实例列表 | ContractInstanceManager;ContractUser; | +| listLeakContractProcess | | ContractInstanceManager;ContractUser; | +| queryContractLogByDate | | ContractInstanceManager;ContractUser; | +| queryContractLogByKey | | ContractInstanceManager;ContractUser; | +| queryContractLogByOffset | | ContractInstanceManager;ContractUser; | +| queryContractLogDetail | | ContractInstanceManager;ContractUser; | +| queryContractLogSize | | ContractInstanceManager;ContractUser; | +| queryNodeLogByDate | | ContractInstanceManager;ContractUser; | +| queryNodeLogByOffset | | ContractInstanceManager;ContractUser; | +| queryNodeLogSize | | ContractInstanceManager;ContractUser; | +| rebuildContractLogIndex | | ContractInstanceManager;ContractUser; | +| rebuildNodeLogIndex | | ContractInstanceManager;ContractUser; | +| changePublic | | ContractProvider; | +| createFile | 新建文件 | ContractProvider; | +| deleteFile | 删除文件 | ContractProvider; | +| distributeContract | | ContractProvider; | +| downloadContract | | ContractProvider; | +| downloadContractFromOtherHost | | ContractProvider; | +| generateAnnotationSample | | ContractProvider; | +| generateAppDataAnalysis | | ContractProvider; | +| generateAppDataSource | | ContractProvider; | +| generateBDCoinEventProject | | ContractProvider; | +| generateBDCoinProject | | ContractProvider; | +| generateBiddingExample | | ContractProvider; | +| generateCSVProject | | ContractProvider; | +| generateContractExecutor | | ContractProvider; | +| generateDAC4BDOA | | ContractProvider; | +| generateDAC4BDOA_persist | | ContractProvider; | +| generateDACSample | | ContractProvider; | +| generateEmptyProject | | ContractProvider; | +| generateEventPublisher | | ContractProvider; | +| generateEventSubscriber | | ContractProvider; | +| generateGasExample | | ContractProvider; | +| generateHello | | ContractProvider; | +| generateHttpExample | | ContractProvider; | +| generateIncentives | | ContractProvider; | +| generateJSONExample | | ContractProvider; | +| generateLedgerExample | | ContractProvider; | +| generateLedgerProject | | ContractProvider; | +| generateLicenceManager | | ContractProvider; | +| generateLoggerExample | | ContractProvider; | +| generateMySQLExample | | ContractProvider; | +| generateMySQLProject | | ContractProvider; | +| generatePostgreSQLSample | | ContractProvider; | +| generateReadme | | ContractProvider; | +| generateRenderSample | | ContractProvider; | +| generateRocksDBSample | | ContractProvider; | +| generateSM2Example | | ContractProvider; | +| generateStaticResource | | ContractProvider; | +| generateTFLinux | | ContractProvider; | +| generategenerateTFMac | | ContractProvider; | +| getProject | | ContractProvider; | +| getTemplateList | | ContractProvider; | +| importContractInstanceCodeByDOI | | ContractProvider; | +| listFile | | ContractProvider; | +| listProject | | ContractProvider; | +| listProjectPermission | | ContractProvider; | +| listProjects | | ContractProvider; | +| renameFile | | ContractProvider; | +| saveFile | | ContractProvider; | +| startContractAsDebug | | ContractProvider; | +| uploadFile | | ContractProvider; | +| compile | | ContractProvider;ContractInstanceManager; | +| evaluates | | ContractProvider;ContractInstanceManager; | +| executeContractP2PTrustfully | | ContractProvider;ContractInstanceManager; | +| getCodeByID | 查询代码 | ContractProvider;ContractInstanceManager; | +| getControlFlowByFileName | | ContractProvider;ContractInstanceManager; | +| getGasValue | | ContractProvider;ContractInstanceManager; | +| listCompiledFiles | | ContractProvider;ContractInstanceManager; | +| queryContractResourceInfo | | ContractProvider;ContractInstanceManager; | +| queryFreeResourceInfo | | ContractProvider;ContractInstanceManager; | +| staticVerifyContract | | ContractProvider;ContractInstanceManager; | +| writeDyjs | | ContractProvider;ContractInstanceManager; | +| authNodeRole | 授权角色 | NodeManager; | +| changeBDledger | 修改账本配置 | NodeManager; | +| changeIpPort | | NodeManager; | +| changeNodeCenter | 修改集群地址 | NodeManager; | +| changeNodeName | | NodeManager; | +| changeIpPort | | NodeManager; | +| changeDOIPConfig | | NodeManager; | +| changeYJSPath | | NodeManager; | +| countNodeLogGroupByCategory | | NodeManager; | +| countRole | | NodeManager; | +| deleteRole | | NodeManager; | +| downloadUUID | 废弃 | NodeManager; | +| getEncodedUUID | 废弃 | NodeManager; | +| getPeerID | | NodeManager; | +| listAllAuthRole | | NodeManager; | +| listNodeInfos | | NodeManager; | +| listUnAuthRole | | NodeManager; | +| loadConfig | | NodeManager; | +| loadNodeConfig | | NodeManager; | +| lockEdit | | NodeManager; | +| unlockEdit | | NodeManager; | +| updateConfig | | NodeManager; | +| uploadLicence | | NodeManager; | +| applyNodeRole | 申请角色 | 任意角色 | +| executeContract | 调用合约 | 任意角色 | +| getConnCount | | 任意角色 | +| getHashAbstractLocally | | 任意角色 | +| getHashLocally | | 任意角色 | +| getNodeRoleDeprecated | 查询当前角色 | 任意角色 | +| getSessionID | | 任意角色 | +| listAdapters | | 任意角色 | +| listTheContractProcess | | 任意角色 | +| login | 登录 | 任意角色 | +| longStr | | 任意角色 | +| ping | | 任意角色 | +| queryDataByHash | | 任意角色 | +| queryDataByHashLocally | | 任意角色 | +| queryHashByOffset | | 任意角色 | +| queryHashByRequestID | | 任意角色 | +| queryHashSize | | 任意角色 | +| queryLedgers | | 任意角色 | +| queryRole | | 任意角色 | +| queryTransactionByHash | | 任意角色 | +| sendTransaction | | 任意角色 | +| setLogStage | | 任意角色 | + +### 合约准入中心角色划分 + +共分为两类角色:CenterManager和NodeManager。其中,CenterManager拥有对集群设置的权限。 +NodeManager可以增加、删除节点等操作。 + +| 接口 | 说明 | 角色 | +| ----------------------------- | ------------ | -------------------------- | +| authNodeManager | | CenterManager; | +| countActionLogByCategory | | CenterManager; | +| countCMLogByCategory | | CenterManager; | +| delete | | CenterManager; | +| listAllUsers | | CenterManager; | +| listApplyList | | CenterManager; | +| listLicence | | CenterManager; | +| queryActionLog | | CenterManager; | +| queryCMLog | | CenterManager; | +| updateLicence | | CenterManager; | +| addNode | | CenterManager;NodeManager; | +| changeNCFile | | CenterManager;NodeManager; | +| changeOtherNC | | CenterManager;NodeManager; | +| createTrustUnit | 创建可信集群 | CenterManager;NodeManager; | +| deleteTrustUnit | | CenterManager;NodeManager; | +| getNCFile | | CenterManager;NodeManager; | +| getNodeTrustUnits | | CenterManager;NodeManager; | +| getOtherNC | | CenterManager;NodeManager; | +| listContractProcess | | CenterManager;NodeManager; | +| listMultiPointContractProcess | | CenterManager;NodeManager; | +| listNodes | | CenterManager;NodeManager; | +| listTrustUnits | | CenterManager;NodeManager; | +| queryUserStat | | CenterManager;NodeManager; | +| stopMultiPointContractProcess | | CenterManager;NodeManager; | +| applyRole | | NodeManager; | +| executeContract | 调用合约 | 任意角色 | +| executeContractTrustfully | | 任意角色 | +| getManagerPubkey | | 任意角色 | +| getNodeRole | | 任意角色 | +| getNodeSessionID | | 任意角色 | +| getRole | | 任意角色 | +| getSessionID | | 任意角色 | +| login | 登录 | 任意角色 | + +- - - + +## 合约节点Http接口 + +`http://xxx.xxx.xxx.xxx:1717/SCIDE/SCManager`为提供Http接口服务的服务器 URL(`xxx.xxx.xxx.xxx:1717`为BDWare SCIDE运行的IP和端口号) , 用户可通过在URL后附加字段参数, 完成以下功能. +`http://xxx.xxx.xxx.xxx:18000/SCIDE/SCManager` 为提供Http接口服务的服务器 + +URL(`xxx.xxx.xxx.xxx:1717` 为BDWare SCIDE运行的IP和端口号),用户可通过在URL后附加字段参数,完成以下功能: + + +### 用户管理类 + +#### ping + +`ping`服务器测试 + +##### 方法 + +GET + +##### 参数 + + +| 字段 | 值 | +| ------ | ---- | +| action | ping | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=ping +``` + +##### 返回结果示例 + +```json +{"data":"pong"} +``` + + +### 合约代码管理类 + + +#### 下载合约项目 + +##### 方法 + +GET + +##### 参数 + + +| 字段 | 值 | +| ----------- | ---------------- | +| action | downloadContract | +| projectName | 合约项目名 | +| isPrivate | 是否在私有目录下 | +| pubKey | 用户公钥 | +| timestamp | 时间戳 | +| sign | 签名 | + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=downloadContract&projectName=BDCoin&isPrivate=false&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba3 +8b7ff78aa631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 +``` + +#### 上传文件 + +##### 方法 + +POST + + +##### 参数 + + +| 字段 | 值 | +| --------- | ---------------- | +| path | 文件上传路径 | +| fileName | 待上传文件名 | +| isPrivate | 是否在私有目录下 | +| order | 第几个数据包 | +| count | 数据包总数 | +| timestamp | 时间戳 | +| sign | 签名 | + + +##### 请求示例 + + +``` +http://127.0.0.1:18000/SCIDE/Upload?path=/TEST/TEST.yjs&fileName=WechatIMG15.jpeg&isPrivate=true&order=0&count=3&pubKey=0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba36ca83066870cf2c1d5de6df67e24e68dde7934af9b31d94a6084281db3d32d5ce42ab8f75bf799aca05&sign=dd867469f5adf9986e4ea6215febeae50c7d4c3836d002cf8c17050dfca031fd2595ffa8646e9eeae53150d2cbaea690e27d818eaf5cea3632ee1b69c3307a4b631e97346086e2d48fac2ba7f5b75ccbd19ebf495c0e6f9934d69e3b083da4d42e46c991e0c2ea8bb45d59f31f46d0ec700fb01f2fdd275 +``` + +##### 返回结果示例 + +```json +{"status":"true","data":"success"} +``` + +#### 保存合约脚本 + +向服务器发送请求, 向服务器本地保存合约脚本内容. + +##### 方法 + +GET + + +##### 参数 + +| 字段 | 值 | +| ------- | -------------- | +| action | writeDyjs | +| target | 合约脚本文件名 | +| content | 合约脚本内容 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=writeDyjs&target=testyjs.yjs&content=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onWriteDyjs", + "data": "success" +} +``` + +后续用户可启动并调用该合约. + + + + + + + +### 合约实例管理类 + +#### 查询合约进程 + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=listContractProcess +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onListContractProcess", + "data": "[\n {\n \"id\": \"-562752842\",\n \"name\": \"shortc\",\n \"port\": \"1626\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]" +} +``` + + +#### 启动合约 + +向服务器发送请求, 启动某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------------- | +| action | startContract | +| script | 合约脚本内容, 需进行进行URIEncode | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContract&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D +``` + +##### 返回结果示例 + +```json +{ + "data": "{\"status\":\"Success\",\"result\":\"\"}", + "action": "onStartContract", + "cid": "-562752842", + "executeTime": 1187 +} +``` + + + +#### 调用合约 + +向服务器发送请求, 调用某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------------------- | --------------------------- | +| action | executeContract | +| contractID | 合约ID | +| withDynamicAnalysis | true/false 是否进行动态分析 | +| operation | 调用合约的方法名 | +| arg | 调用合约的参数 | +| pubkey | 可选,调用者公钥 | +| signature | 可选,签名 | + + +其中pubkey为sm2的公钥,计算方式如下: + +```javascript +//sm2 可从sm2.js中加载获得。 +signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); +``` + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=executeContract&contractID=-620602333&operation=main&arg=hhh +``` + +##### 返回结果示例 + +```json +{ + "data": "{\"status\":\"Success\",\"result\":\"3\"}", + "action": "onExecuteResult", + "executeTime": "13" +} +``` + + + + +#### 批量启动合约 + +向服务器发送请求, 启动服务器中保存有合约脚本的一系列合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ------------------------------------ | +| action | startContractBatched | +| fileList | 合约脚本文件列表(Json数组,URLEncode) | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContractBatched&fileList=%5B%20%22EventPuber.yjs%22%2C%20%22EventSuber.yjs%22%2C%20%22LicenceManager.yjs%22%20%5D + +``` + +##### 返回结果示例 + +```json +{"EventPuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","LicenceManager.yjs":"{\"status\":\"Success\",\"result\":\"\"}","EventSuber.yjs":"{\"status\":\"Success\",\"result\":\"\"}","action":"onStartContract"} + +``` + + + + +#### 启动Zip包合约 + +向服务器发送请求, 启动服务器中包装为`zip`格式的合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| --------- | ----------------------- | +| action | startContractInTempZips | +| owner | 调用者公钥 | +| path | zip合约(路径及)文件名 | +| signature | 调用者签名 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=startContractInTempZips&owner=0475c7b061f32477c1e228dd04143daf58a5574dc3f6b02bd2857cc794eb92bfe98606dc314049e77fd8714f57a5a481cb470cc759e688fe60d40fc87092165e55&path=traceTest.zip&signature=650d3cad50509682937c253d84da99230e8ea1bcfb9b10f6d18f8888c7c4b6b4%2C72231a6daa078a3ce657c0a2ed38251b7db56cf725beaf86780d4c240b19ccc2 + +``` + +##### 返回结果示例 + +```json +{"data":"verify failed","action":"onStartContract"} + +``` + + + + +#### 获取合约代码 + +向服务器发送请求, 获取某个ID合约的脚本代码. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ----------- | +| action | getCodeByID | +| contractID | 合约ID | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=getCodeByID&contractID=814046805 + +``` + +##### 返回结果示例 + +```json +{"status":true,"action":"onCodeResult","data":"@LogType(\"Arg\")\ncontract EventSuberAtCHQ{\n\t\n \texport function init(arg){\n\t\tvar result \u003d YancloudUtil.subscribe(\"EventPuberAt3966\",\"abc\",handler);\n // print(\"Handler:\"+handler);\n \t \n \t\treturn result;\n\t}\n \texport function handler(e){\n var ret \u003d \"ReceiveEvent:\";\n\t\tret+\u003d\"\\n\";\n \tprint(ret);\n \tret+\u003dYancloudUtil.executeContract(\"EventPuberAt3966\",\"notify\",\"success\");\n \tprint(ret);\n return ret;\n\t}\n}\n"} + +``` + + + + +#### 保存合约状态 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------ | +| action | dumpContract | +| contractID | 合约ID 或 合约Name= | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/SCManager?action=dumpContract&contractID=counter&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022004ffd1346b936196f5b13953d2f3e11823a0d0a2d2f6fecea258cef8e20d99c0022100bbc219ed1f56799ba28a763b9e9e47063164e7ceecfbfa752de42f44551ffb83 + +``` + +##### 返回结果示例 + +```json +{"data":"success","size":"3.76 KB","time":"0.03s"} + +``` + + + + +#### 获取合约内存文件列表 + +向服务器发送请求, 获取某子文件夹中的所有内存文件列表. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | listMemoryFiles | +| contractID | 合约Id 或 合约Name | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/SCManager?action=listMemoryFiles&contractID=-247468535&pubKey=040461417efe01423ba603f71c689387e8aac4aa2a6f7cddfaf22c1d22c40222f7669a054e7ec2e8533b04ccbc7a0e6655ac4ae4acef81a2b1822ec6cabcaf6c1f&sign=3045022075c7268e888b0efdef167a3f4dfc6589d771c6be41b3c0a1dc12d057e811f395022100d44f460d0cc3643e169ef08231e75a1e895646c53295c0ef1d15c3b462a53d6b + +``` + +##### 返回结果示例 + +```json +{"data":["2020-09-23.18:40:38","2020-09-24.16:03:41","2020-09-24.16:58:39","2020-09-24.18:25:47","2020-09-24.18:32:37","2020-09-24.20:54:41","2020-09-24.20:57:39","2020-09-24.21:31:07","2020-09-24.21:32:09","2020-09-24.21:36:11","2020-09-28.15:29:15","2020-09-28.20:28:29","2020-09-28.20:39:46","2020-09-28.21:45:31","2020-09-28.21:49:18","2020-09-28.22:27:34","2020-09-28.22:31:09","2020-09-28.22:32:49","2020-10-07.16:51:06","2020-10-07.16:51:23","2020-10-25.21:09:10","2020-12-14.19:06:53","2021-02-02.10:28:56","2021-02-02.10:31:13"],"action":"onListMemoryFiles"} + +``` + +#### 停止合约 + +向服务器发送请求, 停止某个合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------------- | +| action | killContractProcess | +| id | 合约ID | +| *requestID | 请求ID, String类型 | + +`*`表示可选参数 + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=killContractProcess&id=-1759263594 + +``` + +##### 返回结果示例 + +```json +{"status":false,"action":"onListContractProcess","data":"[\n {\n \"id\": \"-65051856\",\n \"name\": \"EventSuber\",\n \"port\": \"1631\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"814046805\",\n \"name\": \"EventSuberAtCHQ\",\n \"port\": \"1630\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"2023975189\",\n \"name\": \"LicenceService\",\n \"port\": \"1632\",\n \"times\": \"0 \",\n \"traffic\": \"32.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n },\n {\n \"id\": \"-620602333\",\n \"name\": \"shortc\",\n \"port\": \"1627\",\n \"times\": \"0 \",\n \"traffic\": \"0.00 B\",\n \"storage\": \"0.00 B\",\n \"contractStatus\": \"Ready\"\n }\n]"} + +``` + + + + +#### 停止所有合约 + +向服务器发送请求, 停止服务器上启动的所有合约. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | killAllContract | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=killAllContract + +``` + +##### 返回结果示例 + +```json +{"status":false,"action":"onKillAllContract","data":"Kill:7357,7541,7548,7555,7584,7585,7591,7598,7609,7612,8440,8442,8444,8521,"} + +``` + +#### 静态分析合约 + +向服务器发送请求, 静态分析合约脚本. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------- | +| action | staticVerifyContract | +| contractid | 合约ID | +| script | 请求ID, String类型 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=staticVerifyContract&contractid=943728900&script=contract%20shortc%7B%0A%09export%20function%20main(arg)%7B%0A%09%09return%20arg.length%3B%09%0A%09%7D%0A%7D&path=static.yjs + +``` + +##### 返回结果示例 + +```json +{"data":"{\"status\":\"Success\",\"result\":\"{\\\"main\\\":\\\"Ret:arg \\\"}\"}","action":"onExecuteResult","cid":"943728900","executeTime":54} + +``` + + + +#### 获取合约静态分析流 + +向服务器发送请求, 获取某个合约的静态分析Control Flow. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------------ | +| action | getControlFlowByFileName | +| path | 合约ID | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=getControlFlowByFileName&path=EventSuber.yjs + +``` + +##### 返回结果示例 + +```json +{"init":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","aload 4","invokedynamic dyn:getProp|getElem|getMethod:YancloudUtil (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B3","stmts":["dup","invokedynamic dyn:getMethod|getProp|getElem:subscribe (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B4","stmts":["swap","ldc XiaomiSmartHomeAtPKU","ldc onAirPurifierModeChange","aload 4","invokedynamic dyn:getProp|getElem|getMethod:handler (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B5","stmts":["invokedynamic dyn:call:\\\u003dYancloudUtil\\,subscribe (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B6","stmts":["\u003dL3\u003d","astore 5"],"original":"\t\tvar result \u003d YancloudUtil.subscribe(\"XiaomiSmartHomeAtPKU\",\"onAirPurifierModeChange\",handler);"},{"type":"Continuous","name":"B7","stmts":["\u003dL4\u003d","aload 5","areturn"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B8","stmts":["\u003dL5\u003d"],"original":" \t\treturn result;"},{"type":"Continuous","name":"B9","stmts":["\u003dL6\u003d"],"original":" \t\treturn result;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B9","label":{"label":"e"}}]},"handler":{"blocks":[{"type":"Continuous","name":"B0","stmts":["\u003dL0\u003d","aload 0","invokevirtual wrp/jdk/nashorn/internal/runtime/ScriptFunction getScope ()Lwrp/jdk/nashorn/internal/runtime/ScriptObject;"],"original":""},{"type":"Continuous","name":"B1","stmts":["\u003dL1\u003d","astore 4"],"original":""},{"type":"Continuous","name":"B2","stmts":["\u003dL2\u003d","ldc ReceiveEvent:","aload 2","invokedynamic dyn:getProp|getElem|getMethod:content (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B3","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B4","stmts":["ldc ","invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B5","stmts":["aload 2","invokedynamic dyn:getProp|getElem|getMethod:type (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 0 "],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B6","stmts":["invokestatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime ADD (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B7","stmts":["\u003dL3\u003d","astore 5"],"original":" var ret \u003d \"ReceiveEvent:\"+e.content+\" \"+e.type;"},{"type":"Continuous","name":"B8","stmts":["\u003dL4\u003d","aload 4","invokedynamic dyn:getMethod|getProp|getElem:print (Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B9","stmts":["getstatic wrp/jdk/nashorn/internal/runtime/ScriptRuntime UNDEFINED Lwrp/jdk/nashorn/internal/runtime/Undefined;","aload 5","invokedynamic dyn:call:print (Ljava/lang/Object;Lwrp/jdk/nashorn/internal/runtime/Undefined;Ljava/lang/Object;)Ljava/lang/Object; HANDLE:wrp/jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite; (6) 5 "],"original":" \tprint(ret);"},{"type":"Continuous","name":"B10","stmts":["pop"],"original":" \tprint(ret);"},{"type":"Continuous","name":"B11","stmts":["\u003dL5\u003d","aload 5","areturn"],"original":" return ret;"},{"type":"Continuous","name":"B12","stmts":["\u003dL6\u003d"],"original":" return ret;"},{"type":"Continuous","name":"B13","stmts":["\u003dL7\u003d"],"original":" return ret;"}],"edges":[{"from":"B0","to":"B1","label":{"label":"e"}},{"from":"B1","to":"B2","label":{"label":"e"}},{"from":"B2","to":"B3","label":{"label":"e"}},{"from":"B3","to":"B4","label":{"label":"e"}},{"from":"B4","to":"B5","label":{"label":"e"}},{"from":"B5","to":"B6","label":{"label":"e"}},{"from":"B6","to":"B7","label":{"label":"e"}},{"from":"B7","to":"B8","label":{"label":"e"}},{"from":"B8","to":"B9","label":{"label":"e"}},{"from":"B9","to":"B10","label":{"label":"e"}},{"from":"B10","to":"B11","label":{"label":"e"}},{"from":"B11","to":"B13","label":{"label":"e"}}]}} + +``` + +### 日志查看类 + +#### 合约日志-查询数量 + +##### 方法 + +GET + +contractName为空或是不传入时,则为查询全部合约的条数 + + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------------------ | +| action | queryContractLogSize | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogSize&contractName=NanningDataSource +``` + +##### 返回结果示例 + +```json +{ + "size": 12, + "action": "onQueryContractLogSize", + "status": "success" +} + +``` + +#### 合约日志-根据日期查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------------------------------- | +| action | queryContractLogByDate | +| start | long,必须,起始时间 | +| end | long,非必须,若无end,默认为当前时间 | +| contractName | 字符串,非必须,合约名称 | + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByDate&start=1597296300272&end=1597296305747 +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getMainFrame", + "costTime": "2493", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296300272, + "key": "-8590335427581967208" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "732", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296301030, + "key": "849660532962309239" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4580", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305745, + "key": "-8003529429500512736" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4551", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305746, + "key": "7604666709899222357" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305751, + "key": "-7561786202695627022" + } + ], + "action": "onQueryRecentContractLog" +} +``` + +#### 合约日志-根据偏移量查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | --------------------------------------------- | +| action | queryContractLogByOffset | +| count | long,必须,获取日志条数 | +| offset | long,非必须,若无offset,默认返回最新count条 | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByOffset&count=5&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "loadResource", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305842, + "key": "-2390672423847654148" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "isOwner", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305868, + "key": "6056586201629372511" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getApplyList", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305893, + "key": "3882409580676458151" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "getAcceptList", + "costTime": "4", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "date": 1597296305908, + "key": "-3437513873417136535" + }, + { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654, + "key": "203156239086062402" + } + ], + "action": "onQueryRecentContractLog" +} +``` + +#### 合约日志-根据key查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------- | +| action | queryContractLogByKey | +| key | long,必须,该日志对应的key | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryContractLogByKey&key=203156239086062402 +``` + +##### 返回结果 + +```json +{ + "data": { + "action": "executeContract", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "contractID": "-1382208250", + "contractName": "NanningDataSource", + "function": "analysisByIndustry", + "costTime": "6", + "totalGas": "0", + "executionGas": "0", + "extraGas": "0", + "signature": "4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02", + "arg": " {\"year\":2018,\"category\":\"工业\",\"indexType\":\"营业额\"}", + "date": 1597296314654 + }, + "action": "onQueryContractLogByKey" +} +``` + +#### 合约日志-按时间段统计调用次数 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------------------------------------------- | +| action | countContractLogGroupByCategory | +| start | long,必须,起始时间 | +| end | 非必须,终止时间,默认为当前 | +| interval | long,非必须,统计间隔 | +| category | 非必须,合约名称以逗号连接,不传入时统计全部合约调用情况 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=countContractLogGroupByCategory&start=1596758400000&interval=86400000 +``` + +##### 返回结果 + +```json +{ + "start": 1596758400000, + "interval": 86400000, + "action": "onCountContractLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 43, + 14 + ] +} +``` + +#### 账本日志-查询数量 + +查询通过本节点去账本上记录的日志数量 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ---------------- | +| action | queryHashSize | +| contractName | 非必须,合约名称 | + + + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashSize&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "count": "2", + "action": "onQueryHashSize" +} +``` + + +#### 账本日志-根据偏移量查询 + +查询x条通过本节点去账本上记录的日志的哈希列表 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | ----------------------------------------------------------- | +| action | queryHashByOffset | +| count | 整数,必须,表示条数 | +| offset | 整数,非必须,表示偏移量,不传入offset则默认返回最新count条 | +| contractName | 字符串,非必须,表示合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryHashByOffset&count=1&contractName=NanningDataSource +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "hash": "3a6c60621907146b77146c1f2d48700e47520173", + "date": 1597296314658 + } + ], + "action": "onQueryHash", + "status": "success" +} +``` + +#### 账本日志-根据hash查询详情 + +根据hash来查询日志内容 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------------------- | +| action | queryDataByHash | +| hash | 字符串,可通过queryHashByOffset | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryDataByHash&count=1&contractName=NanningDataSource&hash=3a6c60621907146b77146c1f2d48700e47520173 +``` + +##### 返回结果 + +```json +{ + "from": "0x3034643139323433323966373263656431343866", + "to": "0x65786563757465436f6e74726163740000000000", + "data": "1597296314655 --> {\"extraGas\":\"0\",\"totalGas\":\"0\",\"executionGas\":\"0\",\"signature\":\"4c2cef1756b2b591ab7eead19d67331e2294c7ba765c72298733c306ada0b6e84afbb6c7b9dba48b9843236ebe67aecb4af09fe58a51eef0e2e89b9f3e5cad02\",\"costTime\":\"6\",\"arg\":\" {\\\\\\\"year\\\\\\\":2018,\\\\\\\"category\\\\\\\":\\\\\\\"工业\\\\\\\",\\\\\\\"indexType\\\\\\\":\\\\\\\"营业额\\\\\\\"}\",\"contractID\":\"-1382208250\",\"action\":\"analysisByIndustry\",\"pubKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}", + "requestID": "1597296314629_6067", + "action": "onQueryDataByHash" +} +``` + +#### 账本日志-根据requestID查询Hash + +根据requestID来查询日志内容,需由开发者保证requestID的唯一性 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| --------- | ------------------------ | +| action | queryHashByRequestID | +| requestID | 字符串,在发起调用时生成 | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=queryHashByRequestID&requestID=0987654321ab +``` + +#### 节点日志-查询数量 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ---------------------------- | +| action | queryNodeLogSize | +| category | 非必须,不传入时查询全部情况 | + +其中包括:ping、startContract、saveFile等。 + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize + +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogSize&category=login +``` + +##### 返回结果 + +```json +{ + "size": 177, + "action": "onQueryNodeLogSize", + "status": "success" +} +``` + +#### 节点日志-按日期查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | ---------------------------- | +| action | queryNodeLogByDate | +| start | long,必须,起始日期 | +| end | long,非必须 | +| category | 非必须,不传入时查询全部情况 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1597376006441 + +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByDate&start=1596758400000&category=login +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByDate" +} +``` + +#### 节点日志-按偏移量查询 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------------ | --------------------------------------------- | +| action | queryNodeLogByOffset | +| count | long,必须,获取日志条数 | +| offset | long,非必须,若无offset,默认返回最新count条 | +| contractName | 字符串,非必须,合约名称 | + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=queryNodeLogByOffset&count=5 +``` + +##### 返回结果 + +```json +{ + "data": [ + { + "action": "listAllAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006438, + "key": "387355870552374748" + }, + { + "action": "listUnAuthRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006441, + "key": "4772693258708933626" + }, + { + "action": "countRole", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006444, + "key": "-6425375229108830572" + }, + { + "action": "loadNodeConfig", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006448, + "key": "-6602401010405792959" + }, + { + "action": "getPeerID", + "pubKey": "04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd", + "status": "accept", + "date": 1597376006449, + "key": "-7006776427870311552" + } + ], + "action": "onQueryNodeLogByOffset" +} +``` + +#### 节点日志-按时间段统计调用次数 + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------------------------------------- | +| action | countLogGroupByCategory | +| start | long,必须,起始时间 | +| end | 非必须,终止时间,默认为当前 | +| interval | long,非必须,统计间隔 | +| category | 非必须,action以逗号连接,不传入时统计全部调用情况 | + +其中,category中的action为NodePortal的接口的action集合。 +包括:ping、startContract、saveFile等。 + +##### 请求示例 + +``` +http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000 + +http://127.0.0.1:18000/SCIDE/CMManager?action=countNodeLogGroupByCategory&start=1596758400000&interval=86400000&category=ping,startContract +``` + +##### 返回结果 + +```json +{ + "start": 1596758400000, + "interval": 86400000, + "action": "onCountNodeLogGroupByCategory", + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 912, + 761 + ] +} +``` + + + + + +#### 输出历史记录日志 + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------ | +| action | printTimeTravelLog | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=printTimeTravelLog + +``` + +##### 返回结果示例 + +```json +{"status":false,"data":"[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/aa_1572335939893.dyjs\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n[CMActions] memory dir \u003d /Users/oliveds/docs/SmartContract/contractExamples/memoryDumps/.\n"} + +``` + + + + + +#### 输出节点转移日志 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 方法 + +GET + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | printTransferLog | + +##### 请求示例 + +``` +http://127.0.0.1:1717/SCIDE/SCManager?action=printTransferLog + +``` + +##### 返回结果示例 + +```json +{"status":false,"data":""} + +``` + + + +### 模板生成类 + + + + +## 账本Http接口 +``` {.yaml} +type: google.api.Service +config_version: 3 + +http: + rules: + - selector: bdware.bdledger.api.Node.ClientVersion + get: /v0/node/version + - selector: bdware.bdledger.api.Ledger.CreateLedger + post: /v0/ledgers + body: "*" + - selector: bdware.bdledger.api.Ledger.GetLedgers + get: /v0/ledgers + - selector: bdware.bdledger.api.Ledger.SendTransaction + post: /v0/ledgers/{ledger}/transactions + body: "*" + - selector: bdware.bdledger.api.Query.GetBlockByHash + get: /v0/ledgers/{ledger}/block + - selector: bdware.bdledger.api.Query.GetBlocks + post: /v0/ledgers/{ledger}/blocks/query + body: "*" + - selector: bdware.bdledger.api.Query.CountBlocks + post: /v0/ledgers/{ledger}/blocks/count + body: "*" + - selector: bdware.bdledger.api.Query.GetRecentBlocks + get: /v0/ledgers/{ledger}/blocks/recent + - selector: bdware.bdledger.api.Query.GetTransactionByHash + get: /v0/ledgers/{ledger}/transaction + - selector: bdware.bdledger.api.Query.GetTransactionByBlockHashAndIndex + get: /v0/ledgers/{ledger}/block/transaction + - selector: bdware.bdledger.api.Query.GetTransactions + post: /v0/ledgers/{ledger}/transactions/query + body: "*" + - selector: bdware.bdledger.api.Query.CountTransactions + post: /v0/ledgers/{ledger}/transactions/count + body: "*" +``` + +> **Note** +> +> Request/Response data of **bytes** type should/will be encoded with +> [Base64](https://tools.ietf.org/html/rfc4648#section-4). + +> **Note** +> +> When using hash strings in URL, they need to be encoded with +> [encodeURIComponent](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent). + +### 账本信息类 + +#### Node.ClientVersion {#_node_clientversion} + +Get BDLedger node version + + GET http://{{IP}}:{{PORT}}/v0/node/version + +##### 返回示例 + +``` {.json} +{ + "version": "dev-210119.a88bf4eb" +} +``` +#### Ledger.CreateLedger {#_ledger_createledger} + +Create a new ledger + + POST http://{{IP}}:{{PORT}}/v0/ledgers + +##### 请求示例 + +``` {.json} +{ + "name": "test" +} +``` + +##### 返回示例 + +``` {.json} +{ + "ok": true +} +``` + +#### Ledger.GetLedgers {#_ledger_getledgers} + +Get all ledgers + + GET http://{{IP}}:{{PORT}}/v0/ledgers + +##### 返回示例 + +``` {.json} +{ + "ledgers": [ + "default", + "test" + ] +} +``` + +#### Ledger.SendTransaction {#_ledger_sendtransaction} + +Send a new transaction + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions + +##### 请求示例 + +``` {.json} +{ + "transaction": { + "type": 0, + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": 52, + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +##### 返回示例 + +``` {.json} +{ + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" +} +``` + +### 查询类 + +#### Query.GetBlockByHash {#_query_getblockbyhash} + +Get a block identified by its hash + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block?hash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D + +**hash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +##### 返回示例 + +``` {.json} +{ + "block": { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } +} +``` + +#### Query.GetBlocks {#_query_getblocks} + +Get blocks in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/query + +``` {.protobuf} +enum IncludeTransactions { + NONE = 0; // Don't include transaction data + HASH = 1; // Include transactions hashes + FULL = 2; // Include full transactions +} +``` + +Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\] + +If only **end\_timestamp** is not specified, or +asciimath:\[\"end\_timestamp\"-\"start\_timestamp\"\>\"query.maxDuration\"\], +then **end\_timestamp** will be set to +asciimath:\[\"start\_timestamp\"+\"query.maxDuration\"\]. + +If only **start\_timestamp** is not specified, then **start\_timestamp** +will be set to asciimath:\[\"end\_timestamp\"-\"query.maxDuration\"\]. + +In all cases, **start\_timestamp** will never be earlier than the +genesis block's timestamp, and **end\_timestamp** will never be later +than the current timestamp when the node process the query request. + +##### 请求示例 +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 0 +} +``` + +##### 返回示例 + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +##### 请求示例2 + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 1 +} +``` + +##### 返回示例2 + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +**Request body 3.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 2 +} +``` + +**Response 3.** + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +#### Query.CountBlocks {#_query_countblocks} + +Count all blocks in a ledger, or blocks in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/count + +Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\] + +If neither **start\_timestamp** nor **end\_timestamp** is specified, +then count all blocks in the specified ledger. + +If only **end\_timestamp** is not specified, then count all blocks with +timestamps later than **start\_timestamp**. + +If only **start\_timestamp** is not specified, then count all blocks +with timestamps earlier than **end\_timestamp**. + +In all cases, **start\_timestamp** will never be earlier than the +genesis block's timestamp, and **end\_timestamp** will never be later +than the current timestamp when the node process the query request. + +##### 请求示例 + +``` {.json} +{} +``` + +##### 返回示例 + +``` {.json} +{ + "count": "5", + "startTimestamp": "0", + "endTimestamp": "1611039957" +} +``` + +##### 请求示例2 + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +##### 返回示例2 + +``` {.json} +{ + "count": "1", + "startTimestamp": "1611038000", + "endTimestamp": "1611039000" +} +``` + +#### Query.GetRecentBlocks {#_query_getrecentblocks} + +Get recent **count** blocks (Only support IncludeTransactions=NONE for +now) + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/recent?count=2 + +##### 返回示例 + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [] + }, + { + "hash": "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "3XkwkuMBearq8uavN76Te7Zdpl8=", + "8pZPR74OALIbps5XFb4dL/s0j0M=" + ], + "witnesses": [], + "timestamp": "1610968019", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "LuxttCm/pSHVMOKF0sJExk+DJXc=", + "transactions": [], + "transactionHashes": [] + } + ], + "startTimestamp": "1610968019", + "endTimestamp": "1611038043" +} +``` + +#### Query.GetTransactionByHash {#_query_gettransactionbyhash} + +Get a transaction identified by its hash + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/transaction?hash=VQBeA5Ee0Y5hqEileoQuYMHbOSE%3D + +**hash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +#### 返回示例 + +``` {.json} +{ + "transaction": { + "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "blockTimestamp": "1611038043", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +#### Query.GetTransactionByBlockHashAndIndex {#_query_gettransactionbyblockhashandindex} + +Get a transaction identified by hash of the block it belongs to and its +index inside the block + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block/transaction?blockHash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D&index=0 + +**blockHash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +#### 返回示例 + +``` {.json} +{ + "transaction": { + "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "blockTimestamp": "1611038043", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +#### Query.GetTransactions {#_query_gettransactions} + +Get transactions in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/query + +**start\_timestamp** and **end\_timestamp** follow the same requirements +and rules as in [???](#Query.GetBlocks). + +##### 请求示例 +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +##### 返回示例 + +``` {.json} +{ + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +#### Query.CountTransactions {#_query_counttransactions} + +Count all transactions in a ledger, or transactions in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/count + +**start\_timestamp** and **end\_timestamp** follow the same requirements +and rules as in [???](#Query.CountBlocks). + +##### 请求示例 + +``` {.json} +{} +``` + +##### 返回示例 + +``` {.json} +{ + "count": "4", + "startTimestamp": "0", + "endTimestamp": "1611039957" +} +``` + +##### 请求示例2 + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +##### 返回示例2 + +``` {.json} +{ + "count": "1", + "startTimestamp": "1611038000", + "endTimestamp": "1611039000" +} +``` + + +- - - + +## 合约节点WebSocket接口 + +### 用户管理类 + +#### 获取Session + +登录前获取session以便进行签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | getSessionID | + +##### 请求示例 + +``` +var req = {}; +req.action = "getSessionID"; +wssocket.send(JSON.stringify(req)); +``` + + +##### 返回结果 + +```json +{ + "action": "onSessionID", + "session": "9782323_session" +} +``` + +#### 用户登录 + +用户进行公私钥身份验证 + +##### 参数 + +| 字段 | 值 | +| ------ | ----- | +| action | login | + +##### 请求示例 + +``` +var loginParam = {}; +loginParam.pubKey = global.sm2Key.publicKey; +loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); +loginParam.action = "login"; +wssocket.send(JSON.stringify(loginParam)); +``` + +##### 返回结果 + +```json +{ + "action": "onLogin", + "data": "NodeManager,ContractProvider" +} +``` + +#### 申请角色 + +在节点管理员界面申请可以申请称为合约管理员(ContractInstanceManager)、合约使用者(ContractUser)、合约提供者(ContractProvider) + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | applyNodeRole | +|role|申请角色名称| + +##### 请求示例 + +``` +var param = {}; +param.action = "applyNodeRole"; +param.role = "ContractUser"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +``` json +{ + "action": "onApplyRole", + "data": "success" +} + +{ + "action":"onApplyRole", + "data":"already has!" +} +``` + +#### 授权角色 + +##### 参数 + +| 字段 | 值 | +| -------- | -------------------- | +| action | authNodeRole | +| isAccept | bool类型,表示否授权 | +| pubKey | 授权用户公钥 | + + +##### 请求示例 + +``` +var param = {}; +param.action = "authNodeRole"; +param.isAccept = true; +param.pubKey = "xxxxx"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onAuthNodeRole", + "data": "success" +} +``` + +#### 删除用户角色 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------- | +| action | deleteRole | +| role | 删除角色名称 | + +##### 请求示例 + +``` +var deleteInfo = {}; +deleteInfo.pubKey = global.authorizedUsers.[publicKey]; +deleteInfo.action = "deleteRole"; +deleteInfo.role="ContractUser"; +wssocket.send(JSON.stringify(deleteInfo)); +``` + +##### 返回结果 + +```json +{ + "action": "onDeleteRole", + "data": "success" +} +``` + +#### 查看授权用户列表 + +查看准入管理员当前组网中已经授权的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | listAllAuthRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "listAllAuthRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onListAllAuthRole", + "data": + { + "kv":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"NodeManager,ContractProvider,ContractUser,ContractInstanceManager"}], + "time":[{"key":"04eafad549d0757cf67f360815e15e157c7428c9ea9fb933f31a5d45bfb6edd9809c5bf6a5f37d7b817207f19fb2d76b7dbdefe38084cd3282e37b9ac39959dfab", + "value":"1617178709933"}] + } +} +``` + +#### 查看申请用户列表 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | listUnAuthRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "listUnAuthRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onListUnAuthRole", + "kv": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "ContractProvider,ContractUser" + }], + "time": [{ + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": "1587398989914" + }] +} +``` + + +##### 参数(删除) + +| 字段 | 值 | +| ------ | ------------- | +| action | queryUserStat | + +##### 请求示例 + +``` +var param = {}; +param.action = "queryUserStat"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 +} +``` + +### 合约代码管理类 + +#### 获取公共合约文件列表 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | listProjects | + +##### 请求示例 + +``` +var request = {}; +request.action = "listProjects"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\",\"BiddingExample\",\"ContractExecutor\"]", + "executeTime":0, + "isPrivate":false +} + +``` + + +#### 获取私有合约文件列表 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listProjects | +| pubKey | 该用户的公钥 | +|isPrivate|true| + +##### 请求示例 + +```javascript +var request = {}; +request.action = "listProjects"; +request.pubKey = "global.sm2.publicKey"; +request.isPrivate=true; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` + + +#### 获取合约实例 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +``` +var request = {}; +request.action = "listContractProcess"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onListContractProcess", + "data":"[{\"id\": \"1658407837\",\"name\": \"BDCoin\",\"port\": \"1617\"}]" +} +``` + + +#### 启动合约 + +##### 参数 + +| 字段 | 值 | +| --------- | ------------- | +| action | startContract | +| owner | pubkey | +| requestID | 当前时间 | +| script | 脚本内容 | +| signature | 签名 | + +##### 请求示例 + +``` +request.action = "startContract"; +request.owner = global.sm2Key.publicKey; +request.requestID = new Date().getTime() + ""; +request.script = global.projectScript; +request.signature = sm2.doSignature("Algorithm|" + request.script + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":\"\",\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStartContract", + "cid":"-506393888", + "executeTime":2496, + "responseID":"1617206735696" +} +``` + +#### 启动可信集群合约 + +##### 参数 + +| 字段 | 值 | +| --------- | ------------------------------------ | +| action | startContractP2PTrustfully | +| owner | pubkey | +| isPrivate | 当前时间 | +| path | 脚本所在路径 | +| signature | 签名 | +| peersID | 可信执行集群中的节点peerID组成的数组 | +| | | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "startContractP2PTrustfully"; +request.peersID = ["3r729hf2ehf982","sjdfiwoehfwoi34","wnfnwoeifnwenef"]; +var project = "JsonTest"; +request.path = "/" + project + "/mainfest.json"; +request.isPrivate = false; +request.signature = sm2.doSignature("Trusted|" + request.path + "|" ++ global.sm2Key.publicKey, global.sm2Key.privateKey); //合约的签名 +request.resultcheck = $("#resultcheck")[0].value; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"{\"status\":\"Success\",\"result\":\"\"}", + "action":"onStartContractP2PTrustfully", + "cid":"-1543583350", + "executeTime":1544 +} +``` + +#### 分发合约项目 + +##### 参数 + +| 字段 | 值 | +| ------------- | ------------------ | +| action | distributeContract | +| peersID | 集群中节点peer | +| projectName | 合约名 | +| isPrivate | 是否在私有目录 | +| sponsorPeerID | 发起者ID | +| signature | 签名 | + +##### 请求示例 + +```javascript +request.action = "distributeContract"; +request.peersID = peersID; +request.projectName = global.projects[global.lastClickedProjectId]; +request.isPrivate = $("#privateDir-tab").hasClass("active"); +request.sponsorPeerID = global.peerID; +request.signature = sm2.doSignature("DistributeContract|" + request.projectName + "|" + global.sm2Key.publicKey, global.sm2Key.privateKey); +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onDistributeContract", + "progress":"100.00%" +} +``` + +#### 终止合约 + +##### 参数 + +| 字段 | 值 | +| --------- | ------------------- | +| action | killContractProcess | +| id | 合约id | +| requestID | 请求ID | + +##### 请求示例 + +``` +request.action = "killContractProcess"; +request.id = contractid; +request.requestID = new Date().getTime() + ""; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data": "ContractHandler: exit in 3 seconds!", + "action": "onOutputStream" +} +``` + +#### 终止所有合约 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | killAllContract | + +##### 请求示例 + +``` +request.action = "killAllContract"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "status":false, + "action":"onKillAllContract", + "data":"Kill:7241,7245," +} +``` + + + +#### 静态分析合约 + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------- | +| action | staticVerifyContract | +| owner | 用户私钥 | +| isPartial | 是否是部分 | +| contractid | contractid | +| script | 脚本内容 | +| path | 合约文件名 | + + +##### 请求示例 + +```javascript +request.action = "staticVerifyContract"; +request.owner = global.sm2Key.privateKey +request.isPartial = false; +request.contractid = contractid; +request.script = global.projectScript; +request.path = global.projectName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json + +{ + "data":"{\"needSeq\":false,\"seq\":0,\"status\":\"Success\",\"result\":{\"hello\":\"Ret:\"},\"isInsnLimit\":false,\"totalGas\":0,\"executionGas\":0,\"extraGas\":0,\"size\":0,\"eventRelated\":false}", + "action":"onStaticVerifyResult", + "cid":"verify", + "executeTime":83 +} +``` + + + +#### 删除合约 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------- | +| action | deleteFile | +| file | fileName | + +##### 请求示例 + +```javascript +request.action = "deleteFile"; +request.file = fileName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onDeleteFile", + "data":"success", + "executeTime":0 +} +``` + + + +#### 私有合约传至公共目录 + +##### 参数 + +| 字段 | 值 | +| -------- | ------------ | +| action | changePublic | +| pubkey | 用户公钥 | +| fileName | fileName | + +##### 请求示例 + +```javascript +request.action = "changePublic"; +request.pubkey = pubkey; +request.fileName = fileName; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onChangePublic", + "data":"success", + "executeTime":0 +} +``` + + + +#### 上传合约 + +##### 参数 + +| 字段 | 值 | +| -------- | ----------- | +| action | UploadFile | +| isAppend | false | +|fileName|fileName| +| path | path | +|isPrivate|true/false| +| content | fileContent(base64编码) | + +##### 请求示例 + +``` +request.action = "uploadFile"; +request.isAppend = false; +request.fileName = "test1.yjs"; +request.path = "test1"; +text="Y29udHJhY3QgdGVzdDF7CglleHBvcnQgZnVuY3Rpb24gaGVsbG8oYXJnKXsgCiAgICAgICAgcmV0dXJuICJ3b3JsZCI7ICAKICAgIH0gICAKfQ==" +request.content = text; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "action":"onUploadFile", + "data":"success", + "executeTime":0 +} +``` + +#### 编译合约 + +##### 参数 + +| 字段 | 值 | +| ---------- | -------------------------- | +| action | compile | +| path | string, 待编译的项目名称 | +| privateTab | bool, 是否为私有目录的项目 | + +##### 请求示例 + +```javascript +var req = {"action":"compile","path":"Hello","privateTab":true} +``` + +##### 返回结果 + +```json +{"result":"Hello_2020-08-17-09:09:40.ypk","action":"onCompile"} +``` + +#### 锁定私有目录 + +锁定某个用户的的私有目录编辑功能 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | lockEdit | +| pubKey | string, 要被锁定的公钥 | + +##### 请求示例 + +```javascript +var req = {}; +req.action = "lockEdit"; +req.pubKey = "xxxxxx"; +wssocket.send(JSON.stringify(req)); +``` +```json +{ + "action":"onLockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" +} +``` + + +#### 解锁私有目录 + +解锁某个用户的的私有目录编辑功能 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | unLockEdit | +| pubKey | string, 要被锁定的公钥 | + +##### 请求示例 + +```javascript +var req = {}; +req.action = unlockEdit; +req.pubKey = "xxxxxx"; +wssocket.send(JSON.stringify(req)); +``` +```json +{ + "action":"onUnlockEdit", + "status":"success", + "data":"04c4c855862b53f323e077ccfcc744ecc2c0a04645ed16d99ede8fd5866b38c0670a97ad22c6260d1a4672aba2a5fe229a2d4eba34627c054aab102620afa288c1" +} +``` + + +### 合约实例管理类 + +#### 查询合约进程 + +向服务器发送请求, 查询服务器上已经启动的所有合约进程. + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------- | +| action | listContractProcess | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "listContractProcess"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "action": "onListContractProcess", + "data": "[...]" +} +``` + + + +#### 调用合约 + +向服务器发送请求, 调用某个合约. + +##### 参数 + +| 字段 | 值 | +| -------------------- | --------------------------- | +| action | executeContract | +| contractID | 合约ID | +| withDynamicAnalysis | true/false 是否进行动态分析,可选 | +| operation | 调用合约的方法名 | +| arg | 调用合约的参数 | +| pubkey | 调用者公钥,可选 | +| signature | 调用者签名 ,可选 | + +`*`表示可选参数 + +```javascript +//sm2 可从sm2.js中加载获得。 +signature = sm2.doSignature(contractID+"|"+operation+"|"+arg+"|"+pubkey,privateKey); +``` + +##### 请求示例 + +```javascript +var request = {}; +request.action = "executeContract"; +request.contractID = "2073401446"; +request.operation = "main"; +request.arg = "hhhhh"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "needSeq":false, + "seq":0, + "status":"Success", + "result":"world", + "isInsnLimit":false, + "totalGas":0, + "executionGas":0, + "extraGas":0, + "size":0, + "eventRelated":false, + "responseID":"1617211077264_223", + "action":"onExecuteResult", + "executeTime":"5" +} +``` + +#### 输出历史记录日志(删除) + +向服务器发送请求, 获取节点服务器上合约的TimeTravel日志. + +##### 参数 + +| 字段 | 值 | +| ------ | ------------------ | +| action | printTimeTravelLog | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "printTimeTravelLog"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "status": false, + "data": "[CMActions] dumpContract :…t/contractExamples/memoryDumps/LicenceManager\n" +} +``` + + + +#### 输出节点转移日志(删除) + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | printTransferLog | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "printTransferLog"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json + { + "status": false, + "data": "" +} +``` + + + +#### 合约状态迁移 + +向服务器发送请求, 获取节点服务器的状态转移日志. + +##### 参数 + +| 字段 | 值 | +| ------------ | ------------ | +| action | loadMemory | +| contractName | 合约名称 | +| memoryFile | 合约文件名称 | + +##### 请求示例 + +```javascript +var request = {}; +request.action = "loadMemory"; +request.contractName = "JsonContract"; +request.memoryFile = "2020-03-17.20/42/55"; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果示例 + +```json +{ + "data":"success", + "size":"0.00 B", + "action":"onTransferTo", + "time":"0.01s" +} +``` + + + +### 日志查看类 + +#### 查看本地近n日节点日志(删除) + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------- | +| action | listLocalNodeLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalNodeLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" +} +``` + + + +#### 查看本地近n日合约日志(删除) + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listLocalContractLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalContractLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7ba358d9234939623ab51ea94ca685e6a1f36ed81fd9630ccba6473e632f163bb30faffd4c91f21e5bace20101d6d6e36c04ac67eea14cc24b4962b84f57\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" +} +``` + + + + +### 节点配置类 + +#### 获取节点配置信息 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | loadNodeConfig | + +##### 请求示例 + +``` +var param = {}; +param.action = "loadNodeConfig"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +``` +{ + "status": true, + "action": "onLoadNodeConfig", + "data": { + "nodeName": "04BF52213343C147E631B877BCEB17B794230EE551E85F58FA429C4BA03D690778CC384C6916C63DF36CB9E35C7E274FDB4E18491DFE3D611D347856D441CACC5AF9090B515F02AFC2DFBF56461EC83B5A4CD342466360D6CF82E6E40B637430AC4A329CCBC798DAF7D526AF9E3B3600E0BEA1BFAB8C160EF90128FAF67B19E45F37664F1E4B", + "licence": "04AADCC7103CD02626D228AFFBEF53F8242ECA4DDD6F179D30B622440666715CFBB6FD1D3678A2B25812DEA9917073E79A65F7ADE517F784DC76288EFCEB37ECAA1025E6903540702F729DA1C2ECCD93F4E6FAFCE40DF443E7FD74387169D0C6D927C7BB12882D0471C8D3E6F31B0316A42FC38F6DD9978D4351B23B2AD63E2244909E98F51185D32CB99B4AE4E22D3AB4C04027BB", + "expireTime": "Wed Aug 26 09:43:08 CST 2020", + "nodes": "[\"node1\",\"node2\",\"node3\"]", + "yjsPath": "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar", + "nodeCenter": "ws://127.0.0.1:1719/SCIDE/NodeCenter" + } +} + +{ + "status":true, + "action":"onLoadNodeConfig", + "data":{ + "nodeName":"Node_180", + "peerID":"", + "masterAddress":"39.104.201.40:21031", + "licence":"04AADCC7103C", + "doipConfig":"{\\"LHSProxyAddress\\":\\"http://39.104.201.40:21042/\\",\\"ownerHandle\\":\\"86.5000.470/dou.TEST\\",\\"certPath\\":\\"keys/dou.TEST.keystore\\",\\"certPassword\\":\\"123456\\",\\"repoID\\":\\"86.5000.470/doip.vcg9Mu1gSq_bdw\\",\\"listeners\\":\\"[{\\\\\\"url\\\\\\":\\\\\\"tcp://39.104.201.40:21032\\\\\\",\\\\\\"protocolVersion\\\\\\":\\\\\\"2.1\\\\\\",\\\\\\"messageFormat\\\\\\":\\\\\\"packet\\\\\\"}]\\",\\"serviceDescription\\":\\"test local Contract Repository\\",\\"serviceName\\":\\"ContractEngine021\\"}", + "clusterConnected":"false", + "nodePubKey":"0492d974b8a5b473d0ed2c81800917f76e2a1ec3666067888c85fe6922a672223f2083f95402ae13a744df58deabbe7206c4a317dd14296b0d3941a26ca4e34dc5", + "ipPort":"", + "bdledger":"39.108.56.240:18091,39.108.56.12:1809139.104.70.160:18091 47.98.247.70:18091 47.98.248.208:18091 39.104.77.165:18091 47.98.249.131:18091", + "yjsPath":"/data/bdwaas/bdcontract/yjs.jar", + "nodeCenter":"ws://39.104.201.21040/SCIDE/NodeCenter" + } +} +``` + + +#### 修改节点配置 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | updateConfig | +| key | 要改的配置项 | +| val | 要更改的目标值 | + +其中,key的可选项包括: + +| key的示 | val示例 | 说明 | +| ------------- | ----------------------------------- | ------------------------------- | +| yjsPath | /User/xxx/cp/yjs.jar | 合约进程启动所需的jar | +| dataChain | 192.168.1.8:18090,182.173.2.3:18091 | 账本节点的ip与端口 | +| nodeCenter | ws://127.0.0.1:18002 | CenterPortal所在的ip/端口 | +| nodeName | Node_180 | 字符串类型 | +| masterAddress | 192.168.3.2:18001 | 该NodePortal节点的ip和的TCP端口 | + +其中NodePortal的TCP端口为Node的http/ws端口号+1。 + + +#### 修改节点名称 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | changeNodeName | +| data | 新的节点名称 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeNodeName"; +param.data = "NewNodeName"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeNodeName", + "data": true +} +``` + + + +#### 修改节点YJS路径 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------- | +| action | changeYJSPath | +| data | 节点服务器yjs.jar路径 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeYJSPath"; +param.data = "/Users/xxx/docs/BDWareHttp/generatedlib/yjs.jar"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeYJSPath", + "data": true +} +``` + + + +#### 修改NodeCenter + +##### 参数 + +| 字段 | 值 | +| ------ | ----------------------------------------- | +| action | changeNodeCenter | +| data | 节点服务器要连接的NodeCenterWebSocket路径 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeNodeCenter"; +param.data = "ws://127.0.0.1:1719/SCIDE/NodeCenter"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeNodeCenter", + "data": true +} +``` + + + +#### 修改账本节点 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------------------- | +| action | changeBDledger | +| data | 数链节点的IP:port,用","隔开 | + +##### 请求示例 + +``` +var param = {}; +param.action = "changeBDledger"; +param.data = "39.108.56.240:18091,39.108.56.12:18091"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onChangeBDledger", + "data": true +} +``` + + + +#### 上传节点Licence + +##### 参数 + +| 字段 | 值 | +| ------ | ----------------------- | +| action | uploadLicence | +| data | 节点服务器的Licence内容 | + +##### 请求示例 + +``` +var param = {}; +param.action = "uploadLicence"; +param.data = "04AADCC7103C"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onUploadLicence", + "data": true +} +``` + + + +#### 获取节点ID + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | getNodeID | + +##### 请求示例 + +``` +var param = {}; +param.action = "getNodeID"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "status": true, + "action": "onGetNodeID", + "data": "0431…d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d" +} +``` + + + +#### 获取节点所在的可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ---------- | ------------------------------------------------ | +| action | getNodeTrustUnits | +| data | 节点ID | +| msgHandler | 收到回复的回调函数, 可使用"建立连接"的msgHandler | +| ws | 节点所属的NodeCenter的WebSocket地址 | + +##### 请求示例 + +``` +centerportalws = createWssocket("ws://127.0.0.1:1718/NodeCenterWS",function() { +var param = {}; +param.action = "getNodeTrustUnits"; +param.data = "0431e311bd70840fe69965e2cabea97fafe99f2133953c01abb9bd7cb62af42f8283f474d203051e920d3a92e1184bbc5817ebda5c2ad498e4ff1d240009b4f06d"; +centerportalws.send(JSON.stringify(param)); +}, msgHandler); +``` + +##### 返回结果 + +```json +{ + "data": [{ + "key": "0475c7b061...65e55_4063665700873624164", + "value": "[\"04541429c11b094…40009b4f06d\"]" + }], + "action": "onGetNodeTrustUnits" +} +``` + +### 模板生成类 + +#### 获取合约模板列表 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | getTemplateList | + +##### 请求示例 + +``` javascript +req={}; +req.action = "getTemplateList"; +wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 + +``` json +{ + "data": [ + { + "formDesc": { + "dbPWD": { + "label": "密码", + "type": "input" + }, + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + }, + "dbUserName": { + "label": "用户名", + "type": "input" + }, + "fieldList": { + "label": "字段名", + "type": "tag" + }, + "dbUrl": { + "label": "数据库链接", + "type": "input" + }, + "tableName": { + "label": "表名", + "type": "input" + } + }, + "apiName": "generateMySQLProject" + }, + { + "formDesc": { + "contractName": { + "label": "合约名称", + "type": "input" + }, + "accessPolicy": { + "label": "访问控制策略", + "type": "input", + "option": [ + { + "text": "无访问控制", + "value": "NAC" + }, + { + "text": "直接访问控制", + "value": "DAC" + }, + { + "text": "基于角色的访问控制", + "value": "RBAC" + } + ] + } + }, + "apiName": "generateEmptyProject" + } + ], + "action": "onTemplateList" +} +``` + +#### 空白合约模板 + +##### 参数 + +| 字段 | 值 | +| ------------ | ----------------------------- | +| action | generateEmptyProject | +| contractName | 字符串类型,合约名称 | +| isPrivate | 布尔类型,是否为私有项目 | +| accessPolicy | 若为"DAC",则实现直接访问控制 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "Empty22"; +req.action = "generateEmptyProject"; +req.accessPolicy = "DAC"; +//wssocket为建立好的连接 +wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"AnnotationSample\",\"AppDataAnalysis\",\"AppDataSource\"]", + "executeTime":0, + "isPrivate":false +} +``` + +#### MySQL接入合约 + +##### 参数 + +| 字段 | 值 | +| ------------- | ------------------------------------------------------ | +| action | generateMySQLProject | +| contractName | 字符串类型,合约名称 | +| isPrivate | 布尔类型,是否为私有项目 | +| dbUrl | 字符串类型,数据库的URI | +| dbUserName | 字符串类型,数据库的用户名 | +| dbPWD | 字符串类型,数据库密码 | +| accessPolicy | 若为"DAC",则实现直接访问控制,若为"NAC"则没有访问控制 | +| tableName | 字符串类型,数据库的表名 | +| fieldList | 字符串列表,数据库的字段列表 | +| defaultAccept | 布尔值,表示申请时是否默认有权 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "MySQLFromTemplate"; +req.action = "generateMySQLProject"; +req.pubKey = global.sm2Key.publicKey; +req.isPrivate = true; +req.tableName = "data"; +req.dbUrl = "jdbc:mysql://xxx:xxx/xxx"; +req.dbUserName = "loushuai"; +req.dbPWD = "loushuai"; +req.fieldList = [{"name":"名字","code":"*"}]; +req.basicInfo={"type":"所属分类","name":"资源名称"}; +req.accessPolicy = "DAC"; +req.defaultAccept = true; +//global.wssocket为建立好的连接 +global.wssocket.send(JSON.stringify(req)); +``` + +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` +#### CSV接入合约 + +##### 参数 + +| 字段 | 值 | +| ----------------- | ------------------------------------------------------ | +| action | generateCSVProject | +| contractName | 字符串类型,合约名称 | +| base64EncodedData | 字符串类型,通过base64编码后的CSV文件内容 | +| isPrivate | 可选字段,布尔类型,是否为私有项目 | +| accessPolicy | 若为"DAC",则实现直接访问控制,若为"NAC"则没有访问控制 | +| defaultAccept | 可选字段,布尔值,表示申请时是否默认有权 | + +##### 请求示例 + +```javascript +var req = {}; +req.contractName = "CSVFromTemplate"; +req.action = "generateCSVProject"; +req.pubKey = global.sm2Key.publicKey; +req.isPrivate = true; +req.tableName = "data"; +req.accessPolicy = "DAC"; +req.defaultAccept = true; +req.base64EncodedData = "bmFtZSwgc2NvcmUsCmphY2ssIDkwLApsdWN5LCA5MQo="; +//global.wssocket为建立好的连接 +global.wssocket.send(JSON.stringify(req)); +``` +##### 返回结果 +```json +{ + "action":"onListProjects", + "data":"[\"CSVFromTemplate\",\"Empty22\",\"Hello\",\"MySQLFromTemplate\",\"test\"]", + "executeTime":0, + "isPrivate":true +} +``` + +- - - + +## 路由节点WebSocket接口 + +### 用户管理类 + +#### 获取Session + +登录前获取session以便进行签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | getSessionID | + +##### 请求示例 + +``` +var req = {}; +req.action = "getSessionID"; +wssocket.send(JSON.stringify(req)); +``` + + +##### 返回结果 + +```json +{ + "action": "onSessionID", + "session": "9782323_session" +} +``` + + +#### 用户登录 + +用户进行公私钥身份验证,需先调用"getSessionID"获取sessionID以便于签名。 + +##### 参数 + +| 字段 | 值 | +| ------ | ----- | +| action | login | + +##### 请求示例 + +``` +var loginParam = {}; +loginParam.pubKey = global.sm2Key.publicKey; +loginParam.signature = sm2.doSignature(global.session, + global.sm2Key.privateKey); +loginParam.action = "login"; +wssocket.send(JSON.stringify(loginParam)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onLogin", + "data": "CenterManager" +} +``` + + + +#### 用户获取当前角色(删除) + +用户根据登录时的公钥获取对应的角色,如果是第一次登录则此时的公钥默认称为准入管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | ------- | +| action | getRole | + +##### 请求示例 + +``` +var param = {}; +param.action = "getRole"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onGetRole", + "data": "CenterManager" +} +``` + +#### 申请角色 + +在准入管理员界面可以申请称为组网中某个节点的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | applyRole | +|role|申请的角色名称| + +##### 请求示例 + +``` +var param = {}; +param.action = "applyRole"; +param.role=" +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onApplyRole", + "data": "failed" +} +``` + + +#### 添加节点 + +##### 参数 + +| 字段 | 值 | +| ---------- | ---------------- | +| action | addNode | +| nodePubKey | 要添加的节点公钥 | + +#### 请求示例 + +``` +var req = {}; +//某节点的publicKey可通过连接该节点,并通过"获取节点配置信息"接口获取 +req.nodePubKey = publicKey; +req.action = "addNode"; +wssocket.send(JSON.stringify(req)); +``` + + +#### 删除用户角色 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | delete | +| pubKey | 对应用户的公钥 | + +##### 请求示例 + +``` +var deleteInfo = {}; +deleteInfo.pubKey = user.publicKey; +deleteInfo.action = "delete"; +wssocket.send(JSON.stringify(deleteInfo)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onDelete", + "data": "success" +} +``` + +#### 查看授权用户列表 + +查看准入管理员当前组网中已经授权的节点管理员 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------ | +| action | listAllUsers | + +##### 请求示例 + +``` +var param = {}; +param.action = "onListAllUsers"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onListAllUsers", + "kv": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": " NodeManager" + }, + "time": { + "key": "049999ebd14ff3b96ebf7f7325e1da94a1c4c376573a1dc1cec2b4f7a3b09ed7b07252134e93b6ac2e1853268b82f4b541d34fb42b0182cd61043e99d3489e2cf7", + "value": 1587398989914 + } +} +``` + +#### 查看申请用户列表 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | listApplyList | + +##### 请求示例 + +``` +var param = {}; +param.action = "onListApplyList"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onListApplyList", + "kv": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": " NodeManager" + }, + "time": { + "key": "04b00f32eab70c78d1b43738f190d326d36c021af2124acefe6d057016b11ea31c750bb473e565c9d89e4993a44f4d30adf447d3026a21ff4b3b64cef523074ef7", + "value": 1587398989914 + } +} +``` + +#### 查看用户类型分布 + +##### 参数 + +| 字段 | 值 | +| ------ | ------------- | +| action | queryUserStat | + +##### 请求示例 + +``` +var param = {}; +param.action = "onQueryUserStat"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果示例 + +```json +{ + "action": "onQueryUserStat", + "userListCount": 3, + "applyListCount":0 +} +``` + +### 节点管理类 + +#### 查看节点列表 + +查看该用户有权限查看的节点列表(仅准入管理员及合约管理者可用) + +##### 参数 + +| 字段 | 值 | +| ------ | --------- | +| action | listNodes | + +##### 请求示例 + +``` +var param = {}; +param.action = "listNodes"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "offline": [{ + "key": "0431e31...40009b4f06d", + "value": "0431e311bd708...b4f06d" + }], + "action": "onListNodes", + "online": [{ + "contracts": [], + "pubKey": "0431e311...09b4f06d", + "nodeName": "NewNodeName", + "udpID": "528822126", + "cimanager": "" + }] +} +``` + + +#### 查看可信执行集群列表 + +查看该用户有权限查看的节点列表(仅中心管理员及合约管理者可用) + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | listTrustUnits | + +##### 请求示例 + +``` +var param = {}; +param.action = "listTrustUnits"; +wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "data": [{ + "key": "0470b2f27f4f6…1cb855f1ecec11", + "value": "[...]" + }], + "action": "onListTrustUnits" +} +``` + + +#### 建立可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ------ | ---------------------- | +| action | createTrustUnit | +| data | 节点公钥组成的Json数组 | +| Msg | 集群名称 | + +##### 请求示例 + +``` +var param = {}; +param.action = "createTrustUnit"; +param.data = "[\"382r0934309t...\",\"345343rr3f34...\"]"; +param.msg = "newUnit1"; +global.wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onCreateTrustUnit", + "status": "Success" +} +``` + + +#### 删除可信执行集群 + +##### 参数 + +| 字段 | 值 | +| ------ | --------------- | +| action | deleteTrustUnit | +| data | 可信执行集群ID | + +##### 请求示例 + +``` +var param = {}; +param.action = "deleteTrustUnit"; +param.data = "0475d34rf3434..._1583410158761"; +global.wssocket.send(JSON.stringify(param)); +``` + +##### 返回结果 + +```json +{ + "action": "onDeleteTrustUnit", + "status": "Success" +} +``` + + + +### 日志查看类 + +#### 查看组网管理操作的统计 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------- | +| action | queryActionLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "onQueryActionLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ "action":"onQueryActionLog", + "data":"[{\"action\":\"login\",\"pubKey\":\"null\",\"status\":\"accept\",\"date\":1583139323822}\",]" +} +``` + + + +#### 查看本地近n日合约日志 + +##### 参数 + +| 字段 | 值 | +| ------ | -------------------- | +| action | listLocalContractLog | +| date | 当前时间 | + +##### 请求示例 + +``` +request.action = "listLocalContractLog"; +request.date = new Date().getTime() - 24 * 3600 * 1000 * n; +wssocket.send(JSON.stringify(request)); +``` + +##### 返回结果 + +```json +{ + "data":"[\"{\"action\":\"startContract\",\"pubKey\":\"04405d7b...\",\"contractID\":\"845581788\",\"contractName\":\"null\",\"date\":1583141525539}\"]" +} +``` + + +- - - + +## Bash接口 + +已废弃。可使用BDWareConfigTool代替。 +通过命令行发送Socket指令, 执行调用`ContractController`类中方法, 完成以下功能. (需要在本机的`1615`端口运行`ContractManager`实例) + +![Bash接口功能示意图](./_static/imgs/bash-api.png) + +### 指令 + +```bash +java -jar yjs.jar function_name arguments + +``` + +`function_name`为调用的方法名; + +`arguments`为方法参数. + +### 启动合约 + +#### 参数 + +`function_name`为`startContract`; + +`arguments`为启动合约需要的参数, 包括合约类型`type`, 合约ID`id`, 合约脚本`script`. + +#### 指令示例 + +```bash +java -jar yjs.jar startContract "{\"type\":\"Algorigthm\",\"id\":\"656565\",\"script\":\"contract c{function main(arg){return arg/1.0+1;}}\"}" +``` + +### 调用合约 + +#### 参数 + +`function_name`为`executeContract`; + +`arguments`为调用合约需要的参数, 包括调用参数`arg`, 合约ID`contractID`. + +#### 指令示例 + +```bash +java -jar yjs.jar executeContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" +``` + +### 停止合约 + +#### 参数 + +`function_name`为`stopContract`; + +`arguments`为调用合约需要的参数, 即合约ID`contractID`. + +#### 指令示例 + +```bash +java -jar yjs.jar stopContract "{\"arg\":\"http://www.baidu.com\",\"contractID\":\"656564\"}" +``` + +### 停止全部合约 + +#### 参数 + +`function_name`为`stopAllContracts`. + +#### 指令示例 + +```bash +java -jar yjs.jar stopAllContracts +``` + +### 查询全部合约 + +#### 参数 + +`function_name`为`listContracts`. + +#### 指令示例 + +```bash +java -jar yjs.jar listContracts +``` + \ No newline at end of file diff --git a/source/markdown_BDWare/IDEUsage.md b/source/markdown_BDWare/IDEUsage.md new file mode 100644 index 0000000..34de595 --- /dev/null +++ b/source/markdown_BDWare/IDEUsage.md @@ -0,0 +1,439 @@ +# 管理界面 + +- - - + +## 合约节点管理界面 + +该界面的使用地址为:[NodePortal.html](/NodePortal.html) + + +### 用户管理菜单 +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +#### 概览 +![nodeUserManager](./_static/imgs/nodeUserManager.jpg) +节点用户管理页面一共有四个模块:用户情况、用户活跃统计、授权用户管理、未授权用户管理。 + +#### 用户类型分布 +主要统计当前节点管理员所拥有的四种角色的数量:合约提供者、合约管理员、合约使用者 +![userList](./_static/imgs/userList.jpg) + +#### 用户活跃统计 +![userActive](./_static/imgs/userActive.jpg) +统计30天之内**登录**、**授权**、**申请**的次数 + +#### 当前用户信息 +![nodeInfo](./_static/imgs/nodeInfo.jpg) + * 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录节点管理员界面,可以将自己的公私钥复制到这个文本框中。 + * 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到节点管理员本地 + * 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是还没有在中心管理员认证的节点则默认为**Anonymous** + * 如果不是节点管理员,想要加入某个中心管理员的网络,那么要在中心管理员所在的用户管理中用自己的公私钥导入后进行认证。 + * 如果想要行使更多关于合约的操作,则需要认证不同的角色:合约管理员、合约使用者、合约提供者,然后进行**角色认证** + +#### 授权与非授权用户列表 +![roleAuth](./_static/imgs/roleAuth.jpg) + 在节点管理员认证角色之后,节点管理员登录会在**未授权角色管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以。 + 授权之后将在**授权角色管理**表格中看见授权后的节点列表。如果节点管理员想要移除某个节点的角色,则在授权角色管理列表中**删除**即可。 + +### 合约代码管理菜单 + +![codeManageMenu](./_static/imgs/codeManageMenu.png) + + + +#### 合约文件 + +![codeManage1](./_static/imgs/codeManage1.png) + +在合约代码管理菜单中,用户可以看到公共合约以及个人私有合约。 +![codeManage1-1](./_static/imgs/codeManage1-1.png) + +对于公共合约,节点管理员可以对其中文件进行删除和上传操作,可以对合约项目进行下载和删除操作。 +![codeManage1-2](./_static/imgs/codeManage1-2.png) + +对于私有合约,合约提供者可以对其中文件进行删除和上传操作,可以对合约项目进行下载、删除和传至公共合约目录操作。 + +以下是对合约文件进行操作的示例。 + +#### 上传文件 +![codeManage6](./_static/imgs/codeManage6.png) + +#### 删除 +![codeManage5](./_static/imgs/codeManage5.png) + +#### 传至公共 +![codeManage7](./_static/imgs/codeManage7.png) + +#### 下拉框 + +![codeManage2](./_static/imgs/codeManage2.png) + +四个下拉框中,可以分别对合约状态保存模式、已启动合约实例、节点所在集群以及结果校验方式进行选择。 + + + +#### 按钮操作 + +![codeManage3](./_static/imgs/codeManage3.png) + +#### 启动 + +在文件列表中选择合约文件之后,在合约运行模式中选择“单节点执行”,点击启动按钮,会启动指定文件,并在结果显示框中显示返回结果。 + + + +#### 启动P2P集群合约 + +在文件列表中选择合约文件之后,在合约运行模式中选择该可信合约运行的合约集群,点击启动按钮,会在该集群的所有节点上启动指定文件,并在结果显示框中显示返回结果。 + + + +#### 启动全部 + +在合约运行模式中选择“单节点执行”,点击启动全部按钮,会启动合约文件列表中所有合约。 + + + +#### 停止P2P集群合约 + +在已启动合约实例的下拉框中选择一个合约实例,在合约运行模式中选择该可信合约运行的合约集群,点击停止按钮,会在该集群的所有节点上终止这个合约进程。 + + + +#### 停止 + +在已启动合约实例的下拉框中选择一个合约实例,点击停止按钮,会终止这个合约进程。 + + + +#### 停止全部 + +点击停止全部按钮,会停止该节点上运行的所有合约实例。 + + + +#### 静态分析 + +在合约文件列表中选择合约文件,并在合约实例下拉框中选择合约实例,点击静态分析按钮,会对该合约进行静态分析,并在结果显示框中显示返回结果。 + + + +#### 分发合约 + +在合约文件列表中选择合约项目,并在合约运行模式中选择一个集群,点击分发合约按钮,会将该合约项目打包为ypk分发给这个集群中的所有节点。 + + + + +#### 返回结果 + +![codeManage4](./_static/imgs/codeManage4.png) + +返回结果显示中显示一些操作的返回结果。 + + + +#### 合约权限配置 + +在启动合约之后,如果当前用户的角色可以查看已经启动合约进程,那么在选定查看合约进程时将会在右下方展示当前合约的IO权限。 +![permissionShow](./_static/imgs/permissionShow.png) + +如果选中的合约没有IO权限,则在当前权限的展示框中提示**当前合约没有IO权限** +![nullPermission](./_static/imgs/nullPermission.png) + +当前用户是合约管理员时可以对已有的合约IO权限进行修改。系统会提示修改后合约将有可能不会正常运行,如果还是确定要取消,那么点击**确定** 即可,反之点击**关闭** +![updatePermission](./_static/imgs/updatePermission.png) + +点击关闭或者打开之后,下一次查看同一个合约代码的进程将会默认显示最近一次修改之后的IO权限。 +![closePermission](./_static/imgs/closePermission.png) + +### 合约实例管理菜单 + +![nodeInstancesPage](./_static/imgs/nodeInstancesPage.png) + +合约实例管理菜单显示了该节点当前的所有合约实例, 用户可查看合约实例的状态, 并对合约实例进行执行或状态迁移的操作. + +#### 合约实例列表 + +![nodeInstancesList](./_static/imgs/nodeInstancesList.png) + +该列表显示了当前节点的所有合约实例信息, 包括合约ID, 合约名称, 合约类型合约状态, 合约进程端口, 合约调用次数, 合约流量, 及合约占用内存, 集群合约的结果校验模式. + +#### 合约实例执行 + +![chooseInstance](./_static/imgs/chooseInstance.png) + +用户可在合约实例的选择下拉框中选择合约实例, 对该合约实例进行操作. + +![intanceExecute](./_static/imgs/intanceExecute.png) + +选择合约实例后, 用户可在"方法"的下拉框中选择该合约的方法名, 在"参数"输入框中输入方法的参数, 点击"执行". + +用户还可点击"动态分析执行"进行带有动态分析结果的执行. + +若该合约为单点合约, 则合约在单点执行; 若该合约为集群合约, 则该合约在该集群的所有节点上执行. + +#### 合约实例执行结果 + +![executeResult](./_static/imgs/executeResult.png) + +合约实例的执行完成后的结果显示在"执行结果"区域中, 包括该次执行的ID, 执行成功/失败, 执行时间, 及执行结果. + +![analysisExecuteResult](./_static/imgs/analysisExecuteResult.png) + +若该合约的执行方式为"动态分析执行", 则结果框内除执行结果, 还会显示该次执行的动态分析结果. + +#### 合约状态迁移 + +![memoryDump](./_static/imgs/memoryDump.png) + +对于支持用户手动迁移的合约实例, 用户可点击"本地状态保存"对合约实例的状态进行保存, 或从合约的TimeTravel列表中选择已保存的合约实例, 将合约状态迁移到对应时刻. + + + +### 日志管理菜单 +![logMenu](./_static/imgs/logMenu.png) + +该菜单是对该节点本地节点日志以及合约日志的统计结果展示。 + +其中,节点管理员可以查看节点日志的相关数据;合约管理者及合约使用者可以查看该节点本地合约日志的相关数据。 + + + +#### 日志统计图 + +![log1](./_static/imgs/log1.png) + +#### 各类平台操作百分比 + +该图默认显示近2日各类平台操作占比的饼图,其中平台操作分为登陆类、用户类、日志类、合约类、维护类以及其他类这六类。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比会同步更新。 + + + +#### 各类合约操作百分比 + +合约操作分为启动、终止、静态分析和执行这四类,该图为近2日对各类合约操作占比的饼图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比会同步更新。 + + + + +#### 每日平台使用统计 + +该图为近2日平台操作次数统计的折线图。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日平台使用统计折线图会同步更新。 + + + + +#### 每日合约使用统计 + +该图为近2日对该节点上合约的操作次数统计的折线图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围,修改之后,每日合约使用统计折线图会同步更新。 + + + + +#### 日志详情 + + + +#### 节点日志详情 +![log2](./_static/imgs/log2.png) + +节点日志详情表是对节点日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比和每日平台使用统计会同步更新。 + + + +#### 合约日志详情 +![log3](./_static/imgs/log3.png) + +合约日志详情表是对合约日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比和每日合约使用统计会同步更新。 + + + +### 节点管理菜单 + +![nodeConfig](./_static/imgs/nodeConfig.png) + +节点管理菜单显示了该节点的配置信息及所属可信执行集群信息. + +#### 节点配置 + +![nodeConfigChange](./_static/imgs/nodeConfigChange.png) + +节点管理员可查看该节点的配置信息, 包括节点名称, 节点YJS路径, 节点的网络中心节点, 节点管理员还可对以上配置进行修改. + +若节点管理员修改了节点的网络中心, 该节点后重新想改节点连接, 整个页面刷新重载. + +#### 节点可信执行集群列表 + +![nodeUnits](./_static/imgs/nodeUnits.png) + +节点管理员可查看节点所属的可信执行集群信息, 包括集群创建者, 集群ID, 集群中节点数目, 集群中节点的信息. + +- - - + +#### 节点Licence配置 + +![nodeLicence](./_static/imgs/nodeLicence.png) + +用户可以查看该节点的Licence及过期时间, 还可申请Licence, 上传Licence, 保存节点UUID. + +## 智能合约在线编辑器 + +### 用户与账号 + +#### 创建账号 + +#### 申请授权 + + +### 创建项目 + +#### 新建文件 + +#### 上传文件 + +### 启动合约 +![contractMode](./_static/imgs/contractMode.png) + +####正常模式 +点击左侧启动按钮,以正常模式启动合约。 + +####debug模式 +点击右侧debug按钮,以debug模式启动合约。目前约定debug模式合约通过executeContract调用正常模式合约时,返回正常模式合约文档中的返回结果示例。 + +### 调用合约 + +###生成文档 +![genReadme](./_static/imgs/genReadme.png) + +启动合约后点击"生成文档"按钮,可以通过各export函数的@Description / @Param / @Result 对合约进行调用及结果返回,从而生成合约的说明文档。 + +- - - + +## 路由准入管理界面 + +### 权限申请与授权 + +### 仪表盘 +仪表盘为提供对准入节点中用户数量,合约数量,节点数量的概览。 + +### 整体视图 +![dashboard](./_static/imgs/dashboard.jpg) +一共分为四个模块,一个模块是用户、合约、节点数量的概览,然后分别是这三个数量的详细分类的数据统计情况。 + +### 节点数目 +![node](./_static/imgs/node.jpg) +当前在线和离线节点统计 + +### 用户类型分布 +![userAll](./_static/imgs/userAll.jpg) +当前准入节点所在组网中的节点管理员、准入管理员的数量和申请中节点的数量 + +### 合约调用情况 +![contract](./_static/imgs/contract.jpg) +当前准入节点所在组网中所有合约中事件、多点执行、ws调用、Http调用的折线统计图。 + +### 用户管理 +用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。 + +### 概览 +![centerManager](./_static/imgs/centerManager.jpg) +用户管理页面一共有四个模块。 + + +### 用户类型分布 +主要统计当前中心管理员所管理的网络中有多少节点管理员,多少个中心管理以及申请节点管理员的数量 +![userList](./_static/imgs/userList.jpg) + +### 30天内的申请情况统计 +![userApplyGraph](./_static/imgs/userApplyGraph.jpg) +统计30天之内申请节点管理员的数量和授权成为节点管理员的数量 + +### 当前用户信息 +![authNodeManager](./_static/imgs/authNodeManager.jpg) + * 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录中心管理员界面,可以将自己的公私钥复制到这个文本框中。 + * 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到中心管理员本地 + * 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是中心管理员则拥有中心管理员的一切权限。 + * 如果不是中心管理员或者节点管理员,想要加入当前中心管理员的网络,那么可以在下面的选择框中选中节点管理员,进行**角色认证**。 + +### 授权与非授权用户列表 + 在中心管理员当前用户信息申请之后,中心管理员登录会在**未授权用户管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以,此时这个申请就无效。 +![authMan](./_static/imgs/authMan.jpg) + 授权之后将在**授权用户管理**表格中看见授权后的节点列表。如果中心管理员想要移除某个节点管理员的某项角色,则在授权用户管理列表中选择相应的角色,然后点击**删除**即可删除选中的角色。 +![authMana](./_static/imgs/authMana.jpg) + +### 节点管理 + +![centerNodePage](./_static/imgs/centerNodePage.png) + +节点管理为Manager对连接到自己的Cluster节点进行管理的页面, 仅Manager管理员及合约管理者可见. Manager管理员及合约管理者可在本页面查看节点信息, 并管理可信执行集群. + +### 概览 + +![centerNodePreview](./_static/imgs/centerNodePreview.png) + +概览中显示了该Manager节点所管理的所有节点的统计信息, 包括总节点数量, 总合约数量, 总订阅事件数量, 及可信执行集群数量, 右侧的饼图则为节点的分别处于Online/Offline的数量统计. + +### 节点列表 + +![centerNodeList](./_static/imgs/centerNodeList.png) + +节点列表显示了用户有权限查看的节点信息(Manager管理员可查看全部节点, 合约管理者可查看自己负责管理的Online节点). 包括节点的名称, 状态, 合约数目, 订阅事件数目, 用于节点间P2P通信的PeerID, 用于节点间UDP通信的UDPID, 及节点公钥. + +### 可信执行集群列表 + +![centerNodeUnits](./_static/imgs/centerNodeUnits.png) + +可信执行集群列表显示了用户有权限查看的可信执行集群信息(Manager管理员可查看全部集群, 合约管理者可查看自己创建的集群). 包括集群的创建者, 集群ID, 集群中节点数目, 以及集群中节点的信息. + +用户可点击列表表项的"删除"按钮, 将该集群删除. + +### 创建可信执行集群 + +![centerNodeUnitCreate](./_static/imgs/centerNodeUnitCreate.png) + +用户可以通过多选节点, 创建新的可信执行集群. 用户可以选择的节点为自己有权限查看的节点, 即Manager管理员从全部节点中选择, 合约管理者可从自己负责管理的Online节点中选择). 选择后点击提交, 即可看到创建成功的提示信息, 该集群将随即显示在可信执行集群列表中. 集群名称由创建者选取, 不能含有双引号, 该名称为合约管理者选择集群时的可见标识. + +### 日志管理 +日志管理主要展示准入节点的各项日志信息,一共分为六个模块。 +### 概览 +![log](./_static/imgs/log.jpg) + +### 管理操作分类统计(2日) +![operator](./_static/imgs/operator.jpg) +两日内所有管理类操作的统计饼图,管理类操作主要分为登录类、日志类、维护类、用户类。 + +### 管理操作每日统计(2日) +![everyLog](./_static/imgs/everyLog.jpg) +两日内管理类所有的操作每日操作统计 + +### 合约操作分类统计(2日) +![contractLog](./_static/imgs/contractLog.jpg) +两日内合约操作分类统计饼图,合约操作主要分为连接类和状态更新类。 + +### 合约操作每日统计(2日) +![contracteveryLog](./_static/imgs/contracteveryLog.jpg) +两日内合约操作数量折线统计图。 + +### 管理操作日志列表 +![opList](./_static/imgs/opList.jpg) +管理操作日志的详细信息列表。包括日志时间,管理操作名称,操作对应的节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +### 合约操作日志列表 +![contractList](./_static/imgs/contractList.jpg) +合约操作日志详细信息列表。包括日志产生时间,合约操作名称,合约操作节点公钥。默认展示范围是两天,可以自定义获取日志的天数。 + +### 设置 + +设置页面是节点证书的状态展示以及配置节点证书 + +### 概览 +![set](./_static/imgs/set.jpg) + +### 证书状态 +![licence](./_static/imgs/licence.jpg) +证书状态主要包括许可到期时间和许可节点数量。 + +### 配置证书 +![plicence](./_static/imgs/plicence.jpg) +配置证书模块可以下载节点ID文件或者输入证书信息进行提交。 diff --git a/source/markdown_BDWare/InstallTips.md b/source/markdown_BDWare/InstallTips.md new file mode 100644 index 0000000..e94eafb --- /dev/null +++ b/source/markdown_BDWare/InstallTips.md @@ -0,0 +1,190 @@ +# 安装说明 + + +- - - + +## 依赖环境的安装 +1.安装Java1.8环境。 + +例如,在Ubuntu下使用apt-get进行安装: + +```bash +apt-get install openjdk-8-jre +``` +在Centos环境下,使用yum进行安装: + +```bash +yum install java-1.8.0-openjdk +``` + +如果是离线环境,可先下载openjdk的安装包后进行离线安装。 + +Ubuntu下 +```bash +dpkg -i jdk-8uxxxxx.deb +``` + +在Centos环境下,使用yum进行离线安装: +```bash +yum localinstall jdk-8u271-linux-xxx.rpm +``` + +2.安装wget与unzip。 +例如,在Ubuntu下使用apt-get进行安装: + +```bash +apt-get install unzip +apt-get install wget +``` + +- - - + +## 网络拓扑说明 + +部署数瑞智能合约引擎最小仅需一个节点,此时可用作调试、测试,不能通过多节点模式来实现可信的计算。 +单节点部署时,可通过配置账本实现"防抵赖"的计算,但不能实现"难篡改"的计算。 + +多节点部署时可参考下图,包含三种逻辑节点,同一虚拟机可安装一至三种节点。 + +1)账本节点。即数瑞图式账本。 + +2)合约节点。运行代码逻辑,并通过内存缓存实现高响应的模块。与其他合约节点组成可信计算网络。 + +3)路由节点。各个合约节点的路由信息。一般单个路由节点可支持最高1000合约节点。可视情况部署多个路由节点,并在路由节点之间配置实现更大规模的节点组网。 + +一般地,同一虚拟机下,会部署**合约节点与账本节点**。 + +![deploytopology](_static/imgs/deploytopology.png) + +- - - + +## 智能合约节点安装 + +打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest) +其中,下载`bdserver-lite.zip`或`bdserver.zip`,其中,`bdserver.zip`包含更多示例和文档。 +下载之后解压并启动。 + +```bash +unzip -d ./bdserver bdserver-lite.zip +cd bdserver +chmod +x *.sh +sh cmstart.sh +``` + +- - - + +## 路由准入节点安装 + +打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest) +其中,下载`bdserver-cluster.zip`。 +下载之后解压并启动。 + +```bash +unzip -d ./bdcluster bdserver-cluster.zip +cd bdcluster +chmod +x *.sh +sh ncstart.sh +``` + +- - - + +## 文件说明 + +### 智能合约节点 + +![bdserver目录](_static/imgs/dirstructure.png) + +该目录下的文件说明: + +1.cmstart.sh 该脚本用于启动合约引擎。合约引擎默认监听8080端口,可通过修改cmstart.sh来修改合约引擎的监听端口。 + +2.BDWareProjectDir 该目录存放了本节点的所有合约项目。 + +3.WebContent 该目录存放了本节点的前端代码。 + +4.cp, 该目录存放了yjs.jar,为启动合约实例所需的jar。 + +5.bdserver.jar 对外提供http/websocket的服务器逻辑。 + +6.updateContract.sh 用于升级的脚本。 + +### 路由准入节点 + +安装脚本会自动下载安装并解压为bdcluster目录。 +该目录下的文件说明: + +1.ncstart.sh 该脚本用于启动节点准入中心。默认监听1718端口。可通过修改ncstart.sh来修改监听的端口。 + +2.WebContent 该目录存放了准入中心的前端代码。 + +3.bdcluster.jar 准入中心的后端。 + +- - - + +## 升级流程 + +### 合约节点 + +在命令行中输入: + +```bash +sh updateContract.sh +``` + +亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract),下载最新文件,单独升级yjs.zip/bdserver-jar.zip/AgentWebContent来升级。 + +### 路由准入节点 + +```bash +sh updateCluster.sh +``` +亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract),下载最新文件,单独升级bdserver-cluster.zip/ClusterWebContent.zip来升级。 + +- - - + +## 使用说明 + +### 通过参考界面使用 +当保留了WebContent目录的情况下,可使用浏览器进行配置。 +更多请使用见左侧文档[BDContract参考界面使用说明](./IDEUsage.html)。 + +#### BDWare OnlineIDE +打开[BDWare OnlineIDE](../OnlineIDE.html)。 + +#### BDWare NodePortal +打开[BDWare NodePortal](../NodePortal.html)。 + +如需组网,使用跨节点功能,则需安装路由准入中心。并按以下步骤进行配置。涉及两组公私钥。 +第一组公私钥为合约节点的、有NodeManager权限的公私钥。 +第二组公私钥为路由准入节点的、有CenterManager权限的公私钥。 + +1.打开NodePortal.html,复制该节点的NodeManager公私钥。 + +2.打开CenterPortal.html,点击右上角,将上述的NodeManager公私钥导入;并选择"NodeManager"进行身份认证。 + +3.在CenterPortal.html中切换CenterManager的公私钥,点左侧的"用户管理",通过NodeManager的认证请求。 + +4.使用NodeManager权限的公私钥打开NodePortal.html,点击:“节点管理”菜单,并配置加入网络。 +其中,加入网络的格式为:ws://centerportal的ip:端口+1。 +![配置示例](_static/imgs/config.png) + + +### 通过SDK使用 + +#### 基础知识 + +[Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) + +[Sm2加密的使用](https://github.com/JuneAndGreen/sm-crypto) + +#### SDK下载 + +1. Java版本的客户端下载:[BDWareJavaClient](_static/BDWareJavaClient.zip)。具体使用说明请下载后解压,查看README.md,并参考[ContractAPI](./ContractAPI.html)。 + +2.Javascript版本的客户端下载:[BDWareWebClient](_static/BDWareWebClient.zip)。具体使用说明请下载后解压,查看README.md,并参考[ContractAPI](./ContractAPI.html)。 + +3.配置工具[BDWareConfigTool](_static/BDWareConfigTool.zip)。具体说明请下载后解压,使用以下命令查看帮助: + +``` bash +java -jar java-client.jar -h +``` \ No newline at end of file diff --git a/source/markdown_BDWare/Introduction.md b/source/markdown_BDWare/Introduction.md new file mode 100644 index 0000000..59be7f8 --- /dev/null +++ b/source/markdown_BDWare/Introduction.md @@ -0,0 +1,54 @@ +# 北大数瑞介绍 + +- - - + +## 什么是北大数瑞? + + 北大数瑞是面向大数据场景的数据资源、IoT资源、云资源的管理、调度平台。BDContract是一个可信计算框架,计算逻辑以智能合约的方式表达。通过”随机“和”冗余计算“的方式实现智能合约的可信执行。BDContract在保证智能合约的可用性、可靠性的同时,着重提升执行效率和安全性。 + + +- - - + +## 特点 + +0. 支持多种执行模式,权衡可用性、可靠性、正确性和效率。 +1. 接入各种数据源。 +2. 支持合约的细粒度监测。 +3. 支持合约的状态。 +4. 访问控制。 +5. 支撑跨语言调用。 + + +- - - + + +## 使用开源项目说明 +BDWare项目站在了许多巨人的肩膀上,感谢这些开源项目。 + +本项目的智能合约后端使用了以下开源库。 + +| 名称 | Licence类型 | 说明 | +| ------ | ---------- | ---- | +| [Project Nashorn](https://openjdk.java.net/projects/nashorn/) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 使用了该项目的编译器,可以将js函数编译为java字节码 | +| [ASM OW2](https://projects.ow2.org/view/asm/) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) with attribution | 基于asm的TreeAPI与VisitorAPI实现合约的静态分析框架 | +| [Netty](https://netty.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用netty作为Http/Websocket的服务端 | +| [gRPC](https://grpc.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用gRPC与BDWareLedger通讯 | +| [RocksDB](https://github.com/facebook/rocksdb) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 后台数据库 | +| [ANTLR](https://github.com/antlr/antlr4) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) | 对合约脚本的词法分析与语法分析 | +| [SM2Java](https://github.com/PopezLotado/SM2Java) | [无](https://github.com/PopezLotado/SM2Java/blob/master/README.md) | 国密SM2 Java语言实现 | + + + +本项目的智能合约前端使用了以下开源库。 + +| 名称 | Licence类型 | 说明 | +| ------ | ---------- | ---- | +| [Bootstrap](https://getbootstrap.com/) | [MIT](https://github.com/twbs/bootstrap/blob/master/LICENSE) | 前端的排版、样式 | +| [jQuery](https://jquery.org/) | [MIT](https://jquery.org/license/) | 用于操作DOM的javascript库 | +| [jQueryUI](https://jqueryui.com/) | [MIT](https://jquery.org/license/) | 前端UI构件库 | +| [DataTables](https://datatables.net/) | [MIT](https://datatables.net/license/mit) | 表格样式 | +| [CodeMirror](https://codemirror.net/) | [MIT](https://codemirror.net/LICENSE) | 代码编辑框样式 | +| [eCharts](https://echarts.apache.org/zh/index.html) | [ApacheV2](https://www.apache.org/licenses/) | 统计图表 | +| [sm-crypto](https://github.com/JuneAndGreen/sm-crypto) | [MIT](https://github.com/JuneAndGreen/sm-crypto/blob/master/LICENCE_MIT) | 国密SM2 javascript语言实现 | + +本项目的文档使用[Sphinx](https://www.sphinx-doc.org/en/master/)生成,感谢[readthedocs](https://readthedocs.org/)提供文档样式。 \ No newline at end of file diff --git a/source/markdown_BDWare/YJSAPI.md b/source/markdown_BDWare/YJSAPI.md new file mode 100644 index 0000000..d547272 --- /dev/null +++ b/source/markdown_BDWare/YJSAPI.md @@ -0,0 +1,1136 @@ +# YJS SDK +## YJS Build-in API + +### 内置对象 Global + + +### 内置对象 requester +该内置对象在export function里面会有值,仅当合约调用签名验证通过。 + + +### 执行合约 executeContract + +参数: + +``` bash +action:executeContract; +contractID:合约的id或名称均可; +operation:调用合约的方法名; +arg: 参数;格式为JSON字符串,有action与arg两个字段。 +``` + +可选参数: + +```bash +requestID:字符串类型,自行生成,用于查询hash +``` + +使用示例: + +```javascript + + function testExecutorContract(arg){ + var ret = JSON.parse(executeContract("ElemeProvider","queryDB",arg)); + if (ret.status == "Success"){ + return JSON.parse(ret.result); + }else return null; + } +``` +### 订阅事件主题 subscribe + +参数 + +``` bash +contractID:字符串类型 合约id或名称均可。 +event:字符串类型 +handler:方法名,该方法必须接受Event(内含字段topic和content)类型的唯一变量为参数;可以不是export方法 +``` + +使用示例: + +```javascript +export function init(arg) { + YancloudUtil.subscribe("topic", handler); + print("Handler: " + handler); +} + +function handler(e) { + print("topic: " + e.topic); + print("content: " + e.content); +} + +``` + +## 发布事件 pubEvent + +参数 + +``` bash +topic:字符串类型,发布的事件主题 +content:字符串类型,发布的事件内容 +``` +使用示例: + +```javascript +export function pub1(arg) { + YancloudUtil.pubEvent("topic", arg); + return "done"; +} +``` + +也可以在合约开头定义事件,则事件名即为事件主题,此时可直接使用事件作为方法名发布事件 + +```javascript +event topic; +export function pub2(arg) { + topic(arg); + return "done"; +} +``` + +该写法与上面的`pub1`等价。 + + +### 访问资源文件 + +通过Global.Resources去加载ypk内部的资源文件。 + +#### loadAsInputStream + +参数: + + ```bash + path:字符串类型 需要加载文件的地址 + ``` + 使用示例: + + ```javascript + var file = Global.Resources.loadAsInputStream("/deleteit.txt"); + ``` + +#### loadAsScanner + +参数: + + ```bash + path:字符串类型 需要加载文件的地址 + ``` + + 使用示例: + + ```javascript + var scanner = Global.Resources.loadAsScanner("/local.txt"); + ``` + + + +## YJS Build-in Annotation + +### @Access + +设置合约的调用是否需要签名,这里分为两种,需签名和无签名。 +其中,"verified"表示需要签名。其他则表示无需签名。 + +``` +@Access("verified") +export function easy(arg){ + return "true"; +} +``` + +### @LogType + +LogType注解通过参数的方式声明合约或函数的需要记录的日志类型。 + +其中,Arg表示日志中记录合约执行的参数;Result表示记录合约执行的返回结果;Branch表示记录合约执行分支。 + +例如 ,通过如下LogType注解来声明函数 + +``` +@LogType("Arg","Result","Branch") +export function easy(arg){ + Global.a = "a"; + Global.b = "b"; + if(arg > 0) + return Global.a; + else + return Global.b; +} +``` + +### @LogLocation + +该注解可以修饰`contract`或`function`。 +设置日志存储的位置。参数中指定为“dataware”则存储在账本和本地,如果没有指定为“dataware”则仅存储在本地。 +例如,通过如下LogLocation设置存储位置。 + +在BaaS平台中,可以指定账本名称,BaaS平台默认账本为default,使用 +`@LogLocation("bdledger:default")`。如想保存到自定义的账本,比如,"abc"账本,就使用 +`@LogLocation("bdledger:abc")` + +``` +@LogLocation("dataware") +export function easy(arg){ + Global.a = "a"; +} +``` + + +### @Permission +该注解只能修饰`contract` +设置合约中调用的工具类的权限,包括File、Http、MySQL、MongoDB、RocksDB等工具类。如果合约中用到了以上工具类,需要在注解中添加对应的授权字段,默认只有YJS自带的YancloudUtil;如果没有添加则会抛出"未授权工具类"的异常。 +这6种工具类的详细说明在本小节后续中有说明。 + +``` +@Permission("Http","File") +contract HttpPermission { + export function main(args){ + var http=HttpUtil.httpGet(args); + var dir="adf/adfas/"; + var file=FileUtil.getDir(dir); + return YancloudUtil.currentTimeMillis(); + } +} +``` + +### @Description +该注解可以修饰`contract`或`function`。 +传入合约及函数的简介,可用于生成说明文档中关于exported函数的介绍。 + +``` +@Description("返回数据条目,无需参数") +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` + +### @Param +该注解可以修饰`function`。 +提供调用函数的参数示例,也为生成说明文档中的返回结果提供默认参数。 +``` +@Param({"offset":0,"count":100}) +export function get(args){ + var offset = args.offset; + var count = args.count; + ... +} +``` +### @MockTemplate +该注解可以修饰`function`。 +提供函数的返回模拟数据模板,用于描述返回值的格式.若加此注解在debug方式调用时,返回按照此格式生成的模拟数据。 + + +####支持的字段类型 +``` +@integer +@string +@boolean +@date +@time +@datatime +/[a-z][A-Z][0-9]/ (正则表达式) +…… +详细格式可以参考http://mockjs.com/examples.html +``` +####注意:模板的格式为{‘result’:模板} +```json +//返回一个1-100之间的整数 +@MockTemplate({'result|1-100':1}) +//返回 +{'result':76} + +//返回一个1-5个数的数组 +@MockTemplate({'result|1-5':[{'value|1-100':1}]}) +//返回 +{"result":[{"value":34},{"value":8},{"value":48},{"value":50},{"value":43}]} + +//返回一个对象包含如下字段 +@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) +//返回 +{"password":"3ZLc","name":"William Young","id":36097783842688,"email":"d.fuunwe@gqnr.to"} + + +//返回元素个数为1-5个之间的一个数组,数组的每个元素都是上述格式的一个对象 +{'result|1-5':[{'id':'@integer','email':'@email','password':'@string','name':'@name'}]} +//返回 +[ + {"password":"dO]wW","name":"Jeffrey Lopez","id":1783453207480410,"email":"a.ckokgxrga@hgiesugi.bb"}, + {"password":"BQYRL","name":"Brian Moore","id":4310212972071102,"email":"k.lbpxocydrh@msgnjtox.na"}, + {"password":"Gw1","name":"Susan Jackson","id":7766580783668916,"email":"h.zjgusl@htce.cr"} +] +``` +``` +@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}}) +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` +### @Result +该注解可以修饰`function`。 +若没有模拟数据模板,则返回模拟数据时使用该注解的内容 +提供函数的返回结果示例,若加此注解则生成说明文档时将直接返回此结果而不使用默认参数调用函数。 +``` +@Result(666) +export function count(args){ + var sql = "select count(*) from data;"; + var conn = getConn(); + var statement = conn.createStatement(); + var resultSet = statement.executeQuery(sql); + var c = {}; + resultSet.next(); + c.count = resultSet.getLong(1); + return JSON.stringify(c); +} +``` +## IO工具类 + +### 概览 + +|IO工具类名称|说明| +|---|---| +| [FileUtil](./YJSAPI.html#fileutil) | 文件操作相关的类 | +| [LedgerUtil](./YJSAPI.html#ledgerutil) | 账本操作相关的类 | +| [HttpUtil](./YJSAPI.html#httputil) | Http接口相关的类 | +| [DOIPUtil](./YJSAPI.html#doiputil) | DoIP相关的类 | +| [MySQLUtil](./YJSAPI.html#mysqlutil) | 连接mysql数据库 | +| [MongoDBUtil](./YJSAPI.html#mongodbutil) | MongoDB连接相关的类 | +| [RocksDBUtil](./YJSAPI.html#rocksdbutil) | RocksDB(基于本地文件的k-v数据库) | +| [BDWareTimeSeriesDBUtil](./YJSAPI.html#BDWareTimeSeriesDBUtil) | 基于本地文件的时间序列数据库 | + + +### FileUtil +可以使用@Permission("File")来引入FileUtil对象。 + +``` +@Permission("File") +contract FileSample { +... +} +``` + +该对象支持以下方法: + +#### copyTo + +可以复制文件和目录。第一个参数是source,第二个参数是destination。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | src | 类型为String | +| 2 | dest | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.copyTo("./source.txt","./dest.txt"); +``` + +#### getContent + +获取文件的文本内容,当文件不存在时,返回```undefined```。 + +##### 参数 + +| 序号 | 参数 | 说明 | +| --- | --- | --- | +| 1 | path | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.getContent("./source.txt"); +``` +#### getDir + +获取文件所在的文件夹名,输入参数为字符串。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 类型为String | + +##### 使用示例 +```javascript +var ret = FileUtil.getDir("./parent/src.txt"); +// ret 为 "./parent/"; +``` + +#### getFileName + +获取文件名。输入参数为字符串。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 类型为String | + +##### 使用示例 + +```javascript +var ret = FileUtil.getFileName("./parent/src.txt"); +// ret 为 "src.txt" +``` + + +#### openFileAsPrinter + +以PrintStream的形式打开文件。 +返回结果是```java.io.PrintStream```类型。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 文件名,类型为String | +| 2 | isAppend| 类型为boolean,表示是否往文件末尾添加 | + +##### 使用示例 + +```javascript +var ret = FileUtil.openFileAsPrinter("./parent/src.txt",true); +ret.println("hello"); +ret.close(); +``` + +### LedgerUtil + +可以使用@Permission("Ledger")来引入LedgerUtil对象。 +``` +@Permission("Ledger") +contract LedgerExample{ +... +} +``` + +#### getClient + +获取一个连接客户端,一个参数,为对象类型。 +返回结果为LedgerClient类型,用于后续的查询账本等操作。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | address | 包含ip和端口两个字段 | + +##### 使用示例 + +```javascript +var address = {}; +address.ip = "127.0.0.1"; +address.port = 18091; +var ledgerClient = LedgerUtil.getClient(address); +``` + +#### queryByHash + +根据Hash查询Transaction。 +返回结果为对象,包含from、to、type和data四个字段,均为String类型。 +其中data为按utf-8编码解析字节数组,如果存证时用的不是utf8编码,可能返回乱码。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | client | 通过getClient方法获得的对象 | +| 2 | info | 对象类型,有两个字段ledger和hash,均为字符串类型 | + +##### 使用示例 + +```javascript +// ... ledgerClient = LedgerUtil.getClient(...); +var info = {}; +info.ledger = "bdcontract"; +info.hash = "4d3b75750835092a50085127702669615b602e53"; +var ret = LedgerUtil.queryByHash(ledgerClient,info); +print(ret.from); +print(ret.to); +print(ret.type); +print(ret.data); +``` + +#### sendTransaction + +存证数据。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | client | 通过getClient方法获得的对象 | +| 2 | info | 对象类型,有from\to\data三个字段,均为String类型 | + +##### 使用示例 + +```javascript +// ... ledgerClient = LedgerUtil.getClient(...); +var info = {}; +info.ledger = "bdcontract"; +info.from = "b60e8dd61c5d32be8058bb8eb970870f07233155"; +info.to = "b60e8dd61c5d32be8058bb8eb970870f07233155"; +info.data = "hello world"; +var ret = LedgerUtil.sendTransaction(ledgerClient,info); +//ret为存证的哈希值 +print(ret); +``` + +### HttpUtil + +可以使用@Permission("Http")来引入HttpUtil对象。 +``` +@Permission("Http") +contract HttpExample{ +... +} +``` + +#### createAPIGate + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | ip | 字符串类型,ip,端口默认为6161 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.createAPIGate("192.168.4.4"); +ret.get("com.tencent.mm","sendMsg","msg"); +print(ret); +``` + +#### createAPIGate + +配合手机的元邦使用,当手机安装元邦且安装了API 接口后,可成为数据来源。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | ip | 字符串类型,ip| +| 2 | port | 字符串类型,端口 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.createAPIGate("192.168.4.4", "6161"); +ret.get("com.tencent.mm","sendMsg","msg"); +print(ret); +``` + +#### get + +发起Http的get请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | url | 字符串,表示url类型 | + +##### 使用示例 + +```javascript +var ret = HttpUtil.get("https://www.baidu.com"); +print(ret.responseCode); +print(ret.response); +``` + +#### post +发起Http的post请求。 +返回结果为对象类型,包含response和responseCode两个字段。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | args | 对象类型,有url,headers和data三个字段。其中,args.headers为对象类型。| + +##### 使用示例 + +```javascript +var req = {}; +req.url = "https://www.baidu.com"; +req.data = "hello"; +req.header = {}; +req.header.Accept = "application/json"; +req.header["Content-Type"] = "application/json"; +var ret = HttpUtil.post(req); +print(ret.resposeCode); +print(ret.response); +``` + +### DOIPUtil + +可以使用@Permission("DOIP")来引入DOIPUtil对象。 +``` +@Permission("DOIP") +contract DOIPExample{ + ... +} +``` + +#### call +调用一个DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型, 目标DO标识| +| 2 | arg1 | 字符串类型, 输入参数字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.call("86.5000.470/do.hello","inputString"); +``` +#### create +向一个Repository创建一个字符串类型DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型, 目标Repo标识| +| 2 | arg1 | 对象类型,包括doID,doBody字段| + +##### 使用示例 + +```javascript +var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); +var ret = DOIPUtil.create("86.5000.470/repo.localTcpRepo",digitalObject); +``` +#### delete +从一个Repository中删除DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| +| 2 | arg1 | 字符串类型 目标Repo标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.delete("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo"); +``` +#### hello +获取目标Repository的DOIP服务信息 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标Repo标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.hello("86.5000.470/repo.localTcpRepo"); +``` +#### listOperation +获取目标DO支持的DOIP操作 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.listOperation("86.5000.470/do.hello"); +``` +#### register +向LHS注册一个DO,返回分配的标识 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 DO所在Repo标识| +| 2 | arg1 | 字符串类型 DO格式描述字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.register("86.5000.470/repo.localTcpRepo","String"); +``` +#### reregister +修改LHS中DO的注册信息 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| +| 2 | arg1 | 字符串类型 DO所在Repo标识| +| 3 | arg2 | 字符串类型 DO格式描述字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.reregister("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo","String"); +``` +#### retrieve +获取一个DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 目标DO标识| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.retrieve("86.5000.470/do.hello"); +``` +### test +测试DOIPUtils是否可用 +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | 字符串类型 任意字符串| + +##### 使用示例 + +```javascript +var ret = DOIPUtil.test("hello"); +``` +#### update +更新目标DO + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | arg0 | JS对象,包括doID,doBody字段| + +##### 使用示例 + +```javascript +var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}"); +var ret = DOIPUtil.update(digitalObject); +``` + + + +### MySQLUtil + +可以使用@Permission("MySQL")来引入MySQLUtil对象。 +``` +@Permission("MySQL") +contract MySQLExample{ +... +} +``` + + +#### getConnection + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | URL | 字符串类型,jdbc连接 | +| 2 | usrName | 字符串类型,用户名 | +| 3 | pwd | 字符串类型,密码 | + + +##### 使用示例 + +```javascript +var url = "jdbc:mysql://xx.xx.xx:port/tableName"; +var usrName = "xxx"; +var pwd = "xxx"; +//配置好用户名和密码,url格式为ip或域名+端口,中间以”:”隔开。 +var conn = MySQLUtil.getConnection(url,usrName,pwd); +//获取数据库连接 +var sql = "select * from newele.data"; +//创建查询语句 +var statement = conn.createStatement(); +var resultSet = statement.executeQuery(sql); +var waimailist = []; +//解析查询结果 +var meta = resultSet.getMetaData(); +for (;resultSet.next();){ + var line = {}; + for (var j=1;j<=meta.getColumnCount();j++){ + line[meta.getColumnName(j)] = resultSet.getString(j); + } + waimailist.push(line); +} +``` + +其中,getConnection方法返回的对象通过反射机制绑定到了Java的一个java.util.Connection对象。因此,可以查看: + +以了解如何进行Mysql数据库操作。 + + +### MongoDBUtil + +可以使用@Permission("MongoDB")来引入MongoDBUtil对象。 +``` +@Permission("MongoDB") +contract MongoDBExample{ +... +} +``` + +#### getConnection + + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | URL | 字符串类型 数据库的URL | +| 2 | port | 整数类型 端口号 | +| 3 | dbName | 字符串类型 数据库的名称 | +| 4 | usrName | 字符串类型 数据库的用户名 | +| 5 | pwd | 字符串类型 数据库的密码 | + + +##### 使用示例 + +**注意:port为整型,其他参数为String类型** + +```javascript +var client = MongoDBUtil.getConnection(url,port,dbName,usrName,pwd); +//获取数据库对象 +var db = client.getDatabase("yancloud"); +var collection = db.getCollection("containers"); +var iter = collection.find().iterator(); +var ret =""; +for (;iter.hasNext();){ + ret+=iter.next().toJson(); + ret+="\n"; +} +``` + +其中,getMongoDBClient对象通过反射机制绑定到了Java的一个com.mongodb.MongoClient对象。因此,可以查看: + + +以了解该对象的更多方法和使用方式。 + +### RocksDBUtil + +使用@Permission("RocksDB")来引入RocksDBUtil对象。 + +``` +@Permission("RocksDB") +contract RocksDBSample { +... +} +``` + +#### loadDB + +通过loadDB来加载一个RocksDB数据库。 +加载后,可进行get/delete/put等操作。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | path | 字符串类型 数据库部署的路径 | +| 2 | readOnly | 布尔类型 数据库只读 | + +##### 使用示例 + +``` +@Permission("RocksDB") +@Description("这是个使用RocksDB的参考代码") +contract RocksDBSample{ + function onCreate(){ + Global.rocksdb = RocksDBUtil.loadDB("./dbdir/","false"); + } + @Description("示例参数: {\"key\":\"abc\",\"value\":\"def\"}") + export function put(arg){ + arg = JSON.parse(arg); + Global.rocksdb.put(arg.key,arg.value); + return "success"; + } + @Description("示例参数: \"abc\"}") + export function get(arg){ + return Global.rocksdb.get(arg); + return "failed"; + } + @Description("示例参数: \"abc\"") + export function deleteKey(arg){ + return Global.rocksdb.delete(arg); + } + @Description("遍历KV库,无需参数") + export function iter(arg){ + var iter = Global.rocksdb.newIterator(); + var obj = undefined; + var ret = { + }; + for (iter.seekToFirst();(obj=Global.rocksdb.getNext(iter))!=undefined;){ + ret[obj.key]=obj.value; + } + return JSON.stringify(ret) + } +} +``` + +### BDWareTimeSeriesDBUtil + +使用示例 + +``` +@Permission("BDWareTimeSeriesDB") +contract BDWareTimeDBExample{ + function onCreate(arg){ + Global.dbutil = BDWareTimeSeriesDBUtil.getConnection(); + } + + export function put(arg){ + //第一个参数为表名,第二个参数为要放的value,时间戳自动打。 + Global.dbutil.put("defaultTable",arg); + return "success"; + } + @Param + export function getCount(arg){ + return Global.dbutil.getCount("defaultTable"); + } + @Param(1617254937373) + export function queryByStartTime(arg){ + var startDate = java.lang.Long.valueOf(arg); + //查询从开始时刻startDate到最新的数据 + var list = Global.dbutil.query("defaultTable",startDate); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } + + @Description("示例参数: {\"offset\":1,\"len\":1}") + @Param({"offset":1,"len":1}) + export function queryByOffset(arg){ + var offsetLen = JSON.parse(arg); + //可配合getCount使用,查询第offset至offset+len条数据 + var list = Global.dbutil.queryByOffset("defaultTable",offsetLen.offset,offsetLen.len); + var ret=[]; + print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size()); + var i=0; + for (i=0;i"+list.get(i)); + ret.push(list.get(i)); + } + return ret; + } +} + +``` + + +## 加解密工具类 + + +### SM2 +可以使用@Permission("SM2")来引入SM2Util对象。 + +``` +@Permission("SM2") +contract SM2Sample { +... +} +``` + +#### generateKeyPair +生成公私钥。 + +##### 参数 +无参数。 + +##### 使用示例 + +```javascript +var ret = SM2Util.generateKeyPair(); +print(ret.publicKey); +print(ret.privateKey); +return JSON.stringify(ret); +``` + +#### sign + +签名。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 要进行签名的内容 | +| 2 | keyPair | sm2 | + + +##### 使用示例 + +``` +var keypair = SM2Util.generateKeyPair(); +var ret = SM2Util.sign("Hello",keypair); +print(ret.status); +//如果status是success +print(ret.signature); +//如果status是failed +print(ret.message); +``` + +#### verify + +验签。 + +##### 参数 + +| 序号 | 参数 | 说明 | +|---|---|---| +| 1 | content | 字符串类型 待验签的内容 | +| 2 | signature | 字符串类型 签名 | +| 3 | publicKey | 字符串类型 公钥 | + +##### 使用示例 + +```javascript +var ret = SM2Util.verify("Hello","....签名","...公钥"); +// 验证通过时,result为true,status为success +// 失败时,result为failed,status为failed +print(ret.status); +print(ret.result); +``` + +## 多线程工具类 + +### AsyncUtil + +可以使用@Permission("Async")来引入AsyncUtil对象。 +``` +@Permission("Async") +contract AsyncExample{ + export function longTimeTask(arg){ + var a = { + }; + a.count = 100; + AsyncUtil.postFunction(taskFun,a); + } + function taskFun(arg){ + Global.progress = 0; + for (var i=0;i + +* Number + +* Math + +* Date + +* RegExp + +* Error + +* JSON diff --git a/source/markdown_BDWare/YJSInDepth.md b/source/markdown_BDWare/YJSInDepth.md new file mode 100644 index 0000000..05068b5 --- /dev/null +++ b/source/markdown_BDWare/YJSInDepth.md @@ -0,0 +1,281 @@ +# YJS语法 + +- - - + +## 概述 + +YJS源文件包括任意数量的**import声明**和一个**contract定义**。 + +- - - + +## import声明 + +与JavaScript(ES6)类似,YJS也支持import声明语句,在全局层面,开发者可以使用如下import声明来导入其他文件。 + +``` +import "filename"; +``` + +### 内容 + +import声明语句将包含在“filename”文件中的所有全局符号(单元)导入到当前文件,且全局范围内有效。 + +### 路径 + +**filename**通常用**/**做目录分隔符来表示文件的路径,例如,从同一目录下导入**x.yjs**文件到当前文件,可以使用**import "x.yjs"**语句;从其他目录下导入**x.yjs**使用**import "lib/x.yjs"**语句。 + +- - - + +## Contract定义 + +### 示例 + +以下是一个合约示例,用于JSON处理,此YJS源文件以合约名称命名。 + +``` +contract ScoreAdder{ + //arg = {"action":"main","arg":"[{\"score\":20},{\"score\":20}]"} + export function main(arg){ + //JSON is a build-in object. + var point = JSON.parse(arg); + var s = 0; + print(point[0].score); + print(point.length); + for (var i=0;i + Data from contract: + + + + +``` +示例的资源文件"/html/hello.js"如下: + +```javascript +var queryDataFromContract = function(){ + //第一个参数为函数名,第二个为参数,第三个参数为回调。 + var data = executeCurrentContract("query","abc",function(argg){ + $("#resultText")[0].innerHTML = argg.result; + }); +} +``` + +参考示例: + + + + +### YJS-Python + +TODO + diff --git a/source/markdown_BDWare/httpapi.md b/source/markdown_BDWare/httpapi.md new file mode 100644 index 0000000..dae8693 --- /dev/null +++ b/source/markdown_BDWare/httpapi.md @@ -0,0 +1,594 @@ +``` {.yaml} +type: google.api.Service +config_version: 3 + +http: + rules: + - selector: bdware.bdledger.api.Node.ClientVersion + get: /v0/node/version + - selector: bdware.bdledger.api.Ledger.CreateLedger + post: /v0/ledgers + body: "*" + - selector: bdware.bdledger.api.Ledger.GetLedgers + get: /v0/ledgers + - selector: bdware.bdledger.api.Ledger.SendTransaction + post: /v0/ledgers/{ledger}/transactions + body: "*" + - selector: bdware.bdledger.api.Query.GetBlockByHash + get: /v0/ledgers/{ledger}/block + - selector: bdware.bdledger.api.Query.GetBlocks + post: /v0/ledgers/{ledger}/blocks/query + body: "*" + - selector: bdware.bdledger.api.Query.CountBlocks + post: /v0/ledgers/{ledger}/blocks/count + body: "*" + - selector: bdware.bdledger.api.Query.GetRecentBlocks + get: /v0/ledgers/{ledger}/blocks/recent + - selector: bdware.bdledger.api.Query.GetTransactionByHash + get: /v0/ledgers/{ledger}/transaction + - selector: bdware.bdledger.api.Query.GetTransactionByBlockHashAndIndex + get: /v0/ledgers/{ledger}/block/transaction + - selector: bdware.bdledger.api.Query.GetTransactions + post: /v0/ledgers/{ledger}/transactions/query + body: "*" + - selector: bdware.bdledger.api.Query.CountTransactions + post: /v0/ledgers/{ledger}/transactions/count + body: "*" +``` + +> **Note** +> +> Request/Response data of **bytes** type should/will be encoded with +> [Base64](https://tools.ietf.org/html/rfc4648#section-4). + +> **Note** +> +> When using hash strings in URL, they need to be encoded with +> [encodeURIComponent](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent). + +Request Examples {#_request_examples} +================ + +Node.ClientVersion {#_node_clientversion} +------------------ + +Get BDLedger node version + + GET http://{{IP}}:{{PORT}}/v0/node/version + +**Response.** + +``` {.json} +{ + "version": "dev-210119.a88bf4eb" +} +``` + +Ledger.CreateLedger {#_ledger_createledger} +------------------- + +Create a new ledger + + POST http://{{IP}}:{{PORT}}/v0/ledgers + +**Request body.** + +``` {.json} +{ + "name": "test" +} +``` + +**Response.** + +``` {.json} +{ + "ok": true +} +``` + +Ledger.GetLedgers {#_ledger_getledgers} +----------------- + +Get all ledgers + + GET http://{{IP}}:{{PORT}}/v0/ledgers + +**Response.** + +``` {.json} +{ + "ledgers": [ + "default", + "test" + ] +} +``` + +Ledger.SendTransaction {#_ledger_sendtransaction} +---------------------- + +Send a new transaction + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions + +**Request body.** + +``` {.json} +{ + "transaction": { + "type": 0, + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": 52, + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +**Response.** + +``` {.json} +{ + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" +} +``` + +Query.GetBlockByHash {#_query_getblockbyhash} +-------------------- + +Get a block identified by its hash + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block?hash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D + +**hash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +**Response.** + +``` {.json} +{ + "block": { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } +} +``` + +Query.GetBlocks {#_query_getblocks} +--------------- + +Get blocks in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/query + +``` {.protobuf} +enum IncludeTransactions { + NONE = 0; // Don't include transaction data + HASH = 1; // Include transactions hashes + FULL = 2; // Include full transactions +} +``` + +Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\] + +If only **end\_timestamp** is not specified, or +asciimath:\[\"end\_timestamp\"-\"start\_timestamp\"\>\"query.maxDuration\"\], +then **end\_timestamp** will be set to +asciimath:\[\"start\_timestamp\"+\"query.maxDuration\"\]. + +If only **start\_timestamp** is not specified, then **start\_timestamp** +will be set to asciimath:\[\"end\_timestamp\"-\"query.maxDuration\"\]. + +In all cases, **start\_timestamp** will never be earlier than the +genesis block's timestamp, and **end\_timestamp** will never be later +than the current timestamp when the node process the query request. + +**Request body 1.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 0 +} +``` + +**Response 1.** + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +**Request body 2.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 1 +} +``` + +**Response 2.** + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +**Request body 3.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000, + "include_transactions": 2 +} +``` + +**Response 3.** + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "transactionHashes": [ + "VQBeA5Ee0Y5hqEileoQuYMHbOSE=" + ] + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +Query.CountBlocks {#_query_countblocks} +----------------- + +Count all blocks in a ledger, or blocks in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/count + +Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\] + +If neither **start\_timestamp** nor **end\_timestamp** is specified, +then count all blocks in the specified ledger. + +If only **end\_timestamp** is not specified, then count all blocks with +timestamps later than **start\_timestamp**. + +If only **start\_timestamp** is not specified, then count all blocks +with timestamps earlier than **end\_timestamp**. + +In all cases, **start\_timestamp** will never be earlier than the +genesis block's timestamp, and **end\_timestamp** will never be later +than the current timestamp when the node process the query request. + +**Request body 1.** + +``` {.json} +{} +``` + +**Response 1.** + +``` {.json} +{ + "count": "5", + "startTimestamp": "0", + "endTimestamp": "1611039957" +} +``` + +**Request body 2.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +**Response 2.** + +``` {.json} +{ + "count": "1", + "startTimestamp": "1611038000", + "endTimestamp": "1611039000" +} +``` + +Query.GetRecentBlocks {#_query_getrecentblocks} +--------------------- + +Get recent **count** blocks (Only support IncludeTransactions=NONE for +now) + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/recent?count=2 + +**Response.** + +``` {.json} +{ + "blocks": [ + { + "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "3XkwkuMBearq8uavN76Te7Zdpl8=" + ], + "witnesses": [], + "timestamp": "1611038043", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "transactions": [], + "transactionHashes": [] + }, + { + "hash": "rk0DWMaUpRG82yVX+cFhbfhPFdw=", + "creator": "", + "nonce": "0", + "parentHashes": [ + "fLX5pMY8M1qSAGZdKT1rWBkdEMo=", + "3XkwkuMBearq8uavN76Te7Zdpl8=", + "8pZPR74OALIbps5XFb4dL/s0j0M=" + ], + "witnesses": [], + "timestamp": "1610968019", + "size": "0", + "transactionCount": 1, + "transactionsRoot": "LuxttCm/pSHVMOKF0sJExk+DJXc=", + "transactions": [], + "transactionHashes": [] + } + ], + "startTimestamp": "1610968019", + "endTimestamp": "1611038043" +} +``` + +Query.GetTransactionByHash {#_query_gettransactionbyhash} +-------------------------- + +Get a transaction identified by its hash + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/transaction?hash=VQBeA5Ee0Y5hqEileoQuYMHbOSE%3D + +**hash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +**Response.** + +``` {.json} +{ + "transaction": { + "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "blockTimestamp": "1611038043", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +Query.GetTransactionByBlockHashAndIndex {#_query_gettransactionbyblockhashandindex} +--------------------------------------- + +Get a transaction identified by hash of the block it belongs to and its +index inside the block + + GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block/transaction?blockHash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D&index=0 + +**blockHash** has to be encoded with +[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + +**Response.** + +``` {.json} +{ + "transaction": { + "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=", + "blockTimestamp": "1611038043", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } +} +``` + +Query.GetTransactions {#_query_gettransactions} +--------------------- + +Get transactions in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/query + +**start\_timestamp** and **end\_timestamp** follow the same requirements +and rules as in [???](#Query.GetBlocks). + +**Request body.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +**Response.** + +``` {.json} +{ + "transactions": [ + { + "blockHash": "", + "blockTimestamp": "0", + "index": 0, + "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=", + "type": "RECORD", + "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=", + "nonce": "0", + "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM=" + } + ], + "startTimestamp": "1611038043", + "endTimestamp": "1611038043" +} +``` + +Query.CountTransactions {#_query_counttransactions} +----------------------- + +Count all transactions in a ledger, or transactions in a timestamp range + + POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/count + +**start\_timestamp** and **end\_timestamp** follow the same requirements +and rules as in [???](#Query.CountBlocks). + +**Request body 1.** + +``` {.json} +{} +``` + +**Response 1.** + +``` {.json} +{ + "count": "4", + "startTimestamp": "0", + "endTimestamp": "1611039957" +} +``` + +**Request body 2.** + +``` {.json} +{ + "start_timestamp": 1611038000, + "end_timestamp": 1611039000 +} +``` + +**Response 2.** + +``` {.json} +{ + "count": "1", + "startTimestamp": "1611038000", + "endTimestamp": "1611039000" +} +``` diff --git a/toRst.sh b/toRst.sh new file mode 100644 index 0000000..674449d --- /dev/null +++ b/toRst.sh @@ -0,0 +1,19 @@ +#!/bin/bash +cd source +rm -rf ContractAPI.rst +rm -rf IDEUsage.rst +rm -rf InstallTips.rst +rm -rf Introduction.rst +rm -rf YJSAPI.rst +rm -rf YJSInDepth.rst + +pandoc ./markdown/ContractAPI.md -f markdown -t rst -o ContractAPI.rst +pandoc ./markdown/IDEUsage.md -f markdown -t rst -o IDEUsage.rst +pandoc ./markdown/InstallTips.md -f markdown -t rst -o InstallTips.rst +pandoc ./markdown/Introduction.md -f markdown -t rst -o Introduction.rst +pandoc ./markdown/YJSAPI.md -f markdown -t rst -o YJSAPI.rst +pandoc ./markdown/YJSInDepth.md -f markdown -t rst -o YJSInDepth.rst + +cd .. +make clean +make html diff --git a/toWordConvert.sh b/toWordConvert.sh new file mode 100644 index 0000000..0405e90 --- /dev/null +++ b/toWordConvert.sh @@ -0,0 +1,28 @@ +#!/bin/bash +cd source +# 需安装pandoc +files=("ContractAPI" "IDEUsage" "InstallTips" "Introduction" "YJSAPI" "YJSInDepth") +path_prefix="" +path_suffix=".rst" +titles=("BDContract SDK" "BDContract管理界面" "BDContract安装说明" "BDContract简介" "YJS语法" "YJS SDK") +target_path_prefix="../build/word/" +target_path_suffix=".docx" + +rm -rf $target_path_prefix +mkdir $target_path_prefix + +for(( i=0;i<${#files[@]};i++)) do + target_path="$target_path_prefix${titles[$i]}$target_path_suffix" + source_path="$path_prefix${files[$i]}$path_suffix" + pandoc --highlight-style=espresso -o $target_path -f rst -t docx $source_path +done + +# 模板 espresso/breezedark +#pygments +#tango +#espresso +#zenburn +#kate +#monochrome +#breezedark +#haddock diff --git a/文档编写说明.txt b/文档编写说明.txt new file mode 100644 index 0000000..23ed143 --- /dev/null +++ b/文档编写说明.txt @@ -0,0 +1,49 @@ +# 开发环境安装: + +pip install sphinx + +# 配置文件说明 + +./source/index.rst +./source/conf.py + +# 编写文档 + +前往source/markdown目录,修改xxx.md文件。 + +## 转换成rst,并生成html。 + +在./doc/目录下,执行: +```bash +sh toRst.sh +``` + +## + + +# MarkDownTips + +1)学习markdown:https://www.runoob.com/markdown/md-tutorial.html +2)可参考现有.md文件作为模板。 +3)表格示例: +| 字段 | 值 | +| ------ | --------------------------------- | +| action | startContract | +| script | 合约脚本内容, 需进行进行URIEncode | + +4)代码示例: +特别地,json代码的格式化可以使用:http://www.bejson.com/t2ck.htm +```json +{ + "data": "{\"status\":\"Success\",\"result\":\"\"}", + "action": "onStartContract", + "cid": "-562752842", + "executeTime": 1187 +} +``` +5)插入图片示例: +![shortcut2](./_static/imgs/shortcut2.png) +方括号内为小标题,小括号内为“图片的相对路径”,一定不要写成绝对路径。 + +6)超链接: +[百度](http://baidu.com)