From 5d4afb1494d127be297f21ee642378154a47e33c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=A5=E5=9B=BD=E5=AE=87?= <841185308@qq.com>
Date: Thu, 30 May 2024 17:43:12 +0800
Subject: [PATCH] feat: Optimize light client external node detection (#3165)
---
.../neuron-ui/src/containers/Main/index.tsx | 76 ++++++++++++-------
packages/neuron-ui/src/locales/en.json | 3 +-
packages/neuron-ui/src/locales/es.json | 3 +-
packages/neuron-ui/src/locales/fr.json | 3 +-
packages/neuron-ui/src/locales/zh-tw.json | 3 +-
packages/neuron-ui/src/locales/zh.json | 3 +-
.../src/block-sync-renderer/sync/queue.ts | 3 +-
.../neuron-wallet/src/services/ckb-runner.ts | 8 +-
.../src/services/light-runner.ts | 16 +++-
packages/neuron-wallet/src/utils/toml.ts | 18 ++++-
.../tests/services/ckb-runner.test.ts | 16 +++-
.../tests/services/light-runner.test.ts | 30 ++++++--
.../neuron-wallet/tests/utils/toml/test.toml | 1 +
.../tests/utils/toml/toml.test.ts | 33 +++++---
14 files changed, 147 insertions(+), 69 deletions(-)
diff --git a/packages/neuron-ui/src/containers/Main/index.tsx b/packages/neuron-ui/src/containers/Main/index.tsx
index 038ca40a31..92b27d5cb3 100644
--- a/packages/neuron-ui/src/containers/Main/index.tsx
+++ b/packages/neuron-ui/src/containers/Main/index.tsx
@@ -37,6 +37,8 @@ const MainContent = () => {
[network, networks]
)
+ const isLightClientNetwork = network?.type === 2
+
useSyncChainData({
chainURL: network?.remote ?? '',
dispatch,
@@ -98,6 +100,48 @@ const MainContent = () => {
}
}, [])
+ const dialogProps = (function getDialogProps() {
+ if (isLightClientNetwork) {
+ return {
+ onConfirm: onCloseSwitchNetwork,
+ children: t('main.external-node-detected-dialog.external-node-is-light'),
+ }
+ }
+ if (sameUrlNetworks.length) {
+ return {
+ onConfirm: onSwitchNetwork,
+ children: (
+ <>
+
+ {t('main.external-node-detected-dialog.body-tips-with-network')}
+
+
@@ -124,39 +168,13 @@ const MainContent = () => {
{showEditorDialog ? (
Please allocate more disk space or migrate the data to another disk.",
diff --git a/packages/neuron-ui/src/locales/es.json b/packages/neuron-ui/src/locales/es.json
index 3ac8e1f57f..325880ce4e 100644
--- a/packages/neuron-ui/src/locales/es.json
+++ b/packages/neuron-ui/src/locales/es.json
@@ -1192,7 +1192,8 @@
"body-tips-without-network": "\"Internal Node\" está reservado para el nodo CKB incorporado, agregue una nueva opción de red para el nodo externo.",
"body-tips-with-network": "\"Internal Node\" está reservado para el nodo CKB incorporado, seleccione una de las siguientes opciones de red o agregue una nueva para el nodo externo.",
"add-network": "Agregar red",
- "ignore-external-node": "Ignorar nodo externo"
+ "ignore-external-node": "Ignorar nodo externo",
+ "external-node-is-light": "Debido a las diferentes suposiciones de seguridad del cliente ligero, Neuron no admite nodos de cliente ligero externos. ¿Desea conectarse a un \"Light Client\" ?"
},
"no-disk-space-dialog": {
"tip": "La sincronización se ha detenido debido a falta de espacio en disco.
Asigne más espacio en disco o migre los datos a otro disco.",
diff --git a/packages/neuron-ui/src/locales/fr.json b/packages/neuron-ui/src/locales/fr.json
index a609830ca1..710b521d1c 100644
--- a/packages/neuron-ui/src/locales/fr.json
+++ b/packages/neuron-ui/src/locales/fr.json
@@ -1202,7 +1202,8 @@
"body-tips-without-network": "\"Noeud interne\" est réservé au noeud CKB intégré, veuillez ajouter une nouvelle option réseau pour le noeud externe.",
"body-tips-with-network": "\"Noeud interne\" est réservé au noeud CKB intégré, veuillez sélectionner parmi les options réseau suivantes ou en ajouter une nouvelle pour le noeud externe.",
"add-network": "Ajouter un réseau",
- "ignore-external-node": "Ignorer le noeud externe"
+ "ignore-external-node": "Ignorer le noeud externe",
+ "external-node-is-light": "En raison de différentes hypothèses de sécurité du client léger, Neuron ne prend pas en charge les nœuds clients légers externes. Voulez-vous vous connecter à un \"Light Client\" ?"
},
"no-disk-space-dialog": {
"tip": "En raison d'un espace disque insuffisant, la synchronisation a été interrompue.
Veuillez allouer plus d'espace disque ou migrer les données vers un autre disque.",
diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json
index 8e61fb1c5d..3d82319d84 100644
--- a/packages/neuron-ui/src/locales/zh-tw.json
+++ b/packages/neuron-ui/src/locales/zh-tw.json
@@ -1205,7 +1205,8 @@
"body-tips-without-network": "\"Internal Node\" 僅用於連接內置節點,請添加新的網絡選項以連接外部節點。",
"body-tips-with-network": "\"Internal Node\" 僅用於連接內置節點,請選擇以下網絡選項或添加新的網絡選項以連接外部節點。",
"add-network": "添加網絡",
- "ignore-external-node": "忽略外部節點"
+ "ignore-external-node": "忽略外部節點",
+ "external-node-is-light": "由於輕客戶端的安全假設不同,Neuron 不支持外部輕客戶端節點。您想連接到 \"Light Client\" 嗎?"
},
"no-disk-space-dialog": {
"tip": "由於磁盤空間不足,同步已停止。
請分配更多磁盤空間或將數據遷移到其他磁盤。",
diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json
index d0ad40e458..0854352928 100644
--- a/packages/neuron-ui/src/locales/zh.json
+++ b/packages/neuron-ui/src/locales/zh.json
@@ -1204,7 +1204,8 @@
"body-tips-without-network": "\"Internal Node\" 仅用于连接内置节点,请添加新的网络选项以连接外部节点。",
"body-tips-with-network": "\"Internal Node\" 仅用于连接内置节点,请选择以下网络选项或添加新的网络选项以连接外部节点。",
"add-network": "添加网络",
- "ignore-external-node": "忽略外部节点"
+ "ignore-external-node": "忽略外部节点",
+ "external-node-is-light": "由于轻客户端的安全假设不同,Neuron 不支持外部轻客户端节点。您想连接到 \"Light Client\" 吗?"
},
"no-disk-space-dialog": {
"tip": "由于磁盘空间不足,同步已停止。
请分配更多磁盘空间或将数据迁移到其他磁盘。",
diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts
index 2c5d5008a5..6ff88e8e90 100644
--- a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts
+++ b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts
@@ -20,7 +20,6 @@ import { ShouldInChildProcess } from '../../exceptions'
import { AppendScript, BlockTips, Synchronizer } from './synchronizer'
import LightSynchronizer from './light-synchronizer'
import { generateRPC } from '../../utils/ckb-rpc'
-import { BUNDLED_LIGHT_CKB_URL } from '../../utils/const'
import { NetworkType } from '../../models/network'
import WalletService from '../../services/wallets'
@@ -65,7 +64,7 @@ export default class Queue {
start = async () => {
logger.info('Queue:\tstart')
try {
- if (this.#url === BUNDLED_LIGHT_CKB_URL) {
+ if (this.#nodeType === NetworkType.Light) {
this.#indexerConnector = new LightSynchronizer(this.#addresses, this.#url)
} else {
this.#indexerConnector = new FullSynchronizer(this.#addresses, this.#url, this.#nodeType)
diff --git a/packages/neuron-wallet/src/services/ckb-runner.ts b/packages/neuron-wallet/src/services/ckb-runner.ts
index 003800312d..5eae7a91ef 100644
--- a/packages/neuron-wallet/src/services/ckb-runner.ts
+++ b/packages/neuron-wallet/src/services/ckb-runner.ts
@@ -115,8 +115,12 @@ export const startCkbNode = async () => {
listenPort = await getUsablePort(rpcPort >= listenPort ? rpcPort + 1 : listenPort)
updateToml(path.join(SettingsService.getInstance().getNodeDataPath(), 'ckb.toml'), {
- rpc: `listen_address = "127.0.0.1:${rpcPort}"`,
- network: `listen_addresses = ["/ip4/0.0.0.0/tcp/${listenPort}"]`,
+ rpc: {
+ listen_address: `"127.0.0.1:${rpcPort}"`,
+ },
+ network: {
+ listen_addresses: `["/ip4/0.0.0.0/tcp/${listenPort}"]`,
+ },
})
const options = ['run', '-C', SettingsService.getInstance().getNodeDataPath(), '--indexer']
const stdio: (StdioNull | StdioPipe)[] = ['ignore', 'pipe', 'pipe']
diff --git a/packages/neuron-wallet/src/services/light-runner.ts b/packages/neuron-wallet/src/services/light-runner.ts
index 1c05fbf38e..da93dd39d2 100644
--- a/packages/neuron-wallet/src/services/light-runner.ts
+++ b/packages/neuron-wallet/src/services/light-runner.ts
@@ -81,6 +81,7 @@ export class CKBLightRunner extends NodeRunner {
protected binaryName: string = 'ckb-light-client'
protected logStream: Map
= new Map()
protected _port: number = 9000
+ protected listenPort: number = 8118
static getInstance(): CKBLightRunner {
if (!CKBLightRunner.instance) {
@@ -117,13 +118,22 @@ export class CKBLightRunner extends NodeRunner {
async updateConfig() {
const usablePort = await getUsablePort(this._port)
+ const listenPort = await getUsablePort(usablePort >= this._port ? this.listenPort + 1 : this.listenPort)
this._port = usablePort
+ this.listenPort = listenPort
const storePath = path.join(SettingsService.getInstance().getNodeDataPath(), './store')
const networkPath = path.join(SettingsService.getInstance().getNodeDataPath(), './network')
updateToml(this.configFile, {
- store: `path = "${this.platform() === 'win' ? storePath.replace(/\\/g, '\\\\') : storePath}"`,
- network: `path = "${this.platform() === 'win' ? networkPath.replace(/\\/g, '\\\\') : networkPath}"`,
- rpc: `listen_address = "127.0.0.1:${usablePort}"`,
+ store: {
+ path: `"${this.platform() === 'win' ? storePath.replace(/\\/g, '\\\\') : storePath}"`,
+ },
+ network: {
+ path: `"${this.platform() === 'win' ? networkPath.replace(/\\/g, '\\\\') : networkPath}"`,
+ listen_addresses: `["/ip4/0.0.0.0/tcp/${listenPort}"]`,
+ },
+ rpc: {
+ listen_address: `"127.0.0.1:${usablePort}"`,
+ },
})
}
diff --git a/packages/neuron-wallet/src/utils/toml.ts b/packages/neuron-wallet/src/utils/toml.ts
index b0e724513f..97a57eef78 100644
--- a/packages/neuron-wallet/src/utils/toml.ts
+++ b/packages/neuron-wallet/src/utils/toml.ts
@@ -1,7 +1,11 @@
import fs from 'fs'
import path from 'path'
-export function updateToml(filePath: string, updateValue: Record, newFilePath?: string) {
+export function updateToml(
+ filePath: string,
+ updateValue: Record>,
+ newFilePath?: string
+) {
const values = fs.readFileSync(filePath).toString().split('\n')
let field: string | undefined = undefined
const newValues = values.map(v => {
@@ -14,9 +18,15 @@ export function updateToml(filePath: string, updateValue: Record
return v
}
if (field && updateValue[field]) {
- const newLine = updateValue[field]
- field = undefined
- return newLine
+ const equalIndex = v.indexOf('=')
+ if (equalIndex !== -1) {
+ const stringBeforeEqual = v.slice(0, equalIndex)
+ const key = stringBeforeEqual.trim()
+ if (updateValue[field][key]) {
+ const newLine = `${stringBeforeEqual}= ${updateValue[field][key]}`
+ return newLine
+ }
+ }
}
return v
})
diff --git a/packages/neuron-wallet/tests/services/ckb-runner.test.ts b/packages/neuron-wallet/tests/services/ckb-runner.test.ts
index 451d9b2462..067137a946 100644
--- a/packages/neuron-wallet/tests/services/ckb-runner.test.ts
+++ b/packages/neuron-wallet/tests/services/ckb-runner.test.ts
@@ -255,8 +255,12 @@ describe('ckb runner', () => {
expect(getNodeUrl()).toBe('http://127.0.0.1:8114')
expect(getUsablePortMock).toHaveBeenLastCalledWith(8115)
expect(updateTomlMock).toBeCalledWith(path.join('/chains/mainnet', 'ckb.toml'), {
- rpc: `listen_address = "127.0.0.1:8114"`,
- network: `listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]`,
+ rpc: {
+ listen_address: `"127.0.0.1:8114"`,
+ },
+ network: {
+ listen_addresses: `["/ip4/0.0.0.0/tcp/8115"]`,
+ },
})
const promise = stopCkbNode()
stubbedCkb.emit('close')
@@ -270,8 +274,12 @@ describe('ckb runner', () => {
expect(getNodeUrl()).toBe('http://127.0.0.1:8115')
expect(getUsablePortMock).toHaveBeenLastCalledWith(8116)
expect(updateTomlMock).toBeCalledWith(path.join('/chains/mainnet', 'ckb.toml'), {
- rpc: `listen_address = "127.0.0.1:8115"`,
- network: `listen_addresses = ["/ip4/0.0.0.0/tcp/8116"]`,
+ rpc: {
+ listen_address: `"127.0.0.1:8115"`,
+ },
+ network: {
+ listen_addresses: `["/ip4/0.0.0.0/tcp/8116"]`,
+ },
})
let promise = stopCkbNode()
stubbedCkb.emit('close')
diff --git a/packages/neuron-wallet/tests/services/light-runner.test.ts b/packages/neuron-wallet/tests/services/light-runner.test.ts
index a88ed7a1ec..1a2a2fe7ed 100644
--- a/packages/neuron-wallet/tests/services/light-runner.test.ts
+++ b/packages/neuron-wallet/tests/services/light-runner.test.ts
@@ -337,32 +337,46 @@ describe('test light runner', () => {
describe('test update config', () => {
it('port is used', async () => {
- getUsablePortMock.mockResolvedValueOnce(9001)
+ getUsablePortMock.mockResolvedValueOnce(9001).mockResolvedValueOnce(8119)
lightDataPathMock.mockReturnValue('lightDataPath')
resolveMock.mockImplementation((...v: string[]) => v.join(''))
joinMock.mockImplementation((...v: string[]) => v.join(''))
await CKBLightRunner.getInstance().updateConfig()
expect(CKBLightRunner.getInstance().port).toEqual(9001)
expect(updateTomlMock).toHaveBeenCalledWith('lightDataPath./ckb_light.toml', {
- store: `path = "lightDataPath./store"`,
- network: `path = "lightDataPath./network"`,
- rpc: `listen_address = "127.0.0.1:9001"`,
+ store: {
+ path: `"lightDataPath./store"`,
+ },
+ network: {
+ listen_addresses: '["/ip4/0.0.0.0/tcp/8119"]',
+ path: `"lightDataPath./network"`,
+ },
+ rpc: {
+ listen_address: `"127.0.0.1:9001"`,
+ },
})
//reset port
getUsablePortMock.mockResolvedValueOnce(9000)
await CKBLightRunner.getInstance().updateConfig()
})
it('port is not used', async () => {
- getUsablePortMock.mockResolvedValueOnce(9000)
+ getUsablePortMock.mockResolvedValueOnce(9000).mockResolvedValueOnce(8118)
lightDataPathMock.mockReturnValue('lightDataPath')
resolveMock.mockImplementation((...v: string[]) => v.join(''))
joinMock.mockImplementation((...v: string[]) => v.join(''))
await CKBLightRunner.getInstance().updateConfig()
expect(CKBLightRunner.getInstance().port).toEqual(9000)
expect(updateTomlMock).toHaveBeenCalledWith('lightDataPath./ckb_light.toml', {
- store: `path = "lightDataPath./store"`,
- network: `path = "lightDataPath./network"`,
- rpc: `listen_address = "127.0.0.1:9000"`,
+ store: {
+ path: `"lightDataPath./store"`,
+ },
+ network: {
+ listen_addresses: '["/ip4/0.0.0.0/tcp/8118"]',
+ path: `"lightDataPath./network"`,
+ },
+ rpc: {
+ listen_address: `"127.0.0.1:9000"`,
+ },
})
})
})
diff --git a/packages/neuron-wallet/tests/utils/toml/test.toml b/packages/neuron-wallet/tests/utils/toml/test.toml
index 7a693b7094..e5c6426928 100644
--- a/packages/neuron-wallet/tests/utils/toml/test.toml
+++ b/packages/neuron-wallet/tests/utils/toml/test.toml
@@ -17,6 +17,7 @@ log_to_stdout = true
[network]
network = 127
+listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]
### Specify the public and routable network addresses
# public_addresses = []
diff --git a/packages/neuron-wallet/tests/utils/toml/toml.test.ts b/packages/neuron-wallet/tests/utils/toml/toml.test.ts
index 37ea295d0c..1184bcb430 100644
--- a/packages/neuron-wallet/tests/utils/toml/toml.test.ts
+++ b/packages/neuron-wallet/tests/utils/toml/toml.test.ts
@@ -27,41 +27,50 @@ describe('test toml', () => {
resetMock()
})
describe('test update toml', () => {
- it('update skip comment', () => {
+ it('update skip non exist key', () => {
const tomlPath = path.resolve(__dirname, './test.toml')
updateToml(tomlPath, {
- network: 'network = 127',
+ network: {
+ network1: '127',
+ },
})
- expect(writeFileSyncMock).toBeCalledWith(
- tomlPath,
- fs.readFileSync(tomlPath).toString().replace('listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]', 'network = 127')
- )
+ expect(writeFileSyncMock).toBeCalledWith(tomlPath, fs.readFileSync(tomlPath).toString())
})
it('update multi values with new file and dir exist', () => {
const tomlPath = path.resolve(__dirname, './test.toml')
existsSyncMock.mockReturnValue(true)
- updateToml(tomlPath, { network: 'network = 127', rpc: 'rpc = 8116' }, path.resolve(__dirname, './new.toml'))
+ updateToml(
+ tomlPath,
+ { network: { network: '126', listen_addresses: 'test' }, rpc: { listen_address: 'listen_address' } },
+ path.resolve(__dirname, './new.toml')
+ )
expect(writeFileSyncMock).toBeCalledWith(
path.resolve(__dirname, './new.toml'),
fs
.readFileSync(tomlPath)
.toString()
- .replace('listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]', 'network = 127')
- .replace('listen_address = "127.0.0.1:8114"', 'rpc = 8116')
+ .replace('network = 127', 'network = 126')
+ .replace('listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]', 'listen_addresses = test')
+ .replace('listen_address = "127.0.0.1:8114"', 'listen_address = listen_address')
)
})
it('update multi values with new file and dir not exist', () => {
const tomlPath = path.resolve(__dirname, './test.toml')
existsSyncMock.mockReturnValue(false)
- updateToml(tomlPath, { network: 'network = 127', rpc: 'rpc = 8116' }, path.resolve(__dirname, './new.toml'))
+ updateToml(
+ tomlPath,
+ { network: { network: '126', listen_addresses: 'test' }, rpc: { listen_address: 'listen_address' } },
+ path.resolve(__dirname, './new.toml')
+ )
expect(mkdirSyncMock).toBeCalledWith(__dirname, { recursive: true })
expect(writeFileSyncMock).toBeCalledWith(
path.resolve(__dirname, './new.toml'),
fs
.readFileSync(tomlPath)
.toString()
- .replace('listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]', 'network = 127')
- .replace('listen_address = "127.0.0.1:8114"', 'rpc = 8116')
+ .replace('network = 127', 'network = 126')
+ .replace('listen_addresses = ["/ip4/0.0.0.0/tcp/8115"]', 'listen_addresses = test')
+ .replace('listen_address = "127.0.0.1:8114"', 'listen_address = listen_address')
)
})
})