Skip to content

Commit

Permalink
BREAKING CHANGE: replace Buffer with Uint8Array (#713)
Browse files Browse the repository at this point in the history
  • Loading branch information
twhy authored Jun 13, 2024
1 parent d13f880 commit fec185f
Show file tree
Hide file tree
Showing 22 changed files with 376 additions and 381 deletions.
2 changes: 1 addition & 1 deletion packages/base/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function computeScriptHash(script: Script): string {
return ckbHash(blockchain.Script.pack(script));
}

function hashCode(buffer: Buffer): number {
function hashCode(buffer: Uint8Array): number {
return xxHash32(buffer, 0);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/base/src/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Value {
}

hashCode(): number {
return xxHash32(Buffer.from(this.buffer), 0);
return xxHash32(this.buffer, 0);
}

hash(): Hash {
Expand Down
3 changes: 2 additions & 1 deletion packages/base/tests/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const test = require("ava");
const { bytes } = require("@ckb-lumos/codec");

const {
CKBHasher,
Expand Down Expand Up @@ -63,7 +64,7 @@ test("computeScriptHash", (t) => {
});

test("hashCode, should return same hash if same input", (t) => {
const buffer = Buffer.from("1234ab", "hex");
const buffer = bytes.bytify("0x1234ab");
t.is(hashCode(buffer), hashCode(buffer));
});

Expand Down
5 changes: 2 additions & 3 deletions packages/codec/examples/custom-codec-utf8string.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { molecule, bytes } from "../src";
import { Buffer } from "buffer"; // https://github.com/feross/buffer

const UTF8String = molecule.byteVecOf<string>({
pack: (str) => Buffer.from(str, "utf8"),
unpack: (buf) => Buffer.from(bytes.bytify(buf)).toString("utf8"),
pack: (str) => new TextEncoder().encode(str),
unpack: (buf) => new TextDecoder().decode(bytes.bytify(buf)),
});

const packed = UTF8String.pack("hello world, 你好世界");
Expand Down
4 changes: 2 additions & 2 deletions packages/codec/examples/rpc-character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ const SwordMaterial = byteOf<Material>({
});

const UTF8String = byteVecOf<string>({
pack: (str) => Uint8Array.from(Buffer.from(str, "utf8")),
unpack: (buf) => Buffer.from(bytes.bytify(buf)).toString("utf8"),
pack: (str) => new TextEncoder().encode(str),
unpack: (buf) => new TextDecoder().decode(bytes.bytify(buf)),
});

/***** molecule binding *****/
Expand Down
12 changes: 7 additions & 5 deletions packages/common-scripts/examples/pw_lock/lock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import {
TransactionSkeletonType,
createTransactionFromSkeleton,
} from "@ckb-lumos/helpers";
import { bytes } from "@ckb-lumos/codec";
import { keccak256 } from "@ckb-lumos/crypto"
import { getConfig, Config, initializeConfig } from "@ckb-lumos/config-manager";
import { Set } from "immutable";
import keccak, { Keccak } from "keccak";

const { ScriptValue } = values;
const { bytify, hexify } = bytes;

// https://github.com/lay2dev/pw-lock/commit/b447c2bb3f855e933e36212b45af4dec92adf705 pw-lock is a lock script which uses secp256k1_keccak256 algorithm.

Expand Down Expand Up @@ -238,21 +240,21 @@ async function setupInputCell(

// It's a secp256k1_keccak256 sighash all lock script, so we need a keccak256 hash method.
class Keccak256Hasher {
private hasher: Keccak;
private hasher: ReturnType<typeof keccak256.create>;

constructor() {
this.hasher = keccak("keccak256");
this.hasher = keccak256.create();
}

update(data: string | ArrayBuffer | Reader): this {
const reader = new Reader(data);
const array: Buffer = Buffer.from(reader.serializeJson().slice(2), "hex");
const array = bytify(reader.serializeJson());
this.hasher.update(array);
return this;
}

digestReader(): Reader {
const hex = "0x" + this.hasher.digest("hex").toString();
const hex = hexify(this.hasher.digest())
return new Reader(hex);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/common-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@ckb-lumos/base": "0.23.0",
"@ckb-lumos/bi": "0.23.0",
"@ckb-lumos/codec": "0.23.0",
"@ckb-lumos/crypto": "0.23.0",
"@ckb-lumos/config-manager": "0.23.0",
"@ckb-lumos/helpers": "0.23.0",
"@ckb-lumos/rpc": "0.23.0",
Expand Down Expand Up @@ -58,9 +59,7 @@
"@ckb-lumos/crypto": "0.23.0",
"@ckb-lumos/debugger": "0.23.0",
"@ckb-lumos/hd": "0.23.0",
"@types/keccak": "^3.0.1",
"@unisat/wallet-sdk": "^1.1.2",
"keccak": "^3.0.1",
"tweetnacl": "^1.0.3"
},
"publishConfig": {
Expand Down
6 changes: 3 additions & 3 deletions packages/common-scripts/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ function generateLockScriptInfos({ config = undefined }: Options = {}): void {
};

const configHashCode: number = utils.hashCode(
Buffer.from(JSON.stringify(config))
new TextEncoder().encode(JSON.stringify(config))
);

if (lockScriptInfos.infos.length === 0) {
Expand Down Expand Up @@ -931,8 +931,8 @@ function getTransactionSize(txSkeleton: TransactionSkeletonType): number {

function getTransactionSizeByTx(tx: Transaction): number {
const serializedTx = blockchain.Transaction.pack(tx);
// 4 is serialized offset bytesize
const size = serializedTx.byteLength + 4;
const offset = 4; // 4 is serialized offset bytesize
const size = serializedTx.byteLength + offset;
return size;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/common-scripts/tests/p2pkh.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from "ava";
import { Script, utils } from "@ckb-lumos/base";
import { default as createKeccak } from "keccak";
import { keccak256 } from "@ckb-lumos/crypto";
import { createP2PKHMessageGroup } from "../src/p2pkh";
import { txObject, txSkeletonFromJson } from "./helper";
import p2pkhJson from "./p2pkh.json";
Expand Down Expand Up @@ -35,13 +35,13 @@ test("pw lock [g1]", (t) => {
SIGNATURE_PLACEHOLDER
);

const keccak = createKeccak("keccak256");
const keccak = keccak256.create();
const signLock = p2pkhJson["PW_LOCK_[G1]"].SIGN_LOCK as Script;

const messageGroup = createP2PKHMessageGroup(tx, [signLock], {
hasher: {
update: (message) => {
keccak.update(Buffer.from(new Uint8Array(message)));
keccak.update(new Uint8Array(message));
},
digest: () => keccak.digest(),
},
Expand Down
4 changes: 2 additions & 2 deletions packages/common-scripts/tests/sudt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -667,9 +667,9 @@ test("transfer secp => secp, change to acp and has previous output, split change

test("pack and unpack sudt amount", (t) => {
const unpacked = BI.from(0x1234);
const packed = Buffer.alloc(16);
const packed = new Uint8Array(16);
// little endian of 0x1234
packed.write("3412", "hex");
packed.set([0x34, 0x12]);

t.true(bytes.equal(packAmount(unpacked), packed));
t.true(unpackAmount(packed).eq(unpacked));
Expand Down
3 changes: 2 additions & 1 deletion packages/debugger/src/executor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataLoader, ExecuteResult, Executor } from "./types";
import { TransactionSkeletonType } from "@ckb-lumos/helpers";
import { randomBytes } from "@ckb-lumos/crypto";
import { bytes } from "@ckb-lumos/codec";
import { spawnSync } from "child_process";
import { Hash } from "@ckb-lumos/base";
import * as fs from "fs";
Expand Down Expand Up @@ -52,7 +53,7 @@ export class CKBDebugger implements Executor {
private saveTmpTxFile(txSkeleton: TransactionSkeletonType): string {
const debuggerData = parseDebuggerData(txSkeleton, this.loader);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
const randomHex = Buffer.from(randomBytes(18)).toString("hex");
const randomHex = bytes.hexify(randomBytes(18)).slice(2);
const tempFileName = `lumos-debugger-data-${randomHex}`;
const tmpTxPath = path.join(os.tmpdir(), `${tempFileName}.json`);
fs.writeFileSync(tmpTxPath, JSON.stringify(debuggerData));
Expand Down
2 changes: 1 addition & 1 deletion packages/hd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
"dependencies": {
"@ckb-lumos/base": "0.23.0",
"@ckb-lumos/bi": "0.23.0",
"@ckb-lumos/codec": "0.23.0",
"@ckb-lumos/crypto": "0.23.0",
"bn.js": "^5.1.3",
"elliptic": "^6.5.4",
"scrypt-js": "^3.0.1",
"uuid": "^8.3.0"
},
"repository": {
Expand Down
40 changes: 22 additions & 18 deletions packages/hd/src/extended_key.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */
import Keychain from "./keychain";
import key, { privateToPublic } from "./key";
import { bytes } from "@ckb-lumos/codec";
import { utils, HexString } from "@ckb-lumos/base";
import { privateToPublic, publicKeyToBlake160 } from "./key";
import { assertPublicKey, assertChainCode, assertPrivateKey } from "./helper";

const { bytify, hexify } = bytes;

export enum AddressType {
Receiving = 0,
Change = 1,
Expand Down Expand Up @@ -55,19 +59,19 @@ export class AccountExtendedPublicKey extends ExtendedPublicKey {

publicKeyInfo(type: AddressType, index: number): PublicKeyInfo {
const publicKey: string = this.getPublicKey(type, index);
const blake160: string = key.publicKeyToBlake160(publicKey);
const blake160: string = publicKeyToBlake160(publicKey);
return {
publicKey,
blake160,
path: AccountExtendedPublicKey.pathFor(type, index),
};
}

public static pathForReceiving(index: number) {
public static pathForReceiving(index: number): string {
return AccountExtendedPublicKey.pathFor(AddressType.Receiving, index);
}

public static pathForChange(index: number) {
public static pathForChange(index: number): string {
return AccountExtendedPublicKey.pathFor(AddressType.Change, index);
}

Expand All @@ -77,14 +81,14 @@ export class AccountExtendedPublicKey extends ExtendedPublicKey {

private getPublicKey(type = AddressType.Receiving, index: number): HexString {
const keychain = Keychain.fromPublicKey(
Buffer.from(this.publicKey.slice(2), "hex"),
Buffer.from(this.chainCode.slice(2), "hex"),
bytify(this.publicKey),
bytify(this.chainCode),
AccountExtendedPublicKey.ckbAccountPath
)
.deriveChild(type, false)
.deriveChild(index, false);

return "0x" + keychain.publicKey.toString("hex");
return hexify(keychain.publicKey);
}
}

Expand Down Expand Up @@ -117,24 +121,24 @@ export class ExtendedPrivateKey {

toAccountExtendedPublicKey(): AccountExtendedPublicKey {
const masterKeychain = new Keychain(
Buffer.from(this.privateKey.slice(2), "hex"),
Buffer.from(this.chainCode.slice(2), "hex")
bytify(this.privateKey),
bytify(this.chainCode)
);
const accountKeychain = masterKeychain.derivePath(
AccountExtendedPublicKey.ckbAccountPath
);

return new AccountExtendedPublicKey(
"0x" + accountKeychain.publicKey.toString("hex"),
"0x" + accountKeychain.chainCode.toString("hex")
hexify(accountKeychain.publicKey),
hexify(accountKeychain.chainCode)
);
}

static fromSeed(seed: Buffer): ExtendedPrivateKey {
static fromSeed(seed: Uint8Array): ExtendedPrivateKey {
const keychain = Keychain.fromSeed(seed);
return new ExtendedPrivateKey(
"0x" + keychain.privateKey.toString("hex"),
"0x" + keychain.chainCode.toString("hex")
hexify(keychain.privateKey),
hexify(keychain.chainCode)
);
}

Expand All @@ -145,8 +149,8 @@ export class ExtendedPrivateKey {

privateKeyInfoByPath(path: string): PrivateKeyInfo {
const keychain = new Keychain(
Buffer.from(this.privateKey.slice(2), "hex"),
Buffer.from(this.chainCode.slice(2), "hex")
bytify(this.privateKey),
bytify(this.chainCode)
).derivePath(path);

return this.privateKeyInfoFromKeychain(keychain, path);
Expand All @@ -157,8 +161,8 @@ export class ExtendedPrivateKey {
path: string
): PrivateKeyInfo {
return {
privateKey: "0x" + keychain.privateKey.toString("hex"),
publicKey: "0x" + keychain.publicKey.toString("hex"),
privateKey: hexify(keychain.privateKey),
publicKey: hexify(keychain.publicKey),
path: path,
};
}
Expand Down
33 changes: 18 additions & 15 deletions packages/hd/src/key.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */
import { bytes } from "@ckb-lumos/codec";
import { HexString, utils } from "@ckb-lumos/base";
import { ec as EC, SignatureInput } from "elliptic";
import { assertPrivateKey, assertPublicKey } from "./helper";

const { bytify } = bytes;
const ec = new EC("secp256k1");

export function signRecoverable(
Expand Down Expand Up @@ -31,40 +34,40 @@ export function recoverFromSignature(
utils.assertHexString("message", message);
utils.assertHexString("signature", signature);

const msgBuffer = Buffer.from(message.slice(2), "hex");
const sigBuffer = Buffer.from(signature.slice(2), "hex");
const msg = bytify(message);
const sig = bytify(signature);

const sign: SignatureInput = {
r: sigBuffer.slice(0, 32),
s: sigBuffer.slice(32, 64),
recoveryParam: sigBuffer[64],
r: sig.slice(0, 32),
s: sig.slice(32, 64),
recoveryParam: sig[64],
};

const point = ec.recoverPubKey(msgBuffer, sign, sign.recoveryParam!);
const point = ec.recoverPubKey(msg, sign, sign.recoveryParam!);

Check warning on line 46 in packages/hd/src/key.ts

View workflow job for this annotation

GitHub Actions / lint-staged

Forbidden non-null assertion
const publicKey = "0x" + point.encode("hex", true).toLowerCase();
return publicKey;
}

export function privateToPublic(privateKey: Buffer): Buffer;
export function privateToPublic(privateKey: HexString): HexString;
export function privateToPublic(privateKey: Uint8Array): Uint8Array;

export function privateToPublic(
privateKey: Buffer | HexString
): Buffer | HexString {
let pkBuffer = privateKey;
privateKey: Uint8Array | HexString
): Uint8Array | HexString {
let pk = privateKey;
if (typeof privateKey === "string") {
assertPrivateKey(privateKey);
pkBuffer = Buffer.from(privateKey.slice(2), "hex");
pk = bytify(privateKey);
}
if (pkBuffer.length !== 32) {
if (pk.length !== 32) {
throw new Error("Private key must be 32 bytes!");
}

const publickey = ec.keyFromPrivate(pkBuffer).getPublic(true, "hex");
const publickey = "0x" + ec.keyFromPrivate(pk).getPublic(true, "hex");
if (typeof privateKey === "string") {
return "0x" + publickey;
return publickey;
}
return Buffer.from(publickey, "hex");
return bytify(publickey);
}

export function publicKeyToBlake160(publicKey: HexString): HexString {
Expand Down
Loading

0 comments on commit fec185f

Please sign in to comment.