@ckb-ccc/core 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/README.md +2 -0
- package/dist/address.advanced-8N_Hcv6p.mjs +2 -0
- package/dist/address.advanced-8N_Hcv6p.mjs.map +1 -0
- package/dist/advanced.d.mts +1 -1
- package/dist/advanced.mjs +1 -1
- package/{dist.commonjs/advancedBarrel-DRDT4GBS.d.ts → dist/advancedBarrel-4xTrm-An.d.mts} +581 -16
- package/dist/advancedBarrel-4xTrm-An.d.mts.map +1 -0
- package/dist/advancedBarrel.d.mts +1 -1
- package/dist/advancedBarrel.mjs +1 -1
- package/dist/barrel-D3tMRxi5.mjs +7 -0
- package/dist/barrel-D3tMRxi5.mjs.map +1 -0
- package/dist/barrel.d.mts +2 -2
- package/dist/barrel.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist.commonjs/address.advanced-CUIioHfv.js +2 -0
- package/dist.commonjs/address.advanced-CUIioHfv.js.map +1 -0
- package/dist.commonjs/advanced.d.ts +1 -1
- package/dist.commonjs/advanced.js +1 -1
- package/{dist/advancedBarrel-BD7EAPVd.d.mts → dist.commonjs/advancedBarrel-XD_hMVay.d.ts} +582 -15
- package/dist.commonjs/advancedBarrel-XD_hMVay.d.ts.map +1 -0
- package/dist.commonjs/advancedBarrel.d.ts +1 -1
- package/dist.commonjs/advancedBarrel.js +1 -1
- package/dist.commonjs/barrel-D6tLiPED.js +21 -0
- package/dist.commonjs/barrel-D6tLiPED.js.map +1 -0
- package/dist.commonjs/barrel.d.ts +2 -2
- package/dist.commonjs/barrel.js +1 -1
- package/dist.commonjs/index.d.ts +2 -2
- package/dist.commonjs/index.js +1 -1
- package/package.json +2 -2
- package/src/ckb/transaction.ts +20 -1
- package/src/client/cache/cache.ts +1 -2
- package/src/client/cache/memory.ts +1 -2
- package/src/client/client.ts +1 -2
- package/src/client/clientPublicMainnet.advanced.ts +34 -0
- package/src/client/clientPublicTestnet.advanced.ts +34 -0
- package/src/client/clientTypes.ts +1 -6
- package/src/client/jsonRpc/transformers.ts +1 -2
- package/src/client/knownScript.ts +2 -0
- package/src/codec/entity.ts +13 -6
- package/src/hasher/hasherCkb.ts +7 -1
- package/src/hex/index.ts +82 -2
- package/src/num/index.ts +17 -4
- package/src/signer/ckb/index.ts +3 -1
- package/src/signer/ckb/secp256k1Signing.ts +94 -0
- package/src/signer/ckb/signerCkbPrivateKey.ts +6 -11
- package/src/signer/ckb/signerCkbPublicKey.ts +8 -3
- package/src/signer/ckb/signerMultisigCkbPrivateKey.ts +129 -0
- package/src/signer/ckb/signerMultisigCkbReadonly.ts +713 -0
- package/src/signer/signer/index.ts +100 -1
- package/src/utils/index.ts +3 -3
- package/dist/address.advanced-BmJKF_Lg.mjs +0 -2
- package/dist/address.advanced-BmJKF_Lg.mjs.map +0 -1
- package/dist/advancedBarrel-BD7EAPVd.d.mts.map +0 -1
- package/dist/barrel-C-sr5NLL.mjs +0 -7
- package/dist/barrel-C-sr5NLL.mjs.map +0 -1
- package/dist.commonjs/address.advanced-D9nKvIr3.js +0 -2
- package/dist.commonjs/address.advanced-D9nKvIr3.js.map +0 -1
- package/dist.commonjs/advancedBarrel-DRDT4GBS.d.ts.map +0 -1
- package/dist.commonjs/barrel-SuR9mcfv.js +0 -21
- package/dist.commonjs/barrel-SuR9mcfv.js.map +0 -1
- package/src/signer/ckb/verifyCkbSecp256k1.ts +0 -31
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
2
|
+
import { bytesConcat, bytesFrom, BytesLike } from "../../bytes/index.js";
|
|
3
|
+
import { hashCkb } from "../../hasher/index.js";
|
|
4
|
+
import { Hex, hexFrom } from "../../hex/index.js";
|
|
5
|
+
|
|
6
|
+
export const SECP256K1_SIGNATURE_LENGTH = 65;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sign a message using Secp256k1.
|
|
10
|
+
*
|
|
11
|
+
* @param message - The message to sign.
|
|
12
|
+
* @param privateKey - The private key.
|
|
13
|
+
* @returns The signature.
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export function signMessageSecp256k1(
|
|
17
|
+
message: BytesLike,
|
|
18
|
+
privateKey: BytesLike,
|
|
19
|
+
): Hex {
|
|
20
|
+
const signature = secp256k1.sign(bytesFrom(message), bytesFrom(privateKey), {
|
|
21
|
+
format: "recovered",
|
|
22
|
+
prehash: false,
|
|
23
|
+
});
|
|
24
|
+
return hexFrom(bytesConcat(signature.slice(1), signature.slice(0, 1)));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Verify a message using Secp256k1.
|
|
29
|
+
*
|
|
30
|
+
* @param message - The message to verify.
|
|
31
|
+
* @param signature - The signature.
|
|
32
|
+
* @param publicKey - The public key.
|
|
33
|
+
* @returns True if the signature is valid, false otherwise.
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export function verifyMessageSecp256k1(
|
|
37
|
+
message: BytesLike,
|
|
38
|
+
signature: BytesLike,
|
|
39
|
+
publicKey: BytesLike,
|
|
40
|
+
): boolean {
|
|
41
|
+
const signatureBytes = bytesFrom(signature);
|
|
42
|
+
return secp256k1.verify(
|
|
43
|
+
bytesConcat(signatureBytes.slice(64), signatureBytes.slice(0, 64)),
|
|
44
|
+
bytesFrom(message),
|
|
45
|
+
bytesFrom(publicKey),
|
|
46
|
+
{ format: "recovered", prehash: false },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Recover the public key from a Secp256k1 signature.
|
|
52
|
+
*
|
|
53
|
+
* @param message - The message.
|
|
54
|
+
* @param signature - The signature.
|
|
55
|
+
* @returns The recovered public key.
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export function recoverMessageSecp256k1(
|
|
59
|
+
message: BytesLike,
|
|
60
|
+
signature: BytesLike,
|
|
61
|
+
): Hex {
|
|
62
|
+
const signatureBytes = bytesFrom(signature);
|
|
63
|
+
return hexFrom(
|
|
64
|
+
secp256k1.recoverPublicKey(
|
|
65
|
+
bytesConcat(signatureBytes.slice(64), signatureBytes.slice(0, 64)),
|
|
66
|
+
bytesFrom(message),
|
|
67
|
+
{ prehash: false },
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export function messageHashCkbSecp256k1(message: string | BytesLike): Hex {
|
|
76
|
+
const msg = typeof message === "string" ? message : hexFrom(message);
|
|
77
|
+
const buffer = bytesFrom(`Nervos Message:${msg}`, "utf8");
|
|
78
|
+
return hashCkb(buffer);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @public
|
|
83
|
+
*/
|
|
84
|
+
export function verifyMessageCkbSecp256k1(
|
|
85
|
+
message: string | BytesLike,
|
|
86
|
+
signature: string,
|
|
87
|
+
publicKey: string,
|
|
88
|
+
): boolean {
|
|
89
|
+
return verifyMessageSecp256k1(
|
|
90
|
+
messageHashCkbSecp256k1(message),
|
|
91
|
+
signature,
|
|
92
|
+
publicKey,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
2
|
-
import {
|
|
2
|
+
import { bytesFrom, BytesLike } from "../../bytes/index.js";
|
|
3
3
|
import { Transaction, TransactionLike, WitnessArgs } from "../../ckb/index.js";
|
|
4
4
|
import { Client } from "../../client/index.js";
|
|
5
5
|
import { Hex, hexFrom, HexLike } from "../../hex/index.js";
|
|
6
|
+
import {
|
|
7
|
+
messageHashCkbSecp256k1,
|
|
8
|
+
signMessageSecp256k1,
|
|
9
|
+
} from "./secp256k1Signing.js";
|
|
6
10
|
import { SignerCkbPublicKey } from "./signerCkbPublicKey.js";
|
|
7
|
-
import { messageHashCkbSecp256k1 } from "./verifyCkbSecp256k1.js";
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* @public
|
|
@@ -23,15 +26,7 @@ export class SignerCkbPrivateKey extends SignerCkbPublicKey {
|
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
async _signMessage(message: HexLike): Promise<Hex> {
|
|
26
|
-
|
|
27
|
-
bytesFrom(message),
|
|
28
|
-
bytesFrom(this.privateKey),
|
|
29
|
-
{
|
|
30
|
-
format: "recovered",
|
|
31
|
-
prehash: false,
|
|
32
|
-
},
|
|
33
|
-
);
|
|
34
|
-
return hexFrom(bytesConcat(signature.slice(1), signature.slice(0, 1)));
|
|
29
|
+
return signMessageSecp256k1(message, this.privateKey);
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
async signMessageRaw(message: string | BytesLike): Promise<Hex> {
|
|
@@ -2,9 +2,10 @@ import { Address } from "../../address/index.js";
|
|
|
2
2
|
import { bytesFrom } from "../../bytes/index.js";
|
|
3
3
|
import { Script, Transaction, TransactionLike } from "../../ckb/index.js";
|
|
4
4
|
import { CellDepInfo, Client, KnownScript } from "../../client/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { hashCkbShort } from "../../hasher/index.js";
|
|
6
6
|
import { Hex, HexLike, hexFrom } from "../../hex/index.js";
|
|
7
7
|
import { Signer, SignerSignType, SignerType } from "../signer/index.js";
|
|
8
|
+
import { SECP256K1_SIGNATURE_LENGTH } from "./secp256k1Signing.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @public
|
|
@@ -47,7 +48,7 @@ export class SignerCkbPublicKey extends Signer {
|
|
|
47
48
|
return Address.fromKnownScript(
|
|
48
49
|
this.client,
|
|
49
50
|
KnownScript.Secp256k1Blake160,
|
|
50
|
-
|
|
51
|
+
hashCkbShort(this.publicKey),
|
|
51
52
|
);
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -140,7 +141,11 @@ export class SignerCkbPublicKey extends Signer {
|
|
|
140
141
|
|
|
141
142
|
await Promise.all(
|
|
142
143
|
(await this.getRelatedScripts(tx)).map(async ({ script, cellDeps }) => {
|
|
143
|
-
await tx.prepareSighashAllWitness(
|
|
144
|
+
await tx.prepareSighashAllWitness(
|
|
145
|
+
script,
|
|
146
|
+
SECP256K1_SIGNATURE_LENGTH,
|
|
147
|
+
this.client,
|
|
148
|
+
);
|
|
144
149
|
await tx.addCellDepInfos(this.client, cellDeps);
|
|
145
150
|
}),
|
|
146
151
|
);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { SinceLike, Transaction, TransactionLike } from "../../ckb/index.js";
|
|
2
|
+
import { Client, KnownScript, ScriptInfoLike } from "../../client/index.js";
|
|
3
|
+
import { hashCkbShort } from "../../hasher/index.js";
|
|
4
|
+
import { Hex, hexFrom, HexLike } from "../../hex/index.js";
|
|
5
|
+
import { signMessageSecp256k1 } from "./secp256k1Signing.js";
|
|
6
|
+
import { SignerCkbPrivateKey } from "./signerCkbPrivateKey.js";
|
|
7
|
+
import {
|
|
8
|
+
MultisigCkbWitnessLike,
|
|
9
|
+
SignerMultisigCkbReadonly,
|
|
10
|
+
} from "./signerMultisigCkbReadonly.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A class extending Signer that provides access to a CKB multisig script and supports signing operations.
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export class SignerMultisigCkbPrivateKey extends SignerMultisigCkbReadonly {
|
|
17
|
+
private readonly privateKey: Hex;
|
|
18
|
+
private readonly signer: SignerCkbPrivateKey;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates an instance of SignerMultisigCkbPrivateKey.
|
|
22
|
+
*
|
|
23
|
+
* @param client - The client instance.
|
|
24
|
+
* @param privateKey - The private key.
|
|
25
|
+
* @param multisigInfo - The multisig information.
|
|
26
|
+
* @param options - The options.
|
|
27
|
+
*/
|
|
28
|
+
constructor(
|
|
29
|
+
client: Client,
|
|
30
|
+
privateKey: HexLike,
|
|
31
|
+
multisigInfo: MultisigCkbWitnessLike,
|
|
32
|
+
options?: {
|
|
33
|
+
since?: SinceLike | null;
|
|
34
|
+
scriptInfos?: (KnownScript | ScriptInfoLike)[] | null;
|
|
35
|
+
} | null,
|
|
36
|
+
) {
|
|
37
|
+
super(client, multisigInfo, options);
|
|
38
|
+
|
|
39
|
+
this.privateKey = hexFrom(privateKey);
|
|
40
|
+
this.signer = new SignerCkbPrivateKey(client, this.privateKey);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sign a transaction only (without preparing).
|
|
45
|
+
*
|
|
46
|
+
* @param txLike - The transaction to sign.
|
|
47
|
+
* @returns The signed transaction.
|
|
48
|
+
*/
|
|
49
|
+
async signOnlyTransaction(txLike: TransactionLike): Promise<Transaction> {
|
|
50
|
+
let tx = Transaction.from(txLike);
|
|
51
|
+
|
|
52
|
+
const thisPubkeyHash = hashCkbShort(this.signer.publicKey);
|
|
53
|
+
|
|
54
|
+
const index = this.multisigInfo.publicKeyHashes.indexOf(thisPubkeyHash);
|
|
55
|
+
if (index === -1) {
|
|
56
|
+
return tx;
|
|
57
|
+
}
|
|
58
|
+
const isSelfRequired = index < this.multisigInfo.mustMatch;
|
|
59
|
+
|
|
60
|
+
for (const { script } of await this.scriptInfos) {
|
|
61
|
+
const info = await this.getSignInfo(tx, script);
|
|
62
|
+
if (!info) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// === Find a position for the signature ===
|
|
67
|
+
tx = await this.prepareWitnessArgsAt(
|
|
68
|
+
tx,
|
|
69
|
+
info.position,
|
|
70
|
+
async (witness) => {
|
|
71
|
+
// We re-evaluate the signatures to filter invalid / excessive signatures
|
|
72
|
+
const signatures: Hex[] = [];
|
|
73
|
+
let requiredCount = 0;
|
|
74
|
+
let isSignNeeded = true;
|
|
75
|
+
|
|
76
|
+
for (const {
|
|
77
|
+
pubkeyHash,
|
|
78
|
+
signature,
|
|
79
|
+
isRequired,
|
|
80
|
+
} of witness.generatePublicKeyHashesFromSignatures(info.message)) {
|
|
81
|
+
if (pubkeyHash === thisPubkeyHash) {
|
|
82
|
+
if (!isSignNeeded) {
|
|
83
|
+
// Has signed and added to the signatures list already. We will not add it again.
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
isSignNeeded = false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isRequired) {
|
|
90
|
+
requiredCount += 1;
|
|
91
|
+
} else if (
|
|
92
|
+
signatures.length - requiredCount >=
|
|
93
|
+
this.multisigInfo.flexibleThreshold
|
|
94
|
+
) {
|
|
95
|
+
// Too many flexible signatures
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
signatures.push(signature);
|
|
100
|
+
if (signatures.length >= this.multisigInfo.threshold) {
|
|
101
|
+
// We have got enough signatures
|
|
102
|
+
isSignNeeded = false;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (
|
|
108
|
+
isSignNeeded &&
|
|
109
|
+
(isSelfRequired ||
|
|
110
|
+
signatures.length - requiredCount <
|
|
111
|
+
this.multisigInfo.flexibleThreshold)
|
|
112
|
+
) {
|
|
113
|
+
// Add the signature from this signer only when
|
|
114
|
+
// 1. The signature is needed
|
|
115
|
+
// 2. It's required or...
|
|
116
|
+
// 3. We haven't got enough flexible signatures
|
|
117
|
+
signatures.push(
|
|
118
|
+
signMessageSecp256k1(info.message, this.privateKey),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
witness.signatures = signatures;
|
|
122
|
+
return witness;
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return tx;
|
|
128
|
+
}
|
|
129
|
+
}
|