Refactor: remove ckb-sdk-utils and repalce with lumos - #2734
Conversation
|
@zhangyouxin the conflicts is needed to resolve |
|
Packaging for test is done in 5390477118 for commit 8e89627 . |
|
Packaging for test is done in 5396537909 for commit 7ffd05c . |
|
Packaging for test is done in 5396866191 for commit dd6a4de . |
| const outputsResult: [boolean, Output[], AnyoneCanPayInfo[]] = this.selectOutputs() | ||
| const isMainnet = NetworksService.getInstance().isMainnet() | ||
| const outputAddresses: string[] = outputsResult[1].map(output => scriptToAddress(output.lock, isMainnet)) | ||
| const lumosOptions = isMainnet ? { config: config.predefined.LINA } : { config: config.predefined.AGGRON4 } |
There was a problem hiding this comment.
there are so many isMainnet ? LINA : AGGRON4 in the PR, such a refactoring would only increase the complexity, maybe it is better to extract a helper to cover the case
There was a problem hiding this comment.
Agree, we can init the config after ckb node starts and change the config when the network changes.
There was a problem hiding this comment.
a migration that has already been released should not be refactored, which may pose some risks
| const rawTransaction = this.toSDKRawTransaction() | ||
| return utils.ckbHash( | ||
| blockchain.RawTransaction.pack({ | ||
| ...rawTransaction, | ||
| outputs: rawTransaction.outputs.map(o => ({ | ||
| ...o, | ||
| type: o.type || undefined, | ||
| })), | ||
| cellDeps: rawTransaction.cellDeps.map(cd => ({ | ||
| ...cd, | ||
| outPoint: cd.outPoint!, | ||
| })), | ||
| inputs: rawTransaction.inputs.map(i => ({ | ||
| ...i, | ||
| previousOutput: i.previousOutput!, | ||
| })), | ||
| }) | ||
| ) |
There was a problem hiding this comment.
If it is found that refactoring increases complexity, this refactoring should not be done, and if there is no export method in lumos to calculate transaction hash, it should be marked as TODO instead of refactoring as such
| codeHash: config.predefined.LINA.SCRIPTS.DAO.CODE_HASH, | ||
| hashType: config.predefined.LINA.SCRIPTS.DAO.HASH_TYPE, |
There was a problem hiding this comment.
SystemScriptInfo may not same with the LINA's
There was a problem hiding this comment.
The codeHashes of systemScripts are the same in mainnet/testnet/devnet
| const cellOutput = output.toSDK() | ||
| const bytes = bytesUtils.hexify( | ||
| blockchain.CellOutput.pack({ | ||
| capacity: cellOutput.capacity, | ||
| lock: cellOutput.lock, | ||
| type: cellOutput.type || undefined, // TODO: null is not a packable type | ||
| }) | ||
| ) |
There was a problem hiding this comment.
what is the TODO means here?
There was a problem hiding this comment.
cellOutput.type could be null, so maybe it's better to provide a translator to convert CKBCompont types with nulls to lumos compatible types with undefineds so that the code may look nicer.
| const bytes = serializeFixVec(wit) | ||
| return HexUtils.byteLength(bytes) + TransactionSize.SERIALIZED_OFFSET_BYTESIZE | ||
| if (typeof witness === 'string') { | ||
| const fixvecCodec = fixvec(number.Uint8) |
There was a problem hiding this comment.
witness is not uint8, it is bytes, and I think the refactor just makes the code hard to understand
the blockchain.mol describes the Transaction as
table Transaction {
raw: RawTransaction,
witnesses: BytesVec,
}
vector Bytes <byte>;
vector BytesVec <Bytes>;
So it should be BytesVec.pack(Bytes.pack(WitnessArgs.pack({lock:'...'}))) here, but it is not. I think this method only calculates a part of the size, now this change will only make this method more difficult to understand, I suggest not to change this method first
There was a problem hiding this comment.
Yes this part of code is hard to understand. So I just try to keep the logic as it is.
The original code just wraps witness in Uint8Array by using serializeFixVec.
The idea you provided here is changing original logic, which may cause unintended bugs, please refer to :
neuron/packages/neuron-wallet/src/models/transaction-size.ts
Lines 68 to 72 in 55e0db3
| args, | ||
| codeHash: systemScripts.SECP256K1_BLAKE160.codeHash, | ||
| hashType: systemScripts.SECP256K1_BLAKE160.hashType, | ||
| codeHash: config.predefined.AGGRON4.SCRIPTS.SECP256K1_BLAKE160.CODE_HASH, |
There was a problem hiding this comment.
I found there are so many AGGRON4 in the refactor, it is better to extract them to an independent module to manage the config, that would make the config easy to maintain when the config has changed or the code hash is not the same with the predefined.
There was a problem hiding this comment.
For this part, we are just using SECP256K1_BLAKE160 code hash, which is the same in mainnet/testnet/devnet.
Because lumos utils like helpers.encodeToAddress, parseAddress needs to receive a config, so I plan to create a static method to provide config like NeuronInstance.getLumosConfig()
| '10000', | ||
| Script.fromObject({ codeHash: '', args: '', hashType: ScriptHashType.Type }), | ||
| Script.fromObject({ codeHash: '', args: '', hashType: ScriptHashType.Type }), | ||
| Script.fromObject({ codeHash: `0x${'00'.repeat(32)}`, args: '0x', hashType: ScriptHashType.Type }), |
There was a problem hiding this comment.
it is better to add some comment to describe why the empty codeHash is required here
There was a problem hiding this comment.
I have described the reason in the PR comment, please refer to:#2734 (comment)
| describe('with public key info exist for the public key', () => { | ||
| const publicKey = 'public key' | ||
| // const publicKey = 'public key' // not valid public key | ||
| const publicKey = '0x' + '00'.repeat(65) // 65 bytes pub key |
There was a problem hiding this comment.
Just keep it as it is, unit tests can't always construct complete test data, as compared to semanticization, which makes unit tests easier to maintain
There was a problem hiding this comment.
It can't pass test after refactor, because publicKey is used to generate secp256k1 args, in lumos we can call utils.ckbHash(pubkey).slice(0, 42), which requires publicKey to be a valid BytesLike value.
| import Multisig from '../models/multisig' | ||
| import SystemScriptInfo from '../models/system-script-info' | ||
| import NetworksService from '../services/networks' | ||
| import { config as lumosConig, helpers, utils, config } from '@ckb-lumos/lumos' |
There was a problem hiding this comment.
What's the difference between config as lumosConfig and config
There was a problem hiding this comment.
setting lumosConfig as alias for config , because there is another viarable named config in the scope
There was a problem hiding this comment.
I didn't get it, lumosConfig and config are both from @ckb-lumos/lumos.config, pointing to the same one.
BTW, lumosConig is a typo
There was a problem hiding this comment.
neuron/packages/neuron-wallet/src/controllers/multisig.ts
Lines 110 to 117 in b4f7de2
config is delared here in line 110, if import { config } from '@ckb-lumos/lumos', then there are two configs in the mapFunction, I'll fix the typo
There was a problem hiding this comment.
| import { config as lumosConig, helpers, utils, config } from '@ckb-lumos/lumos' | |
| import { config as lumosConig, helpers, utils } from '@ckb-lumos/lumos' |
|
I find that totally removal of After creating this PR, I can see some sub-tasks. So I would like to close this PR and create each PR for:
With the tasks seperated we can push the diliveration of this PR more smoothly |
| const outputsResult: [boolean, Output[], AnyoneCanPayInfo[]] = this.selectOutputs() | ||
| const isMainnet = NetworksService.getInstance().isMainnet() | ||
| const outputAddresses: string[] = outputsResult[1].map(output => scriptToAddress(output.lock, isMainnet)) | ||
| const lumosOptions = isMainnet ? { config: config.predefined.LINA } : { config: config.predefined.AGGRON4 } |
There was a problem hiding this comment.
Agree, we can init the config after ckb node starts and change the config when the network changes.
| const script = addressToScript(address) | ||
| const isMainnet = address.startsWith('ckb') | ||
| const script = isMainnet | ||
| ? helpers.addressToScript(address, { config: config.predefined.LINA }) |
There was a problem hiding this comment.
Can we move the address.startsWith('ckb') logic to helpers.addressToScript function?
There was a problem hiding this comment.
Good idea, it's common way to determine if isMainnet by address prefix, in the mean time, when we need to translate Script to Address, we still need to get a isMainnet env from somewhere else, so I try to solve the two convertion problem together, maybe more common way is to call config.initializeConfig(isMainnet ? LINA : AGGRON4) when network changes? @homura
There was a problem hiding this comment.
Can we move the address.startsWith('ckb') logic to helpers.addressToScript function?
OK, we'll implement it in the Lumos
| outputType: '', | ||
| }) | ||
| witnessEntry.witness = bytes.hexify( | ||
| blockchain.WitnessArgs.pack({ |
There was a problem hiding this comment.
Refer to https://github.com/nervosnetwork/neuron/pull/2734/files#diff-7703c04c04ff2f19a47617fbb9bd430893f7cb702bb9ef8185998fd2cdcb259dR73,
blockchain.WitnessArgs.pack can not accept spaces as inputType or outputType parameters, so should we change to
witnessEntry.witnessArgs.inputType ?? undefined| // input_type: undefined | ||
| // output_type: undefined | ||
| // } | ||
| expect(result).toEqual(HexUtils.byteLength('0x1400000010000000100000001400000000000000') + 4 + 4) |
There was a problem hiding this comment.
It may cause here https://github.com/ckb-js/lumos/blob/develop/packages/codec/src/blockchain.ts#L64-L66 Lumos set all fields as option. But ckb-sdk-js does not set fields as option
There was a problem hiding this comment.
I feel confused with https://github.com/ckb-js/lumos/blob/develop/packages/codec/src/blockchain.ts#L64-L66.
When I call bytes.hexify(base.blockchain.WitnessArgs.pack({ lock: '0x', input_type: '0x', output_type: '0x'})), it will output 0x1400000010000000140000001400000000000000, why input_type and output_type set empty, but lock set '0x00000000'.
There was a problem hiding this comment.
here '0x00000000' is args, check the test case setup:
| '0' | ||
| ) | ||
| tx.witnesses[0] = serializeWitnessArgs(WitnessArgs.emptyLock().toSDK()) | ||
| // tx.witnesses[0] = bytes.hexify(blockchain.WitnessArgs.pack(WitnessArgs.emptyLock().toSDK()) |
Description
Due to merge of
ckb-sdk-xtolumos, we need to gradually deprecateckb-sdk-x, this PR removesckb-sdk-utilsinpackages/neuron-wallet, It's not a small PR and may be not that easy to review, so I plan to seperate this task to two PRs, will create another PR to remove it inpackages/neuron-uiThis PR is not not compilable, because I have updated
lumosto0.20, some snake_case fields has changed to camelCase, the task is in another PR: #2683, only when after that PR is merged, this PR can be ready for review.Resolve Magickbase/neuron-public-issues#201
changed
scriptToHash(script)should be replaced withutils.computeScriptHash(script).scriptToAddress(script, isMainet)should be replaced withhelpers.encodeToAddress(script, lumosOptions). We should translateisMainettolumosOptionshere.addressToScript(address)should be replaced withhelpers.addressToScript(address, lumosOptions). We should detect ifisMainetby checking if the address starts with 'ckb' or not. Alternatively, we could useNetworksService.getInstance().isMainnet().src/models/blake2b.tshas been deleted and replaced with@ckb-lumos/hdandlumos helpers.nullvalues are not compatible with@ckb-lumos/basetypes.argsshould be a valid hex string. Values like "0xuuid" have been deleted.0xorundefined. Empty strings have been deleted.0x1have been changed to0x01.