Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { scheduler } from 'timers/promises'
import SyncProgressService from '../../services/sync-progress'
import { BlockTips, LumosCellQuery, Connector, AppendScript } from './connector'
import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils'
import { LightRPC, LightScriptFilter } from '../../utils/ckb-rpc'
import { FetchTransactionReturnType, LightRPC, LightScriptFilter } from '../../utils/ckb-rpc'
import HexUtils from '../../utils/hex'
import Multisig from '../../services/multisig'
import { SyncAddressType } from '../../database/chain/entities/sync-progress'
Expand Down Expand Up @@ -61,7 +61,7 @@ export default class LightConnector extends Connector<CKBComponents.Hash> {
this.fetchDepCell()
}

private async fetchDepCell() {
private async getDepTxs(): Promise<string[]> {
const assetAccountInfo = new AssetAccountInfo()
const fetchCellDeps = [
assetAccountInfo.anyoneCanPayCellDep,
Expand All @@ -75,30 +75,36 @@ export default class LightConnector extends Connector<CKBComponents.Hash> {
const fetchTxHashes = fetchCellDeps
.map(v => v.outPoint.txHash)
.map<[string, string]>(v => ['fetchTransaction', v])
let txs = await this.lightRpc
.createBatchRequest<any, string[], (CKBComponents.TransactionWithStatus | null)[]>(fetchTxHashes)
const txs = await this.lightRpc
.createBatchRequest<any, string[], FetchTransactionReturnType[]>(fetchTxHashes)
.exec()
if (txs.some(v => !v)) {
// if some txs fetch to added, then fetch the actural txs
txs = await this.lightRpc
.createBatchRequest<any, string[], (CKBComponents.TransactionWithStatus | null)[]>(fetchTxHashes)
.exec()
if (txs.some(v => !v.txWithStatus)) {
// wait for light client sync the dep cell
await scheduler.wait(10000)
return await this.getDepTxs()
}
const depGroupOutputsData: string[] = fetchCellDeps
return fetchCellDeps
.map((v, idx) => {
if (v.depType === DepType.DepGroup) {
Comment thread
Keith-CY marked this conversation as resolved.
return txs[idx]?.transaction?.outputsData?.[+v.outPoint.index]
const tx = txs[idx]
return tx.txWithStatus ? tx?.txWithStatus?.transaction?.outputsData?.[+v.outPoint.index] : undefined
}
})
.filter<string>((v): v is string => !!v)
}

private async fetchDepCell() {
const depGroupOutputsData: string[] = await this.getDepTxs()
const depGroupTxHashes = [
...new Set(depGroupOutputsData.map(v => unpackGroup.unpack(v).map(v => v.tx_hash.toHexString())).flat())
]
await this.lightRpc
.createBatchRequest<any, string[], (CKBComponents.TransactionWithStatus | null)[]>(
depGroupTxHashes.map(v => ['fetchTransaction', v])
)
.exec()
if (depGroupTxHashes.length) {
await this.lightRpc
.createBatchRequest<any, string[], FetchTransactionReturnType[]>(
depGroupTxHashes.map(v => ['fetchTransaction', v])
)
.exec()
}
}

private async synchronize() {
Expand Down Expand Up @@ -154,9 +160,9 @@ export default class LightConnector extends Connector<CKBComponents.Hash> {
if (!this.addressMetas.length && !appendScripts?.length) {
return
}
const sycnScripts = await this.lightRpc.getScripts()
const syncScripts = await this.lightRpc.getScripts()
const existSyncscripts: Record<string, LightScriptFilter> = {}
sycnScripts.forEach(v => {
syncScripts.forEach(v => {
existSyncscripts[scriptToHash(v.script)] = v
})
const currentWalletId = WalletService.getInstance().getCurrent()?.id
Expand Down
6 changes: 4 additions & 2 deletions packages/neuron-wallet/src/controllers/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ export default class AppController {
if (env.isTestMode) {
return
}
await stopCkbNode()
await CKBLightRunner.getInstance().stop()
await Promise.all([
stopCkbNode(),
CKBLightRunner.getInstance().stop(),
])
}

public registerChannels(win: BrowserWindow, channels: string[]) {
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-wallet/src/controllers/networks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default class NetworksController {
await this.connectToNetwork(true)
} else {
logger.debug('Network:\tconnection dropped')
resetSyncTaskQueue.push(false)
resetSyncTaskQueue.asyncPush(false)
}
})

Expand Down
56 changes: 28 additions & 28 deletions packages/neuron-wallet/src/services/ckb-runner.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import env from '../env'
import path from 'path'
import fs from 'fs'
import { ChildProcess, spawn } from 'child_process'
import { ChildProcess, StdioNull, StdioPipe, spawn } from 'child_process'
import process from 'process'
import logger from '../utils/logger'
import SettingsService from './settings'
import MigrateSubject from '../models/subjects/migrate-subject'
import IndexerService from './indexer'
import { resetSyncTaskQueue } from '../block-sync-renderer'

const platform = (): string => {
switch (process.platform) {
Expand Down Expand Up @@ -83,35 +84,33 @@ export const startCkbNode = async () => {

logger.info('CKB:\tstarting node...')
const options = ['run', '-C', SettingsService.getInstance().ckbDataPath, '--indexer']
const stdio: (StdioNull | StdioPipe)[] = ['ignore', 'ignore', 'pipe']
if (app.isPackaged && process.env.CKB_NODE_ASSUME_VALID_TARGET) {
options.push('--assume-valid-target', process.env.CKB_NODE_ASSUME_VALID_TARGET)
stdio[1] = 'pipe'
}
ckb = spawn(ckbBinary(), options, { stdio: ['ignore', 'pipe', 'pipe'] })

ckb.stderr &&
ckb.stderr.on('data', data => {
const dataString: string = data.toString()
logger.error('CKB:\trun fail:', dataString)
if (dataString.includes('CKB wants to migrate the data into new format')) {
MigrateSubject.next({ type: 'need-migrate' })
}
})
if (app.isPackaged && process.env.CKB_NODE_ASSUME_VALID_TARGET) {
ckb.stdout &&
ckb.stdout.on('data', data => {
const dataString: string = data.toString()
if (
dataString.includes(
`can't find assume valid target temporarily, hash: Byte32(${process.env.CKB_NODE_ASSUME_VALID_TARGET})`
)
) {
isLookingValidTarget = true
lastLogTime = Date.now()
} else if (lastLogTime && Date.now() - lastLogTime > 10000) {
isLookingValidTarget = false
}
})
}
ckb = spawn(ckbBinary(), options, { stdio })

ckb.stderr?.on('data', data => {
const dataString: string = data.toString()
logger.error('CKB:\trun fail:', dataString)
if (dataString.includes('CKB wants to migrate the data into new format')) {
MigrateSubject.next({ type: 'need-migrate' })
}
})
ckb.stdout?.on('data', data => {
const dataString: string = data.toString()
if (
dataString.includes(
`can't find assume valid target temporarily, hash: Byte32(${process.env.CKB_NODE_ASSUME_VALID_TARGET})`
)
) {
isLookingValidTarget = true
lastLogTime = Date.now()
} else if (lastLogTime && Date.now() - lastLogTime > 10000) {
isLookingValidTarget = false
}
})

ckb.on('error', error => {
logger.error('CKB:\trun fail:', error)
Expand All @@ -133,7 +132,7 @@ export const stopCkbNode = () => {
if (ckb) {
logger.info('CKB:\tkilling node')
ckb.once('close', () => resolve())
ckb.kill('SIGKILL')
ckb.kill()
ckb = null
} else {
resolve()
Expand All @@ -148,6 +147,7 @@ export const clearCkbNodeCache = async () => {
await stopCkbNode()
fs.rmSync(SettingsService.getInstance().ckbDataPath, { recursive: true, force: true })
await startCkbNode()
resetSyncTaskQueue.asyncPush(true)
}

export function migrateCkbData() {
Expand Down
11 changes: 4 additions & 7 deletions packages/neuron-wallet/src/services/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { clean as cleanChain } from '../database/chain'
import SettingsService from './settings'
import startMonitor, { stopMonitor } from './monitor'
import NodeService from './node'
import { resetSyncTaskQueue } from '../block-sync-renderer'

export default class IndexerService {
private constructor() {}
Expand All @@ -19,19 +20,15 @@ export default class IndexerService {
}

static clearCache = async (clearIndexerFolder = false) => {
if (!NodeService.getInstance().isCkbNodeExternal) {
await stopMonitor('ckb')
}
await cleanChain()

if (clearIndexerFolder) {
if (!NodeService.getInstance().isCkbNodeExternal && clearIndexerFolder) {
await stopMonitor('ckb')
IndexerService.getInstance().clearData()
await new SyncedBlockNumber().setNextBlock(BigInt(0))
}

if (!NodeService.getInstance().isCkbNodeExternal) {
await startMonitor('ckb', true)
}
resetSyncTaskQueue.asyncPush(true)
}

static cleanOldIndexerData() {
Expand Down
4 changes: 3 additions & 1 deletion packages/neuron-wallet/src/services/light-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import env from '../env'
import logger from '../utils/logger'
import SettingsService from '../services/settings'
import { clean } from '../database/chain'
import { resetSyncTaskQueue } from '../block-sync-renderer'

const { app } = env

Expand Down Expand Up @@ -53,7 +54,7 @@ abstract class NodeRunner {
if (this.runnerProcess) {
logger.info('Runner:\tkilling node')
this.runnerProcess.once('close', () => resolve())
this.runnerProcess.kill('SIGKILL')
this.runnerProcess.kill()
this.runnerProcess = undefined
} else {
resolve()
Expand Down Expand Up @@ -167,5 +168,6 @@ export class CKBLightRunner extends NodeRunner {
fs.rmSync(SettingsService.getInstance().testnetLightDataPath, { recursive: true, force: true })
await clean()
await this.start()
resetSyncTaskQueue.asyncPush(true)
}
}
6 changes: 4 additions & 2 deletions packages/neuron-wallet/src/services/monitor/ckb-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ export default class CkbMonitor extends BaseMonitor {
}

async stop(): Promise<void> {
await stopCkbNode()
await CKBLightRunner.getInstance().stop()
await Promise.all([
stopCkbNode(),
CKBLightRunner.getInstance().stop()
])
}

name: string = 'ckb'
Expand Down
14 changes: 9 additions & 5 deletions packages/neuron-wallet/src/utils/ckb-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ const lightRPCProperties: Record<string, Omit<Parameters<CKBRPC['addMethod']>[0]
method: 'fetch_transaction',
paramsFormatters: [paramsFormatter.toHash],
resultFormatters: (result: { status: 'fetched' | 'fetching' | 'added' | 'not_found', data?: RPC.TransactionWithStatus }) => {
if (result.status === 'fetched' && result.data) {return resultFormatter.toTransactionWithStatus(result.data)}
return result
return {
status: result.status,
txWithStatus: result.status === 'fetched' && result.data ? resultFormatter.toTransactionWithStatus(result.data) : undefined
}
}
}
}
Expand All @@ -106,6 +108,8 @@ export class FullCKBRPC extends CKBRPC {
}
}

export type FetchTransactionReturnType = { status: 'fetched' | 'fetching' | 'added' | 'not_found', txWithStatus?: CKBComponents.TransactionWithStatus }

export class LightRPC extends Base {
setScripts: (params: LightScriptFilter[]) => Promise<null>
getScripts: () => Promise<LightScriptSyncStatus[]>
Expand All @@ -117,7 +121,7 @@ export class LightRPC extends Base {
) => Promise<{ lastCursor: HexString, txs: { txHash: HexString, txIndex: HexString, blockNumber: CKBComponents.BlockNumber }[]}>

getTransactionInLight: Base['getTransaction']
fetchTransaction: (hash: string) => Promise<CKBComponents.TransactionWithStatus | { status: 'fetching' | 'added' | 'not_found' }>
fetchTransaction: (hash: string) => Promise<FetchTransactionReturnType>

getGenesisBlock: () => Promise<CKBComponents.Block>
exceptionMethods = ['getCurrentEpoch', 'getEpochByNumber', 'getBlockHash', 'getLiveCell']
Expand Down Expand Up @@ -151,10 +155,10 @@ export class LightRPC extends Base {
if (!tx?.transaction) {
tx = await CommonUtils.retry(3, 100, async () => {
const tmp = await this.fetchTransaction(hash)
if ('status' in tmp) {
if (!tmp.txWithStatus) {
throw new Error(`transaction ${hash} status: ${tmp.status}`)
}
return tmp
return tmp.txWithStatus
})
if (!tx) {throw new Error(`Fetch transaction tx failed, please try it later: ${hash}`)}
}
Expand Down
9 changes: 0 additions & 9 deletions packages/neuron-wallet/src/utils/common.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import logger from '../utils/logger'

//TODO remove it after typescript upgrade to above 4.5
type Awaited<T> = T extends null | undefined
? T // special case for `null | undefined` when not in `--strictNullChecks` mode
: T extends object & { then(onfulfilled: infer F, ...args: infer _): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
? F extends (value: infer V, ...args: infer _) => any // if the argument to `then` is callable, extracts the first argument
? Awaited<V> // recursively unwrap the value
: never // the argument to `then` was not callable
: T // non-object or non-thenable

export default class CommonUtils {
public static sleep = (ms: number): Promise<void> => {
return new Promise(resolve => setTimeout(resolve, ms))
Expand Down
Loading