-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(common-scripts): support eth displaying for omnilock (#718)
- Loading branch information
Showing
7 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@ckb-lumos/common-scripts": minor | ||
"@ckb-lumos/lumos": minor | ||
--- | ||
|
||
feat: support eth displaying auth mode for omnilock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
packages/common-scripts/src/omnilock-ethereum-displaying.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { BytesLike, bytes } from "@ckb-lumos/codec"; | ||
import { hexify } from "@ckb-lumos/codec/lib/bytes"; | ||
|
||
const COMMON_PREFIX = "CKB transaction: 0x"; | ||
|
||
export interface Provider { | ||
request: { | ||
(payload: { | ||
method: "personal_sign"; | ||
params: [from: string, message: string]; | ||
}): Promise<string>; | ||
}; | ||
} | ||
|
||
export async function signMessage( | ||
address: string, | ||
digest: BytesLike, | ||
provider?: Provider | ||
): Promise<string> { | ||
/* c8 ignore start */ | ||
const internal: Provider | undefined = | ||
provider ?? (globalThis as { ethereum?: Provider }).ethereum; | ||
|
||
if (!internal) { | ||
throw new Error( | ||
"No provider found, make sure you have installed MetaMask or the other EIP1193 compatible wallet" | ||
); | ||
} | ||
/* c8 ignore end */ | ||
|
||
const sig = await internal.request({ | ||
method: "personal_sign", | ||
params: [address, `${COMMON_PREFIX}${hexify(digest).slice(2)}`], | ||
}); | ||
|
||
const signature = bytes.bytify(sig); | ||
|
||
const [tweakedV] = signature.slice(-1); | ||
// https://eips.ethereum.org/EIPS/eip-155 | ||
const PARITY_FLAG = 27; | ||
const v = tweakedV >= PARITY_FLAG ? tweakedV - PARITY_FLAG : tweakedV; | ||
signature.set([v], signature.length - 1); | ||
return bytes.hexify(signature); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
packages/common-scripts/tests/omnilock-ethereum-displaying.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import test from "ava"; | ||
import { createOmnilockScript, OmnilockWitnessLock } from "../src/omnilock"; | ||
import { Provider, signMessage } from "../src/omnilock-ethereum-displaying"; | ||
import { BytesLike, bytes } from "@ckb-lumos/codec"; | ||
import { TransactionSkeleton } from "@ckb-lumos/helpers"; | ||
import { | ||
CKBDebuggerDownloader, | ||
createTestContext, | ||
getDefaultConfig, | ||
} from "@ckb-lumos/debugger"; | ||
import common from "../src/common"; | ||
import { mockOutPoint } from "@ckb-lumos/debugger/lib/context"; | ||
import { blockchain, utils } from "@ckb-lumos/base"; | ||
import { | ||
ecsign, | ||
fromSigned, | ||
hashPersonalMessage, | ||
privateToAddress, | ||
toUnsigned, | ||
} from "@ethereumjs/util"; | ||
import { Uint8 } from "@ckb-lumos/codec/lib/number"; | ||
import { randomBytes } from "node:crypto"; | ||
|
||
const context = createTestContext(getDefaultConfig()); | ||
const managerConfig = { PREFIX: "ckt", SCRIPTS: context.scriptConfigs }; | ||
|
||
test.before(async () => { | ||
await new CKBDebuggerDownloader().downloadIfNotExists(); | ||
}); | ||
|
||
test("Omnilock with IdentityEthereumDisplayingFlag", async (t) => { | ||
const privateKey = randomBytes(32); | ||
const provider = makeProvider(privateKey); | ||
|
||
const lock = createOmnilockScript( | ||
{ | ||
auth: { flag: "ETHEREUM-DISPLAYING", content: provider.selectedAddress }, | ||
}, | ||
{ config: managerConfig } | ||
); | ||
|
||
const txSkeleton = TransactionSkeleton().asMutable(); | ||
|
||
await common.setupInputCell( | ||
Check warning on line 44 in packages/common-scripts/tests/omnilock-ethereum-displaying.test.ts GitHub Actions / lint-staged
|
||
txSkeleton, | ||
{ | ||
cellOutput: { lock, capacity: "0x1" }, | ||
data: "0x", | ||
outPoint: mockOutPoint(), | ||
}, | ||
undefined, | ||
{ config: managerConfig } | ||
); | ||
|
||
common.prepareSigningEntries(txSkeleton, { config: managerConfig }); | ||
Check warning on line 55 in packages/common-scripts/tests/omnilock-ethereum-displaying.test.ts GitHub Actions / lint-staged
|
||
|
||
const signedMessage = await signMessage( | ||
provider.selectedAddress, | ||
txSkeleton.get("signingEntries").get(0)!.message, | ||
provider | ||
); | ||
|
||
const signedWitness = bytes.hexify( | ||
blockchain.WitnessArgs.pack({ | ||
lock: OmnilockWitnessLock.pack({ signature: signedMessage }), | ||
}) | ||
); | ||
|
||
txSkeleton.update("witnesses", (witnesses) => | ||
witnesses.set(0, signedWitness) | ||
); | ||
|
||
const result = await context.executor.execute(txSkeleton, { | ||
scriptHash: utils.computeScriptHash(lock), | ||
scriptGroupType: "lock", | ||
}); | ||
|
||
t.is(result.code, 0); | ||
}); | ||
|
||
function makeProvider( | ||
privateKey: BytesLike | ||
): Provider & { selectedAddress: string } { | ||
const privKey = bytes.bytify(privateKey); | ||
const selectedAddress = bytes.hexify(privateToAddress(privKey)); | ||
|
||
return { | ||
selectedAddress, | ||
request: async ({ params }) => { | ||
const message = new TextEncoder().encode(params[1]); | ||
const msgHash = hashPersonalMessage(message); | ||
const sig = ecsign(msgHash, privKey); | ||
|
||
const serialized = concatSig(Uint8.pack(sig.v), sig.r, sig.s); | ||
return serialized; | ||
}, | ||
}; | ||
} | ||
|
||
function concatSig(v: Uint8Array, r: Uint8Array, s: Uint8Array): string { | ||
const rSig = fromSigned(r); | ||
const sSig = fromSigned(s); | ||
|
||
const rStr = toUnsigned(rSig); | ||
const sStr = toUnsigned(sSig); | ||
|
||
return bytes.hexify(bytes.concat(rStr, sStr, v)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
export { | ||
bitcoin, | ||
solana, | ||
ethereumDisplaying, | ||
OmnilockWitnessLock, | ||
createOmnilockScript, | ||
setupInputCell, | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
d279b87
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.
🚀 New canary release:
0.0.0-canary-d279b87-20240624101315