diff --git a/.env b/.env new file mode 100644 index 0000000..d213f4b --- /dev/null +++ b/.env @@ -0,0 +1 @@ +USE_LIGHT_CLIENT_WASM=false \ No newline at end of file diff --git a/.github/workflows/ckb-light-client-ci-wasm.yml b/.github/workflows/ckb-light-client-ci-wasm.yml new file mode 100644 index 0000000..dda7aaf --- /dev/null +++ b/.github/workflows/ckb-light-client-ci-wasm.yml @@ -0,0 +1,54 @@ +name: ci-ckb-wasm + +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + + +jobs: + npm-install-1: + strategy: + fail-fast: false + matrix: + net: ['testnet_v1'] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - uses: actions/setup-node@v3 + with: + node-version: '16' + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - name: Node Cache + uses: actions/cache@v4 + id: npm-and-yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: | + ${{ steps.yarn-cache-dir-path.outputs.dir }} + ~/.npm + key: ${{ runner.os }}-node_modules-${{ hashFiles('/home/runner/work/**/package-lock.json', '/home/runner/work/**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node_modules- + - name: prepare env + id: runtest + run: | + npm install --save-dev mocha @types/mocha chai @types/chai + bash prepare_wasm.sh + - name: run test + id: ci-test + run: | + npm run test-wasm + + - name: Publish reports + if: failure() + uses: actions/upload-artifact@v4 + with: + name: jfoa-build-reports-${{ runner.os }} + path: mochawesome-report/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8e8f007 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ckb-light-wasm-demo"] + path = ckb-light-wasm-demo + url = https://github.com/gpBlockchain/ckb-light-wasm-demo.git diff --git a/ckb-light-wasm-demo b/ckb-light-wasm-demo new file mode 160000 index 0000000..f2a397a --- /dev/null +++ b/ckb-light-wasm-demo @@ -0,0 +1 @@ +Subproject commit f2a397ae0dee68f2a6d7beb0c6c1e66c683b1348 diff --git a/config/config.ts b/config/config.ts index fb61700..952abcb 100644 --- a/config/config.ts +++ b/config/config.ts @@ -5,20 +5,21 @@ import {LightClientRPC} from "@ckb-lumos/light-client"; const CKB_CLIENT_CLI_PATH = "tmp/ckb-cli-light-client" const CKB_LIGHT_CLIENT_PATH = "tmp/startBlockchain/ckbLightClient/ckb-light-client" -const DEV_PATH = "tmp/startBlockchain/ckbDevWithIndexAndeLightClient" -const CKB_DEV_PATH = "tmp/startBlockchain/ckbDevWithIndexAndeLightClient/ckb/target/release" -const CKB_DEV_INDEX_PATH = "tmp/startBlockchain/ckbDevWithIndexAndeLightClient/ckb-indexer/target/release" -const CKB_DEV_LIGHT_CLIENT_PATH = "tmp/startBlockchain/ckbDevWithIndexAndeLightClient/ckb-light-client/target/release" +const DEV_PATH = "tmp/startBlockchain/ckbDevWithIndexAndLightClient" +const CKB_DEV_PATH = "tmp/startBlockchain/ckbDevWithIndexAndLightClient/ckb/target/release" +const CKB_DEV_INDEX_PATH = "tmp/startBlockchain/ckbDevWithIndexAndLightClient/ckb-indexer/target/release" +const CKB_DEV_LIGHT_CLIENT_PATH = "tmp/startBlockchain/ckbDevWithIndexAndLightClient/ckb-light-client/target/release" -const CKB_DEV_RPC_URL = "https://testnet.ckbapp.dev/"; -const CKB_DEV_RPC_INDEX_URL = "https://testnet.ckbapp.dev/"; +const CKB_DEV_RPC_URL = "http://localhost:8114/"; +const CKB_DEV_RPC_INDEX_URL = "http://localhost:8116/"; -const RPC_DEBUG = false +const RPC_DEBUG = true const CKB_RPC_URL = "https://testnet.ckbapp.dev/"; // const CKB_RPC_URL = CKB_DEV_RPC_URL; const CKB_RPC_INDEX_URL = "https://testnet.ckbapp.dev/"; // const CKB_RPC_INDEX_URL = CKB_DEV_RPC_INDEX_URL; const CKB_LIGHT_RPC_URL = "http://127.0.0.1:9000"; + export enum FeeRate { SLOW = 1000, NORMAL = 1000000, @@ -32,13 +33,13 @@ config.initializeConfig( config.predefined.AGGRON4 ); const script = helpers.parseAddress( - "ckt1qyqvjdmh4re8t7mfjr0v0z27lwwjqu384vhs6lfftr" + "ckt1qyqvjdmh4re8t7mfjr0v0z27lwwjqu384vhs6lfftr", {config: config.predefined.AGGRON4} ); -const MINER_SCRIPT = helpers.parseAddress("ckt1qyqvjdmh4re8t7mfjr0v0z27lwwjqu384vhs6lfftr") -const MINER_SCRIPT2 = helpers.parseAddress("ckt1qyq8ph2ywxpvkl5l0rcsugcnwcfswqpqngeqqmfuwq") -const MINER_SCRIPT3 = helpers.parseAddress("ckt1qyqd5eyygtdmwdr7ge736zw6z0ju6wsw7rssu8fcve") +const MINER_SCRIPT = helpers.parseAddress("ckt1qyqvjdmh4re8t7mfjr0v0z27lwwjqu384vhs6lfftr", {config: config.predefined.AGGRON4}) +const MINER_SCRIPT2 = helpers.parseAddress("ckt1qyq8ph2ywxpvkl5l0rcsugcnwcfswqpqngeqqmfuwq", {config: config.predefined.AGGRON4}) +const MINER_SCRIPT3 = helpers.parseAddress("ckt1qyqd5eyygtdmwdr7ge736zw6z0ju6wsw7rssu8fcve", {config: config.predefined.AGGRON4}) const CkbClientNode = new LightClient(CKB_LIGHT_CLIENT_PATH) -const lightClientRPC = new LightClientRPC(CKB_LIGHT_RPC_URL) +const lightClientRPC = new LightClientRPC(CKB_LIGHT_RPC_URL) const deprecatedAddr = helpers.generateAddress(script); const newFullAddr = helpers.encodeToAddress(script); @@ -79,6 +80,10 @@ const EVERY_ONE_CAN_PAY_TYPE_ID = { } const EVERY_ONE_CAN_PAY = EVERY_ONE_CAN_PAY_TYPE_ID +export function checkLightClientWasm(): boolean { + return process.env.USE_LIGHT_CLIENT_WASM === 'true'; +} + export { FEE, CKB_RPC_URL, diff --git a/package.json b/package.json index 4442015..8090574 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,11 @@ "@ckb-lumos/light-client": "v0.20.0-alpha.1", "@ckb-lumos/lumos": "v0.20.0-alpha.1", "@ckb-lumos/rpc": "v0.20.0-alpha.1", + "@injectivelabs/networks": "^1.14.4", + "@injectivelabs/wallet-ts": "^1.14.4", "dotenv": "^16.0.1", + "json-rpc": "^0.3.0", + "json-rpc-2.0": "^1.7.0", "mochawesome-merge": "^4.2.1", "npm-run-all": "^4.1.5" }, @@ -29,6 +33,7 @@ "mocha-chai-jest-snapshot": "^1.1.0", "mochawesome": "^7.1.3", "mochawesome-report-generator": "^6.2.0", + "playwright": "^1.49.1", "prettier": "^2.0.5", "prettier-plugin-solidity": "^1.0.0-alpha.59", "solhint": "^3.2.1", @@ -39,6 +44,7 @@ "typescript": "^3.7.3" }, "scripts": { + "test-wasm": "USE_LIGHT_CLIENT_WASM=true mocha --config test/runners/mocha/.mocharc.jsonc --reporter mochawesome", "test": "mocha --config test/runners/mocha/.mocharc.jsonc --reporter mochawesome", "test-load": "mocha --config test/runners/mocha/.mocharc.load.jsonc --reporter mochawesome", "test-data": "mocha --config test/runners/mocha/.mocharc.data.jsonc --reporter mochawesome", diff --git a/service/CkbDevService.ts b/service/CkbDevService.ts index 423b8b3..7dd713d 100644 --- a/service/CkbDevService.ts +++ b/service/CkbDevService.ts @@ -30,7 +30,7 @@ export async function cut_miner_and_wait_lightClient_sync(cut_num: number, miner export async function compare_cells_result(scriptObject1: Script) { let compare = true; const indexCells = await getCellsMsg(scriptObject1, CKB_DEV_RPC_INDEX_URL) - console.log("lightCells:") + const lightCells = await getCellsMsg(scriptObject1, CKB_LIGHT_RPC_URL) // get indexCells but not in light const indexNotInLightCells = indexCells.filter(cell => !lightCells.some(lightCell => { diff --git a/service/node.ts b/service/node.ts index 97bb886..3537238 100644 --- a/service/node.ts +++ b/service/node.ts @@ -1,4 +1,6 @@ import {exec} from "child_process"; +import {request} from "./index"; +import {checkLightClientWasm} from "../config/config"; class LightClient { @@ -12,10 +14,9 @@ class LightClient { } async start(): Promise { - try{ - await sh("rm "+this.dirPath + "/target/release/data/store/LOCK") - }catch(e){ - console.log(e) + if (checkLightClientWasm()){ + await request(1,this.url,"start",[]) + return true } await sh("cd " + this.dirPath + "/target/release && RUST_LOG=info,ckb_light_client=trace ./ckb-light-client run --config-file ./config.toml > node.log 2>&1 &") await sleep(5*1000) @@ -23,12 +24,20 @@ class LightClient { } async stop(): Promise { - + if (checkLightClientWasm()){ + await request(1,this.url,"stop",[]) + return true + } await sh("pkill ckb-light") return true } async clean(): Promise { + if (checkLightClientWasm()){ + await request(1,this.url,"new_client",[]) + await request(1,this.url,"stop",[]) + return true + } try { await this.stop() diff --git a/test/get_cells.spec.ts b/test/get_cells.spec.ts index 096eb09..c736fcb 100644 --- a/test/get_cells.spec.ts +++ b/test/get_cells.spec.ts @@ -1,7 +1,7 @@ import { ACCOUNT_PRIVATE, EVERY_ONE_CAN_PAY_TYPE_ID, CKB_LIGHT_RPC_URL, - CKB_RPC_URL, MINER_SCRIPT, CKB_RPC_INDEX_URL, lightClientRPC, rpcCLient, indexerMockLightRpc + CKB_RPC_URL, MINER_SCRIPT, CKB_RPC_INDEX_URL, lightClientRPC, rpcCLient, indexerMockLightRpc, checkLightClientWasm } from "../config/config"; import {AGGRON4, generateAccountFromPrivateKey, getBlockNumByTxHash, send_tx} from "../service/transfer"; import {BI} from "@ckb-lumos/bi"; @@ -22,6 +22,9 @@ describe('get_cell', function () { describe('script', function () { describe('code_hash', function () { it('length not eq 64 ', async () => { + if (checkLightClientWasm()) { + return + } let acc = generateAccountFromPrivateKey(ACCOUNT_PRIVATE) acc.lockScript.codeHash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce" await getCellsReturnFailed({ @@ -201,7 +204,9 @@ describe('get_cell', function () { }) it(',should return failed', async () => { - + if (checkLightClientWasm()) { + return + } try { await lightClientRPC.getCells( { @@ -626,13 +631,13 @@ describe('get_cell', function () { }); describe('limit', function () { it('0,should return error that limit should be greater than 0', async () => { - await getCellsReturnFailed({ + await getCellsReturnFailed({ limit: "0x0", order: "asc", searchKey: { script: MINER_SCRIPT, scriptType: "lock" } - },CKB_LIGHT_RPC_URL) + }, CKB_LIGHT_RPC_URL) }) it('1', async () => { let cells = await getCellsRequest({ @@ -689,11 +694,17 @@ describe('get_cell', function () { } } let cells = await getCellsRequest(getCellReq) + console.log("cells.objects.length:", cells.objects.length) getCellReq.limit = "0x1" let allCells = await getAllCellsRequest(getCellReq) expect(cells.objects.length).to.be.equal(allCells.length) + console.log("---allCells---") + printCells(allCells) + console.log("---cells---") + printCells(cells.objects) + for (let i = 0; i < cells.objects.length; i++) { - expect(cells.objects[i].blockNumber).to.be.equal(allCells[i].blockNumber) + expect(JSON.stringify(cells.objects[i])).to.be.equals(JSON.stringify(allCells[i])) } }) diff --git a/test/get_transactions.spec.ts b/test/get_transactions.spec.ts index bd67746..164dd62 100644 --- a/test/get_transactions.spec.ts +++ b/test/get_transactions.spec.ts @@ -1,21 +1,60 @@ -import {lightClientRPC} from "../config/config"; +import {CKB_LIGHT_RPC_URL, lightClientRPC, rpcCLient} from "../config/config"; +import {HexNumber, Script} from "@ckb-lumos/base"; +import {ScriptType} from "@ckb-lumos/light-client/src/type"; +import {waitScriptsUpdate} from "../service/lightService"; +import {BI} from "@ckb-lumos/bi"; +type TestLightClientScript = { + script: Script; + scriptType: ScriptType; +}; describe('get_transactions', function () { + this.timeout(100000000) + let test_scripts: TestLightClientScript[] = [ + { + "script": { + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hashType": "data", + "args": "0x" + }, + "scriptType": "lock", + } + ] + // before(async function () { + // + // let txs = await rpcCLient.getTransactions({ + // "script": test_scripts[0].script, "scriptType": test_scripts[0].scriptType, + // "groupByTransaction": true + // }, "asc", "0xfff") + // console.log(txs.objects[0].blockNumber) + // console.log(txs.objects[txs.objects.length - 1].blockNumber) + // await lightClientRPC.setScripts([ + // { + // "script": test_scripts[0].script, + // "scriptType": test_scripts[0].scriptType, + // "blockNumber": txs.objects[txs.objects.length - 1].blockNumber + // } + // ]) + // await waitScriptsUpdate(BI.from(txs.objects[0].blockNumber),CKB_LIGHT_RPC_URL) + // }) - it("demo",async ()=>{ + it("demo", async () => { - let response = await lightClientRPC.getTransactions( + let lightTxs = await lightClientRPC.getTransactions( { - "script": { - "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "hashType": "data", - "args": "0x" - }, - "scriptType": "lock", + "script": test_scripts[0].script, + "scriptType": test_scripts[0].scriptType, "groupByTransaction": true - },"asc","0xfff" + }, "asc", "0xfff" ) - console.log("response:",response) + let ckbTxs = await rpcCLient.getTransactions({ + "script": test_scripts[0].script, "scriptType": test_scripts[0].scriptType, + "groupByTransaction": true + }, "asc", "0xfff") + console.log(lightTxs.objects.length) + console.log(ckbTxs.objects.length) + // (lightTxs.objects.length == ckbTxs.objects.length, "light txs length not equal ckb txs length") + }) }); diff --git a/test/scenes.test.ts b/test/scenes.test.ts index 87a289b..3c2d525 100644 --- a/test/scenes.test.ts +++ b/test/scenes.test.ts @@ -1,5 +1,5 @@ import { - ACCOUNT_PRIVATE, + ACCOUNT_PRIVATE, checkLightClientWasm, CKB_LIGHT_RPC_URL, CKB_RPC_INDEX_URL, CKB_RPC_URL, @@ -71,6 +71,7 @@ describe('scenes', function () { }) it('exist tx ,buy not contains cell tx ,should return null', async () => { + await Sleep(1000 * 5); let header = await lightClientRPC.getTipHeader() let txs = await getTransactionsByBlockNum(BI.from(header.number).toNumber(), rpcCLient) for (const tx of txs) { @@ -167,7 +168,9 @@ describe('scenes', function () { }); describe('set script that block begin with 0', function () { - + if (checkLightClientWasm()){ + return + } let account = generateAccountFromPrivateKey(ACCOUNT_PRIVATE) const costTx = "0x1850f997f867b6d3f1154444498a15e9fc4ce080215e34d0c41b33349bcc119a" @@ -376,6 +379,9 @@ describe('scenes', function () { }); describe('script sync to mid ,try again from 0', function () { + if (checkLightClientWasm()){ + return + } let latestSyncBlockNum; let latestTxs; diff --git a/test/set_scripts.spec.ts b/test/set_scripts.spec.ts index 8caaf94..d677c3d 100644 --- a/test/set_scripts.spec.ts +++ b/test/set_scripts.spec.ts @@ -1,5 +1,5 @@ import {expect} from 'chai' -import { lightClientRPC, rpcCLient} from "../config/config"; +import {checkLightClientWasm, lightClientRPC, rpcCLient} from "../config/config"; import {AGGRON4} from "../service/transfer"; import {Script} from "@ckb-lumos/base"; import {BI} from "@ckb-lumos/bi"; @@ -44,6 +44,11 @@ describe('set_scripts', function () { scriptType: "lock", blockNumber: "0xffffffff" }, + { + script: testScript, + scriptType: "lock", + blockNumber: "0xfff" + }, ]) expect(result).to.be.equal(null) @@ -51,7 +56,7 @@ describe('set_scripts', function () { // get scripts let result1 = await lightClientRPC.getScripts() expect(result1.length).to.be.equal(1) - expect(result1[0].blockNumber).to.be.equal("0xffffffff") + expect(result1[0].blockNumber).to.be.equal("0xfff") expect(result1[0].script.args).to.be.equal(testScript.args) expect(result1[0].script.codeHash).to.be.equal(testScript.codeHash) expect(result1[0].script.hashType).to.be.equal(testScript.hashType) @@ -59,7 +64,9 @@ describe('set_scripts', function () { }) it('set with too many scripts,should return null', async () => { - + if (checkLightClientWasm()){ + return; + } const size = 10000; let scripts: LightClientScript[] = []; @@ -109,13 +116,13 @@ describe('set_scripts', function () { scripts.forEach(value => { temScriptsData.push({ script: value, + scriptType:"lock", blockNumber: "0x1" }) }) if (temScriptsData.length > 0) { - // @ts-ignore - await setScripts(temScriptsData) + await lightClientRPC.setScripts(temScriptsData) await lightClientRPC.getScripts() } } @@ -125,6 +132,9 @@ describe('set_scripts', function () { describe('script', function () { describe('codeHash', function () { it("codeHash length not eq 64, return an error", async () => { + if (checkLightClientWasm()){ + return; + } await setScriptRequestReturnFailed([{ script: { codeHash: "0x1234111", @@ -195,7 +205,9 @@ describe('set_scripts', function () { }) it('hash_type type is null ', async () => { - + if (checkLightClientWasm()){ + return + } await setScriptRequestReturnFailed([{ script: { codeHash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce2", @@ -208,6 +220,9 @@ describe('set_scripts', function () { }); describe('args', function () { it('arg is undefined,should return error msg', async () => { + if (checkLightClientWasm()){ + return + } await setScriptRequestReturnFailed([{ script: { codeHash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce2", @@ -218,6 +233,9 @@ describe('set_scripts', function () { }) it('arg is null,should return error msg ', async () => { + if (checkLightClientWasm()){ + return + } await setScriptRequestReturnFailed([{ script: { codeHash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce2", @@ -228,6 +246,9 @@ describe('set_scripts', function () { }) it('arg is very large,should send success,return null', async () => { + if (checkLightClientWasm()){ + return + } let argData = "0x"; for (let i = 0; i < 100000; i++) { argData = argData + "ffffff" @@ -246,7 +267,10 @@ describe('set_scripts', function () { }); describe('block number', function () { - it.skip('block number is overflow,should return failed msg', async () => { + it('block number is overflow,should return failed msg', async () => { + if (checkLightClientWasm()){ + return + } await setScriptRequestReturnFailed([{ script: { codeHash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8",