From 44ec2c768431341d6283718fe9a168dfc6621442 Mon Sep 17 00:00:00 2001 From: Xuejie Xiao Date: Thu, 7 Nov 2019 12:42:38 +0000 Subject: [PATCH 01/16] multi script group witness signing logic --- .../neuron-wallet/src/services/wallets.ts | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index fe7563a6cc..e2b70542e6 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -371,18 +371,39 @@ export default class WalletService { const paths = addressInfos.map(info => info.path) const pathAndPrivateKeys = this.getPrivateKeys(wallet, paths, password) - const witnesses: string[] = inputs!.map((input: Input) => { - const blake160: string = input.lock!.args! - const info = addressInfos.find(i => i.blake160 === blake160) - const { path } = info! - const pathAndPrivateKey = pathAndPrivateKeys.find(p => p.path === path) - if (!pathAndPrivateKey) { - throw new Error('no private key found') + const witnessesWithLockHashes = inputs!.map((input: Input) => { + return { + // TODO: fill in required DAO's type witness here + witness: { + lock: undefined, + inputType: undefined, + outputType: undefined + }, + lockHash: input.lockHash! + }; + }); + + const lockHashes = new Set(witnessesWithLockHashes.map(w => w.lockHash)); + + for (let lockHash of lockHashes) { + const firstIndex = witnessesWithLockHashes.findIndex(w => w.lockHash == lockHash); + const witnesses = witnessesWithLockHashes.filter(w => w.lockHash == lockHash).map(w => w.witness); + // A 65-byte empty signature used as placeholder + witnesses[0].lock = "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + const signedWitness = core.signWitness(privateKey)({ + transactionHash: txHash, + witnesses: witnesses + })[0] as string; + + for (let w of witnessesWithLockHashes) { + if (w.lockHash == lockHash) { + w.witness = "0x" + } } - const { privateKey } = pathAndPrivateKey - const witness = this.signWitness('', privateKey, txHash) - return witness - }) + witnessesWithLockHashes[firstIndex].witness = signedWitness; + } + + const witnesses: string[] = witnessesWithLockHashes.map(w => w.witness); tx.witnesses = witnesses From 34c95dbacfc7274ab256f90af24efed10634071d Mon Sep 17 00:00:00 2001 From: classicalliu Date: Thu, 7 Nov 2019 22:10:03 +0800 Subject: [PATCH 02/16] chore: consummate sign input group --- .../neuron-wallet/src/services/wallets.ts | 64 ++++++++++++------- .../neuron-wallet/src/types/cell-types.ts | 6 ++ 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index e2b70542e6..9db8157cc2 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -4,7 +4,7 @@ import { AccountExtendedPublicKey, PathAndPrivateKey } from 'models/keys/key' import Keystore from 'models/keys/keystore' import Store from 'models/store' import LockUtils from 'models/lock-utils' -import { TransactionWithoutHash, Input } from 'types/cell-types' +import { TransactionWithoutHash, Input, WitnessArgs } from 'types/cell-types' import ConvertTo from 'types/convert-to' import { WalletNotFound, IsRequired, UsedName } from 'exceptions' import { Address as AddressInterface } from 'database/address/dao' @@ -372,38 +372,54 @@ export default class WalletService { const pathAndPrivateKeys = this.getPrivateKeys(wallet, paths, password) const witnessesWithLockHashes = inputs!.map((input: Input) => { + const blake160: string = input.lock!.args! + const witnessArgs: WitnessArgs = { + lock: undefined, + inputType: undefined, + outputType: undefined + } return { // TODO: fill in required DAO's type witness here - witness: { - lock: undefined, - inputType: undefined, - outputType: undefined - }, - lockHash: input.lockHash! - }; - }); - - const lockHashes = new Set(witnessesWithLockHashes.map(w => w.lockHash)); - - for (let lockHash of lockHashes) { - const firstIndex = witnessesWithLockHashes.findIndex(w => w.lockHash == lockHash); - const witnesses = witnessesWithLockHashes.filter(w => w.lockHash == lockHash).map(w => w.witness); + witnessArgs, + lockHash: input.lockHash!, + witness: '', + blake160, + } + }) + + const lockHashes = new Set(witnessesWithLockHashes.map(w => w.lockHash)) + + for (const lockHash of lockHashes) { + const firstIndex = witnessesWithLockHashes.findIndex(w => w.lockHash === lockHash) + const witnessesArgsWithBlake160 = witnessesWithLockHashes + .filter(w => w.lockHash === lockHash) + .map(w => ({args: w.witnessArgs, blake160: w.blake160})) // A 65-byte empty signature used as placeholder - witnesses[0].lock = "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - const signedWitness = core.signWitness(privateKey)({ + witnessesArgsWithBlake160[0].args.lock = '0x' + '0'.repeat(130) + + const blake160: string = witnessesArgsWithBlake160[0].blake160 + const info = addressInfos.find(i => i.blake160 === blake160) + const { path } = info! + const pathAndPrivateKey = pathAndPrivateKeys.find(p => p.path === path) + if (!pathAndPrivateKey) { + throw new Error('no private key found') + } + const { privateKey } = pathAndPrivateKey + + const signedWitness = core.signWitnesses(privateKey)({ transactionHash: txHash, - witnesses: witnesses - })[0] as string; + witnesses: witnessesArgsWithBlake160.map(w => w.args) + })[0] as string - for (let w of witnessesWithLockHashes) { - if (w.lockHash == lockHash) { - w.witness = "0x" + for (const w of witnessesWithLockHashes) { + if (w.lockHash === lockHash) { + w.witness = '0x' } } - witnessesWithLockHashes[firstIndex].witness = signedWitness; + witnessesWithLockHashes[firstIndex].witness = signedWitness } - const witnesses: string[] = witnessesWithLockHashes.map(w => w.witness); + const witnesses: string[] = witnessesWithLockHashes.map(w => w.witness) tx.witnesses = witnesses diff --git a/packages/neuron-wallet/src/types/cell-types.ts b/packages/neuron-wallet/src/types/cell-types.ts index 3dce8003fc..43cf664568 100644 --- a/packages/neuron-wallet/src/types/cell-types.ts +++ b/packages/neuron-wallet/src/types/cell-types.ts @@ -57,6 +57,12 @@ export interface Transaction extends TransactionWithoutHash { hash: string } +export interface WitnessArgs { + lock: string | undefined + inputType: string | undefined + outputType: string | undefined +} + export interface TxStatus { blockHash: string | null status: 'pending' | 'proposed' | 'committed' From 41600eac58b2296fcd1f3e96c6176f1c20714e52 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Thu, 7 Nov 2019 22:23:19 +0800 Subject: [PATCH 03/16] fix: skip get previous tx when cellbase --- packages/neuron-wallet/src/services/sync/get-blocks.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/neuron-wallet/src/services/sync/get-blocks.ts b/packages/neuron-wallet/src/services/sync/get-blocks.ts index b102b498a0..7cc6a02fb0 100644 --- a/packages/neuron-wallet/src/services/sync/get-blocks.ts +++ b/packages/neuron-wallet/src/services/sync/get-blocks.ts @@ -46,7 +46,12 @@ export default class GetBlocks { const checkTx = new CheckTx(tx, this.url) const addresses = await checkTx.check(lockHashes) if (addresses.length > 0) { - for (const input of tx.inputs!) { + const inputs = tx.inputs! + for (let i = 0; i < inputs.length; ++i) { + if (i === 0) { + continue + } + const input = inputs[i] const previousTxHash = input.previousOutput!.txHash let previousTxWithStatus = cachedPreviousTxs.get(previousTxHash) if (!previousTxWithStatus) { From 7e8a57866a73e511ce7e5d35e71aad355f792e7b Mon Sep 17 00:00:00 2001 From: classicalliu Date: Thu, 7 Nov 2019 22:30:49 +0800 Subject: [PATCH 04/16] fix: skip get previous tx when cellbase in indexer --- packages/neuron-wallet/src/services/indexer/queue.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/neuron-wallet/src/services/indexer/queue.ts b/packages/neuron-wallet/src/services/indexer/queue.ts index 7ba5baa80f..8274fca65b 100644 --- a/packages/neuron-wallet/src/services/indexer/queue.ts +++ b/packages/neuron-wallet/src/services/indexer/queue.ts @@ -48,6 +48,8 @@ export default class IndexerQueue { private url: string + private emptyTxHash = '0x' + '0'.repeat(64) + constructor(url: string, lockHashInfos: LockHashInfo[], tipNumberSubject: Subject) { this.lockHashInfos = lockHashInfos this.url = url @@ -213,6 +215,9 @@ export default class IndexerQueue { if (!txEntity || !txEntity.blockHash) { if (!txEntity) { for (const input of transaction.inputs!) { + if (input.previousOutput!.txHash === this.emptyTxHash) { + continue + } const previousTxWithStatus = await this.getBlocksService.getTransaction(input.previousOutput!.txHash) const previousTx = TypeConvert.toTransaction(previousTxWithStatus.transaction) const previousOutput = previousTx.outputs![+input.previousOutput!.index] From e2fd4106e8c7b6b03ceaf456b869e514f37aebb9 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 09:39:38 +0900 Subject: [PATCH 05/16] refactor: Remove some local vars, extract getting private key out of the input group loop --- .../neuron-wallet/src/services/wallets.ts | 49 +++++++------------ 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 9db8157cc2..0e00c5270e 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -344,13 +344,8 @@ export default class WalletService { return this.sendTx(walletID, tx, password, description) } - public sendTx = async ( - walletID: string = '', - tx: TransactionWithoutHash, - password: string = '', - description: string = '' - ) => { - const wallet = await this.get(walletID) + public sendTx = async (walletID: string = '', tx: TransactionWithoutHash, password: string = '', description: string = '') => { + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } @@ -359,19 +354,24 @@ export default class WalletService { throw new IsRequired('Password') } - const addressInfos = await this.getAddressInfos(walletID) - let txHash: string = core.utils.rawTransactionToHash(ConvertTo.toSdkTxWithoutHash(tx)) if (!txHash.startsWith('0x')) { txHash = `0x${txHash}` } - const { inputs } = tx - + const addressInfos = await this.getAddressInfos(walletID) const paths = addressInfos.map(info => info.path) const pathAndPrivateKeys = this.getPrivateKeys(wallet, paths, password) + const findPrivateKey = (blake160: string) => { + const { path } = addressInfos.find(i => i.blake160 === blake160)! + const pathAndPrivateKey = pathAndPrivateKeys.find(p => p.path === path) + if (!pathAndPrivateKey) { + throw new Error('no private key found') + } + return pathAndPrivateKey.privateKey + } - const witnessesWithLockHashes = inputs!.map((input: Input) => { + const witnessesWithLockHashes = tx.inputs!.map((input: Input) => { const blake160: string = input.lock!.args! const witnessArgs: WitnessArgs = { lock: undefined, @@ -397,15 +397,7 @@ export default class WalletService { // A 65-byte empty signature used as placeholder witnessesArgsWithBlake160[0].args.lock = '0x' + '0'.repeat(130) - const blake160: string = witnessesArgsWithBlake160[0].blake160 - const info = addressInfos.find(i => i.blake160 === blake160) - const { path } = info! - const pathAndPrivateKey = pathAndPrivateKeys.find(p => p.path === path) - if (!pathAndPrivateKey) { - throw new Error('no private key found') - } - const { privateKey } = pathAndPrivateKey - + const privateKey = findPrivateKey(witnessesArgsWithBlake160[0].blake160) const signedWitness = core.signWitnesses(privateKey)({ transactionHash: txHash, witnesses: witnessesArgsWithBlake160.map(w => w.args) @@ -419,9 +411,7 @@ export default class WalletService { witnessesWithLockHashes[firstIndex].witness = signedWitness } - const witnesses: string[] = witnessesWithLockHashes.map(w => w.witness) - - tx.witnesses = witnesses + tx.witnesses = witnessesWithLockHashes.map(w => w.witness) const txToSend = ConvertTo.toSdkTxWithoutHash(tx) await core.rpc.sendTransaction(txToSend) @@ -440,9 +430,7 @@ export default class WalletService { return txHash } - public calculateFee = async ( - tx: TransactionWithoutHash - ) => { + public calculateFee = async (tx: TransactionWithoutHash) => { const inputCapacities = tx.inputs! .map(input => BigInt(input.capacity!)) .reduce((result, c) => result + c, BigInt(0)) @@ -511,12 +499,11 @@ export default class WalletService { // path is a BIP44 full path such as "m/44'/309'/0'/0/0" public getAddressInfos = async (walletID: string): Promise => { - const wallet = await this.get(walletID) + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } - const addrs = await AddressService.allAddressesByWalletId(walletID) - return addrs + return AddressService.allAddressesByWalletId(walletID) } public getChangeAddress = async (): Promise => { @@ -537,7 +524,7 @@ export default class WalletService { })[0] as string } - // Derivate all child private keys for specified BIP44 paths. + // Derive all child private keys for specified BIP44 paths. public getPrivateKeys = (wallet: Wallet, paths: string[], password: string): PathAndPrivateKey[] => { const masterPrivateKey = wallet.loadKeystore().extendedPrivateKey(password) const masterKeychain = new Keychain( From 0258f57d927d775dd3fe47348139881e0dbeba3e Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 09:56:11 +0900 Subject: [PATCH 06/16] refactor: No need to prefix 0x as rawTransactionToHash returns txhash with that already --- packages/neuron-wallet/src/services/wallets.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 0e00c5270e..3cbc6b6a1d 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -354,10 +354,7 @@ export default class WalletService { throw new IsRequired('Password') } - let txHash: string = core.utils.rawTransactionToHash(ConvertTo.toSdkTxWithoutHash(tx)) - if (!txHash.startsWith('0x')) { - txHash = `0x${txHash}` - } + const txHash = core.utils.rawTransactionToHash(ConvertTo.toSdkTxWithoutHash(tx)) const addressInfos = await this.getAddressInfos(walletID) const paths = addressInfos.map(info => info.path) From 4da38dea84c41720599921edaaa4e75844fab590 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 10:11:59 +0900 Subject: [PATCH 07/16] refactor: Prefer shorter variable names --- .../neuron-wallet/src/services/wallets.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 3cbc6b6a1d..971f7a3fcd 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -368,7 +368,7 @@ export default class WalletService { return pathAndPrivateKey.privateKey } - const witnessesWithLockHashes = tx.inputs!.map((input: Input) => { + const witnessSigningEntries = tx.inputs!.map((input: Input) => { const blake160: string = input.lock!.args! const witnessArgs: WitnessArgs = { lock: undefined, @@ -384,31 +384,29 @@ export default class WalletService { } }) - const lockHashes = new Set(witnessesWithLockHashes.map(w => w.lockHash)) + const lockHashes = new Set(witnessSigningEntries.map(w => w.lockHash)) for (const lockHash of lockHashes) { - const firstIndex = witnessesWithLockHashes.findIndex(w => w.lockHash === lockHash) - const witnessesArgsWithBlake160 = witnessesWithLockHashes - .filter(w => w.lockHash === lockHash) - .map(w => ({args: w.witnessArgs, blake160: w.blake160})) + const firstIndex = witnessSigningEntries.findIndex(w => w.lockHash === lockHash) + const witnessesArgs = witnessSigningEntries.filter(w => w.lockHash === lockHash) // A 65-byte empty signature used as placeholder - witnessesArgsWithBlake160[0].args.lock = '0x' + '0'.repeat(130) + witnessesArgs[0].witnessArgs.lock = '0x' + '0'.repeat(130) - const privateKey = findPrivateKey(witnessesArgsWithBlake160[0].blake160) + const privateKey = findPrivateKey(witnessesArgs[0].blake160) const signedWitness = core.signWitnesses(privateKey)({ transactionHash: txHash, - witnesses: witnessesArgsWithBlake160.map(w => w.args) + witnesses: witnessesArgs.map(w => w.witnessArgs) })[0] as string - for (const w of witnessesWithLockHashes) { + for (const w of witnessSigningEntries) { if (w.lockHash === lockHash) { w.witness = '0x' } } - witnessesWithLockHashes[firstIndex].witness = signedWitness + witnessSigningEntries[firstIndex].witness = signedWitness } - tx.witnesses = witnessesWithLockHashes.map(w => w.witness) + tx.witnesses = witnessSigningEntries.map(w => w.witness) const txToSend = ConvertTo.toSdkTxWithoutHash(tx) await core.rpc.sendTransaction(txToSend) From aeeb464d89528a0314a02cf0ad12a753cd14fc90 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Fri, 8 Nov 2019 10:24:25 +0800 Subject: [PATCH 08/16] fix: skip the cellbase tx, not the first input --- .../src/services/sync/get-blocks.ts | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/packages/neuron-wallet/src/services/sync/get-blocks.ts b/packages/neuron-wallet/src/services/sync/get-blocks.ts index 7cc6a02fb0..3dd65c13c9 100644 --- a/packages/neuron-wallet/src/services/sync/get-blocks.ts +++ b/packages/neuron-wallet/src/services/sync/get-blocks.ts @@ -42,27 +42,25 @@ export default class GetBlocks { const cachedPreviousTxs = new Map() for (const block of blocks) { logger.debug(`checking block #${block.header.number}, ${block.transactions.length} txs`) - for (const tx of block.transactions) { + for (let i = 0; i < block.transactions.length; ++i) { + const tx = block.transactions[i] const checkTx = new CheckTx(tx, this.url) const addresses = await checkTx.check(lockHashes) if (addresses.length > 0) { - const inputs = tx.inputs! - for (let i = 0; i < inputs.length; ++i) { - if (i === 0) { - continue + if (i > 0) { + for (const input of tx.inputs!) { + const previousTxHash = input.previousOutput!.txHash + let previousTxWithStatus = cachedPreviousTxs.get(previousTxHash) + if (!previousTxWithStatus) { + previousTxWithStatus = await this.getTransaction(previousTxHash) + cachedPreviousTxs.set(previousTxHash, previousTxWithStatus) + } + const previousTx = TypeConvert.toTransaction(previousTxWithStatus.transaction) + const previousOutput = previousTx.outputs![+input.previousOutput!.index] + input.lock = previousOutput.lock + input.lockHash = LockUtils.lockScriptToHash(input.lock) + input.capacity = previousOutput.capacity } - const input = inputs[i] - const previousTxHash = input.previousOutput!.txHash - let previousTxWithStatus = cachedPreviousTxs.get(previousTxHash) - if (!previousTxWithStatus) { - previousTxWithStatus = await this.getTransaction(previousTxHash) - cachedPreviousTxs.set(previousTxHash, previousTxWithStatus) - } - const previousTx = TypeConvert.toTransaction(previousTxWithStatus.transaction) - const previousOutput = previousTx.outputs![+input.previousOutput!.index] - input.lock = previousOutput.lock - input.lockHash = LockUtils.lockScriptToHash(input.lock) - input.capacity = previousOutput.capacity } await TransactionPersistor.saveFetchTx(tx) addressesUsedSubject.next({ From 879d2276e2a801e520bcc0d9353c4eaafbc78d5c Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 8 Nov 2019 10:54:20 +0800 Subject: [PATCH 09/16] feat: remove skip data and type toggle --- .../src/components/GeneralSetting/index.tsx | 32 +++---------------- .../neuron-ui/src/services/remote/index.ts | 1 - .../src/services/remote/skipDataAndType.ts | 7 ---- .../src/states/initStates/settings.ts | 4 +-- .../stateProvider/actionCreators/app.ts | 2 -- .../stateProvider/actionCreators/index.ts | 3 -- .../actionCreators/skipDataAndType.ts | 21 ------------ .../src/states/stateProvider/reducer.ts | 16 ---------- .../src/stories/GeneralSetting.stories.tsx | 9 +----- packages/neuron-ui/src/types/App/index.d.ts | 4 +-- packages/neuron-wallet/src/controllers/api.ts | 19 +---------- .../neuron-wallet/src/controllers/index.ts | 4 +-- .../src/controllers/skip-data-and-type.ts | 22 ------------- .../tests-e2e/tests/generalSettings.ts | 29 +---------------- 14 files changed, 10 insertions(+), 163 deletions(-) delete mode 100644 packages/neuron-ui/src/services/remote/skipDataAndType.ts delete mode 100644 packages/neuron-ui/src/states/stateProvider/actionCreators/skipDataAndType.ts delete mode 100644 packages/neuron-wallet/src/controllers/skip-data-and-type.ts diff --git a/packages/neuron-ui/src/components/GeneralSetting/index.tsx b/packages/neuron-ui/src/components/GeneralSetting/index.tsx index 1ddde34fd1..ced18634cf 100644 --- a/packages/neuron-ui/src/components/GeneralSetting/index.tsx +++ b/packages/neuron-ui/src/components/GeneralSetting/index.tsx @@ -1,32 +1,8 @@ -import React, { useMemo } from 'react' -import { Stack, Toggle } from 'office-ui-fabric-react' -import { useTranslation } from 'react-i18next' +import React from 'react' +import { Stack } from 'office-ui-fabric-react' -import { StateWithDispatch } from 'states/stateProvider/reducer' -import { setSkipDataAndType } from 'states/stateProvider/actionCreators' - -const GeneralSetting = ({ - settings: { - general: { skipDataAndType }, - }, - dispatch, -}: React.PropsWithoutRef) => { - const [t] = useTranslation() - const [onSetSkipDataAndType] = useMemo(() => [() => setSkipDataAndType(!skipDataAndType)(dispatch)], [ - dispatch, - skipDataAndType, - ]) - return ( - - - - ) +const GeneralSetting = () => { + return } GeneralSetting.displayName = 'GeneralSetting' diff --git a/packages/neuron-ui/src/services/remote/index.ts b/packages/neuron-ui/src/services/remote/index.ts index ca16160094..4d0f24c5ae 100644 --- a/packages/neuron-ui/src/services/remote/index.ts +++ b/packages/neuron-ui/src/services/remote/index.ts @@ -2,7 +2,6 @@ export * from './app' export * from './wallets' export * from './networks' export * from './transactions' -export * from './skipDataAndType' const REMOTE_MODULE_NOT_FOUND = 'The remote module is not found, please make sure the UI is running inside the Electron App' diff --git a/packages/neuron-ui/src/services/remote/skipDataAndType.ts b/packages/neuron-ui/src/services/remote/skipDataAndType.ts deleted file mode 100644 index b0a8cd3253..0000000000 --- a/packages/neuron-ui/src/services/remote/skipDataAndType.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { apiMethodWrapper } from './apiMethodWrapper' - -export const setSkipDataAndType = apiMethodWrapper((api: any) => (params: Controller.SetSkipAndTypeParam) => { - return api.updateSkipDataAndType(params) -}) - -export default { setSkipDataAndType } diff --git a/packages/neuron-ui/src/states/initStates/settings.ts b/packages/neuron-ui/src/states/initStates/settings.ts index 758fe27ccb..87049df80e 100644 --- a/packages/neuron-ui/src/states/initStates/settings.ts +++ b/packages/neuron-ui/src/states/initStates/settings.ts @@ -1,9 +1,7 @@ import { wallets, networks } from 'services/localCache' export const settingsState: State.Settings = { - general: { - skipDataAndType: false, - }, + general: {}, networks: networks.load(), wallets: wallets.load(), } diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts index 1111c41d9d..c0446b5e7d 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts @@ -26,7 +26,6 @@ export const initAppState = () => (dispatch: StateDispatch, history: any) => { syncedBlockNumber = '', connectionStatus = false, codeHash = '', - skipDataAndType = false, } = res.result dispatch({ type: NeuronWalletActions.InitAppState, @@ -39,7 +38,6 @@ export const initAppState = () => (dispatch: StateDispatch, history: any) => { syncedBlockNumber, connectionStatus, codeHash, - skipDataAndType, }, }) if (!wallet) { diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/index.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/index.ts index bb72ba1655..b1ea341f64 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/index.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/index.ts @@ -2,19 +2,16 @@ import app from './app' import wallets from './wallets' import transactions from './transactions' import settings from './settings' -import skipDataAndType from './skipDataAndType' export * from './app' export * from './wallets' export * from './transactions' export * from './settings' -export * from './skipDataAndType' export const actionCreators = { ...app, ...wallets, ...transactions, ...settings, - ...skipDataAndType, } export default actionCreators diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/skipDataAndType.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/skipDataAndType.ts deleted file mode 100644 index 712613d89f..0000000000 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/skipDataAndType.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { setSkipDataAndType as setRemoteSkipDataAndType } from 'services/remote' -import { failureResToNotification } from 'utils/formatters' -import { StateDispatch, NeuronWalletActions } from '../reducer' -import { addNotification } from './app' - -export const setSkipDataAndType = (skip: Controller.SetSkipAndTypeParam) => (dispatch: StateDispatch) => { - setRemoteSkipDataAndType(skip).then(res => { - if (res.status === 1) { - dispatch({ - type: NeuronWalletActions.UpdateSkipDataAndType, - payload: res.result, - }) - } else { - addNotification(failureResToNotification(res))(dispatch) - } - }) -} - -export default { - setSkipDataAndType, -} diff --git a/packages/neuron-ui/src/states/stateProvider/reducer.ts b/packages/neuron-ui/src/states/stateProvider/reducer.ts index 0294211081..84beb07297 100644 --- a/packages/neuron-ui/src/states/stateProvider/reducer.ts +++ b/packages/neuron-ui/src/states/stateProvider/reducer.ts @@ -18,8 +18,6 @@ export enum NeuronWalletActions { // Connection UpdateConnectionStatus = 'updateConnectionStatus', UpdateSyncedBlockNumber = 'updateSyncedBlockNumber', - // settings - UpdateSkipDataAndType = 'updateSkipDataAndType', } export enum AppActions { UpdateTransactionID = 'updateTransactionID', @@ -79,7 +77,6 @@ export const reducer = ( syncedBlockNumber, connectionStatus, codeHash, - skipDataAndType, } = payload return { ...state, @@ -95,25 +92,12 @@ export const reducer = ( settings: { general: { ...state.settings.general, - skipDataAndType, }, networks, wallets, }, } } - case NeuronWalletActions.UpdateSkipDataAndType: { - return { - ...state, - settings: { - ...settings, - general: { - ...settings.general, - skipDataAndType: payload, - }, - }, - } - } case NeuronWalletActions.UpdateCodeHash: { return { ...state, diff --git a/packages/neuron-ui/src/stories/GeneralSetting.stories.tsx b/packages/neuron-ui/src/stories/GeneralSetting.stories.tsx index 3438d16907..b016ba1553 100644 --- a/packages/neuron-ui/src/stories/GeneralSetting.stories.tsx +++ b/packages/neuron-ui/src/stories/GeneralSetting.stories.tsx @@ -2,16 +2,9 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { withKnobs } from '@storybook/addon-knobs' import GeneralSetting from 'components/GeneralSetting' -import initStates from 'states/initStates' const stories = storiesOf('GeneralSettings', module) stories.addDecorator(withKnobs).add('With knobs', () => { - const props = { - ...initStates, - settings: { - ...initStates.settings, - }, - } - return {}} /> + return }) diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 06ee4dd535..377191480b 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -143,9 +143,7 @@ declare namespace State { } } interface Settings { - general: { - skipDataAndType: boolean - } + general: {} networks: Network[] wallets: WalletIdentity[] } diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts index 6505cddd44..b141f8e72d 100644 --- a/packages/neuron-wallet/src/controllers/api.ts +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -4,17 +4,10 @@ import env from 'env' import i18n from 'utils/i18n' import { popContextMenu } from './app/menu' import { showWindow } from './app/show-window' -import { - TransactionsController, - WalletsController, - SyncInfoController, - SkipDataAndTypeController, - NetworksController -} from 'controllers' +import { TransactionsController, WalletsController, SyncInfoController, NetworksController } from 'controllers' import { NetworkType, NetworkID, Network } from 'types/network' import NetworksService from 'services/networks' import WalletsService from 'services/wallets' -import SkipDataAndType from 'services/settings/skip-data-and-type' import { ConnectionStatusSubject } from 'models/subjects/node' import { SystemScriptSubject } from 'models/subjects/system-script' import { MapApiResponse } from 'decorators' @@ -82,8 +75,6 @@ export default class ApiController { }).then(res => res.result) : [] - const skipDataAndType = SkipDataAndType.getInstance().get() - const initState = { currentWallet, wallets: [...wallets.map(({ name, id }) => ({ id, name }))], @@ -94,7 +85,6 @@ export default class ApiController { syncedBlockNumber, connectionStatus, codeHash, - skipDataAndType, } return { status: ResponseCode.Success, result: initState } @@ -265,11 +255,4 @@ export default class ApiController { public static async showTransactionDetails(hash: string) { showWindow(`${env.mainURL}#/transaction/${hash}`, i18n.t(`messageBox.transaction.title`, { hash })) } - - // Misc - - @MapApiResponse - public static async updateSkipDataAndType(skip: boolean) { - return SkipDataAndTypeController.update(skip) - } } diff --git a/packages/neuron-wallet/src/controllers/index.ts b/packages/neuron-wallet/src/controllers/index.ts index 0c20b50af4..ece40cf0d7 100644 --- a/packages/neuron-wallet/src/controllers/index.ts +++ b/packages/neuron-wallet/src/controllers/index.ts @@ -3,7 +3,6 @@ import NetworksController from './networks' import WalletsController from './wallets' import TransactionsController from './transactions' import SyncInfoController from './sync-info' -import SkipDataAndTypeController from './skip-data-and-type' import UpdateController from './update' import ApiController from './api' @@ -14,7 +13,6 @@ export { WalletsController, TransactionsController, SyncInfoController, - SkipDataAndTypeController, UpdateController, - ApiController + ApiController, } diff --git a/packages/neuron-wallet/src/controllers/skip-data-and-type.ts b/packages/neuron-wallet/src/controllers/skip-data-and-type.ts deleted file mode 100644 index 9b88d1d19f..0000000000 --- a/packages/neuron-wallet/src/controllers/skip-data-and-type.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ResponseCode } from 'utils/const' -import SkipDataAndType from 'services/settings/skip-data-and-type' - -export default class SkipDataAndTypeController { - public static async update(skip: boolean): Promise> { - SkipDataAndType.getInstance().update(skip) - - return { - status: ResponseCode.Success, - result: skip, - } - } - - public static async get(): Promise> { - const skip = SkipDataAndType.getInstance().get() - - return { - status: ResponseCode.Success, - result: skip, - } - } -} diff --git a/packages/neuron-wallet/tests-e2e/tests/generalSettings.ts b/packages/neuron-wallet/tests-e2e/tests/generalSettings.ts index 59f2ee70ca..67b56d723c 100644 --- a/packages/neuron-wallet/tests-e2e/tests/generalSettings.ts +++ b/packages/neuron-wallet/tests-e2e/tests/generalSettings.ts @@ -1,37 +1,10 @@ import Application from '../application' -/** - * 1. navigate to the general settings handleViewError - * 2. the toggle of skip data and type script should be off - * 3. click on the toggles and their statuses should be updated - * 4. refresh the view and the statuses should be preserved - */ export default (app: Application) => { beforeAll(async () => { await app.gotoSettingPageFromMenu() await app.waitUntilLoaded() }) - describe('Test general settings', () => { - app.test('Check the initialized statuses', async () => { - const { client } = app.spectron - const toggles = await client.$$('button[role=switch]') - expect((await client.elementIdAttribute(toggles[0].value.ELEMENT, 'aria-checked')).value).toBe('true') - }) - - app.test('toggle SkipDataAndType to false', async () => { - const { client } = app.spectron - await app.waitUntilLoaded() - const toggles = await client.$$('button[role=switch]') - - toggles.forEach((_, idx) => { - client.elementIdClick(toggles[idx].value.ELEMENT) - }) - - await app.waitUntilLoaded() - expect((await client.elementIdAttribute(toggles[0].value.ELEMENT, 'aria-checked')).value).toBe('false') - }) - - test.skip('Toggle statuses should be preserved', async () => {}) - }) + describe.skip('Test general settings', () => {}) } From 9bdece6edd9ed9bd476a49d030502215392a5937 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 12:46:00 +0900 Subject: [PATCH 10/16] feat: Disable search history by amount --- .../src/services/tx/transaction-service.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/neuron-wallet/src/services/tx/transaction-service.ts b/packages/neuron-wallet/src/services/tx/transaction-service.ts index 44ed3b8578..c16d79de40 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-service.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-service.ts @@ -69,7 +69,7 @@ export class TransactionsService { return base } if (type === SearchType.Address) { - const lockHashes: string[] = await new LockUtils(await LockUtils.systemScript()).addressToAllLockHashes(value) + const lockHashes = new LockUtils(await LockUtils.systemScript()).addressToAllLockHashes(value) return ['input.lockHash IN (:...lockHashes) OR output.lockHash IN (:...lockHashes)', { lockHashes }] } if (type === SearchType.TxHash) { @@ -92,7 +92,15 @@ export class TransactionsService { return base } - public static searchByAmount = async (params: TransactionsByLockHashesParam, amount: string) => { + /// TODO: Decide if this should be supported. + /// For now just return empty results. + /// The second query (one after `if (result.totalCount > 100) {` will mostly cuase `SQLITE_ERROR: too many SQL variables` error. + public static searchByAmount = async (_params: TransactionsByLockHashesParam, _amount: string) => { + return { + totalCount: 0, + items: [] + } + /* // 1. get all transactions const result = await TransactionsService.getAll({ pageNo: 1, @@ -114,7 +122,7 @@ export class TransactionsService { return { totalCount: txs.length || 0, items: txs.slice(skip, skip + params.pageSize), - } + }*/ } public static getAll = async ( From 5d59f3dcf45ebb9ebb57717220d3b11b70a060c3 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Fri, 8 Nov 2019 12:25:03 +0800 Subject: [PATCH 11/16] fix: replace with empty string in input group rename witness --- packages/neuron-wallet/src/services/wallets.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 971f7a3fcd..82f01d1238 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -393,15 +393,15 @@ export default class WalletService { witnessesArgs[0].witnessArgs.lock = '0x' + '0'.repeat(130) const privateKey = findPrivateKey(witnessesArgs[0].blake160) - const signedWitness = core.signWitnesses(privateKey)({ + const signed = core.signWitnesses(privateKey)({ transactionHash: txHash, - witnesses: witnessesArgs.map(w => w.witnessArgs) - })[0] as string + witnesses: [witnessesArgs[0].witnessArgs, ...Array.from({length: witnessesArgs.length - 1}).map(() => '0x')] + }) + const signedWitness = signed[0] as string - for (const w of witnessSigningEntries) { - if (w.lockHash === lockHash) { - w.witness = '0x' - } + const entires = witnessSigningEntries.filter(e => e.lockHash === lockHash) + for (let i = 0; i < entires.length; ++i) { + entires[i].witness = signed[i] as string } witnessSigningEntries[firstIndex].witness = signedWitness } From 9a117be0f754f79f67bfd20ee1906e161fc46412 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Fri, 8 Nov 2019 12:40:13 +0800 Subject: [PATCH 12/16] chore: support for args in input groups remain witnesses --- packages/neuron-wallet/src/services/wallets.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 82f01d1238..b027aafee8 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -14,7 +14,7 @@ import AddressesUsedSubject from 'models/subjects/addresses-used-subject' import { WalletListSubject, CurrentWalletSubject } from 'models/subjects/wallets' import dataUpdateSubject from 'models/subjects/data-update' import CellsService from 'services/cells' -import { AddressPrefix } from '@nervosnetwork/ckb-sdk-utils' +import { AddressPrefix, serializeWitnessArgs } from '@nervosnetwork/ckb-sdk-utils' import NodeService from './node' import FileService from './file' @@ -393,9 +393,21 @@ export default class WalletService { witnessesArgs[0].witnessArgs.lock = '0x' + '0'.repeat(130) const privateKey = findPrivateKey(witnessesArgs[0].blake160) + + const serializedWitnesses = witnessesArgs + .map(value => value.witnessArgs) + .map((value: WitnessArgs, index: number) => { + if (index === 0) { + return value + } + if (value.lock === undefined && value.inputType === undefined && value.outputType === undefined) { + return '0x' + } + return serializeWitnessArgs(value) + }) const signed = core.signWitnesses(privateKey)({ transactionHash: txHash, - witnesses: [witnessesArgs[0].witnessArgs, ...Array.from({length: witnessesArgs.length - 1}).map(() => '0x')] + witnesses: serializedWitnesses }) const signedWitness = signed[0] as string From 5f816b7375aa635b76036c5851d838fe9021e164 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Fri, 8 Nov 2019 12:46:25 +0800 Subject: [PATCH 13/16] chore: remove unused firstIndex --- packages/neuron-wallet/src/services/wallets.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index b027aafee8..4a893e4c5c 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -387,7 +387,6 @@ export default class WalletService { const lockHashes = new Set(witnessSigningEntries.map(w => w.lockHash)) for (const lockHash of lockHashes) { - const firstIndex = witnessSigningEntries.findIndex(w => w.lockHash === lockHash) const witnessesArgs = witnessSigningEntries.filter(w => w.lockHash === lockHash) // A 65-byte empty signature used as placeholder witnessesArgs[0].witnessArgs.lock = '0x' + '0'.repeat(130) @@ -409,13 +408,10 @@ export default class WalletService { transactionHash: txHash, witnesses: serializedWitnesses }) - const signedWitness = signed[0] as string - const entires = witnessSigningEntries.filter(e => e.lockHash === lockHash) - for (let i = 0; i < entires.length; ++i) { - entires[i].witness = signed[i] as string + for (let i = 0; i < witnessesArgs.length; ++i) { + witnessesArgs[i].witness = signed[i] as string } - witnessSigningEntries[firstIndex].witness = signedWitness } tx.witnesses = witnessSigningEntries.map(w => w.witness) From ad3e39b338c946379068a7b3cca0145f5bf689c1 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Fri, 8 Nov 2019 13:16:22 +0800 Subject: [PATCH 14/16] chore: reduce loop cycles --- packages/neuron-wallet/src/services/wallets.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 4a893e4c5c..34692e239a 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -394,15 +394,15 @@ export default class WalletService { const privateKey = findPrivateKey(witnessesArgs[0].blake160) const serializedWitnesses = witnessesArgs - .map(value => value.witnessArgs) - .map((value: WitnessArgs, index: number) => { + .map((value: any, index: number) => { + const args = value.witnessArgs if (index === 0) { - return value + return args } - if (value.lock === undefined && value.inputType === undefined && value.outputType === undefined) { + if (args.lock === undefined && args.inputType === undefined && args.outputType === undefined) { return '0x' } - return serializeWitnessArgs(value) + return serializeWitnessArgs(args) }) const signed = core.signWitnesses(privateKey)({ transactionHash: txHash, From 5f6995374702c267e9fd7df4971cd8621499d279 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 14:56:35 +0900 Subject: [PATCH 15/16] chore: Bump to v0.24.2 --- lerna.json | 2 +- package.json | 2 +- packages/neuron-ui/package.json | 2 +- packages/neuron-wallet/package.json | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lerna.json b/lerna.json index 56eecf45f7..110180cdb8 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.24.1", + "version": "0.24.2", "npmClient": "yarn", "useWorkspaces": true } diff --git a/package.json b/package.json index f9a65aa48b..845830554b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "neuron", "productName": "Neuron", "description": "CKB Neuron Wallet", - "version": "0.24.1", + "version": "0.24.2", "private": true, "author": { "name": "Nervos Core Dev", diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index 2247d22eda..335ac2a91f 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -1,6 +1,6 @@ { "name": "neuron-ui", - "version": "0.24.1", + "version": "0.24.2", "private": true, "author": { "name": "Nervos Core Dev", diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 150733eb54..429f913134 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -3,7 +3,7 @@ "productName": "Neuron", "description": "CKB Neuron Wallet", "homepage": "https://www.nervos.org/", - "version": "0.24.1", + "version": "0.24.2", "private": true, "author": { "name": "Nervos Core Dev", @@ -64,7 +64,7 @@ "electron-devtools-installer": "2.2.4", "electron-notarize": "0.1.1", "lint-staged": "9.2.5", - "neuron-ui": "0.24.1", + "neuron-ui": "0.24.2", "rimraf": "3.0.0", "spectron": "8.0.0", "ts-transformer-imports": "0.4.3", From 258ebbe28e3a9290e46da2d3209f6abdf977defa Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 8 Nov 2019 15:01:03 +0900 Subject: [PATCH 16/16] docs: Update changelog --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1520bbda90..7a23513091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## [0.24.2](https://github.com/nervosnetwork/neuron/compare/v0.24.1...v0.24.2) (2019-11-08) + + +### Bug Fixes + +* replace with empty string in input group rename witness ([5d59f3d](https://github.com/nervosnetwork/neuron/commit/5d59f3d)) +* skip get previous tx when cellbase ([41600ea](https://github.com/nervosnetwork/neuron/commit/41600ea)) +* skip get previous tx when cellbase in indexer ([7e8a578](https://github.com/nervosnetwork/neuron/commit/7e8a578)) +* skip the cellbase tx, not the first input ([aeeb464](https://github.com/nervosnetwork/neuron/commit/aeeb464)) + + +### Features + +* Disable search history by amount ([9bdece6](https://github.com/nervosnetwork/neuron/commit/9bdece6)) +* remove skip data and type toggle ([879d227](https://github.com/nervosnetwork/neuron/commit/879d227)) + + + ## [0.24.1](https://github.com/nervosnetwork/neuron/compare/v0.24.0...v0.24.1) (2019-11-07)