-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 . |
@@ -33,7 +33,8 @@ export default class TxAddressFinder { | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SystemScriptInfo
may not same with the LINA's
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the TODO means here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cellOutput.type
could be null
, so maybe it's better to provide a translator to convert CKBCompont
types with null
s to lumos
compatible types with undefined
s 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
public static witness(witness: WitnessArgs | string): number { | |
const wit: string = typeof witness === 'string' ? witness : serializeWitnessArgs(witness.toSDK()) | |
const bytes = serializeFixVec(wit) | |
return HexUtils.byteLength(bytes) + TransactionSize.SERIALIZED_OFFSET_BYTESIZE | |
} |
{ | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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()
@@ -63,8 +63,8 @@ describe('SUDTController', () => { | |||
'txHash', | |||
'0', | |||
'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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is better to add some comment to describe why the empty codeHash
is required here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have described the reason in the PR comment, please refer to:#2734 (comment)
@@ -310,7 +310,8 @@ describe('integration tests for AddressService', () => { | |||
|
|||
describe('#generateAndSaveForPublicKey', () => { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
@@ -12,6 +11,7 @@ import OfflineSignService from '../services/offline-sign' | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between config as lumosConfig
and config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setting lumosConfig
as alias for config
, because there is another viarable named config
in the scope
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neuron/packages/neuron-wallet/src/controllers/multisig.ts
Lines 110 to 117 in b4f7de2
const saveConfigs = Object.values(configOutput.multisig_configs).map(config => ({ | |
r: +config.require_first_n, | |
m: +config.threshold, | |
n: config.sighash_addresses.length, | |
blake160s: config.sighash_addresses.map(v => addressToScript(v).args), | |
walletId, | |
alias: config.alias, | |
})) |
config
is delared here in line 110, if import { config } from '@ckb-lumos/lumos'
, then there are two config
s in the mapFunction, I'll fix the typo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
@@ -33,7 +33,8 @@ export default class TxAddressFinder { | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move the address.startsWith('ckb')
logic to helpers.addressToScript
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here '0x00000000' is args
, check the test case setup:
const witnessArgs = new WitnessArgs('', '0x', '') |
@@ -1158,7 +1161,8 @@ describe('TransactionGenerator', () => { | |||
feeRate, | |||
'0' | |||
) | |||
tx.witnesses[0] = serializeWitnessArgs(WitnessArgs.emptyLock().toSDK()) | |||
// tx.witnesses[0] = bytes.hexify(blockchain.WitnessArgs.pack(WitnessArgs.emptyLock().toSDK()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove annotation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Description
Due to merge of
ckb-sdk-x
tolumos
, we need to gradually deprecateckb-sdk-x
, this PR removesckb-sdk-utils
inpackages/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-ui
This PR is not not compilable, because I have updated
lumos
to0.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 translateisMainet
tolumosOptions
here.addressToScript(address)
should be replaced withhelpers.addressToScript(address, lumosOptions)
. We should detect ifisMainet
by checking if the address starts with 'ckb' or not. Alternatively, we could useNetworksService.getInstance().isMainnet()
.src/models/blake2b.ts
has been deleted and replaced with@ckb-lumos/hd
andlumos helpers
.null
values are not compatible with@ckb-lumos/base
types.args
should be a valid hex string. Values like "0xuuid" have been deleted.0x
orundefined
. Empty strings have been deleted.0x1
have been changed to0x01
.