Skip to content

Commit

Permalink
fix: generate correct inj sigs in MnemonicWallet
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronCQL committed Feb 2, 2024
1 parent af1bda5 commit 76b733e
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 20 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# Changelog

## `v0.0.54`

### Fixes

- Fixed `MnemonicWallet` to generate Injective signatures correctly

## `v0.0.53`

### Fixes

- Fixed `MnemonicWallet` to work with Injective
- Fixed `MnemonicWallet` to resolve Injective address correctly

## `v0.0.52`

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cosmes",
"version": "0.0.53",
"version": "0.0.54",
"private": false,
"packageManager": "[email protected]",
"sideEffects": false,
Expand Down
46 changes: 44 additions & 2 deletions src/codec/sign.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
import { base16, utf8 } from "@scure/base";
import { StdSignDoc } from "@keplr-wallet/types";
import { base16, base64, utf8 } from "@scure/base";
import { describe, expect, it } from "vitest";

import { ethhex } from "./ethhex";
import { hashEthArbitraryMessage, recoverPubKeyFromEthSignature } from "./sign";
import {
hashEthArbitraryMessage,
recoverPubKeyFromEthSignature,
signAmino,
} from "./sign";

describe("signAmino", () => {
it("should sign Injective txs correctly", () => {
const stdSignDoc: StdSignDoc = {
chain_id: "",
account_number: "0",
sequence: "0",
fee: {
gas: "0",
amount: [],
},
msgs: [
{
type: "sign/MsgSignData",
value: {
signer: "inj1l8w4vvmhcku28ryntpeazm37umshetzzl2gc33",
data: base64.encode(
utf8.decode(
"Hi from CosmeES! This is a test message just to prove that the wallet is working."
)
),
},
},
],
memo: "",
};
const privKey = base64.decode(
"o5di+2p2NdLgRYLtBIhJl9gsB9FWll8wKBaep3CmbI0="
);
const expected = // Signature taken from keplr signArbitrary
"qrkZpuo1jpfXgbF3TtBtdR7DynE1nV3xd//bsGXm2FkS08waXeiJJ+FAvdtt9hvStyP/wGae07hxnyYPHEw+Uw==";
const actual = base64.encode(
signAmino(stdSignDoc, privKey, "ethsecp256k1")
);
expect(actual).toStrictEqual(expected);
});
});

describe("hashEthArbitraryMessage", () => {
it("should hash correctly", () => {
Expand Down
26 changes: 17 additions & 9 deletions src/codec/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,43 @@ import { StdSignDoc } from "cosmes/registry";

import { serialiseSignDoc } from "./serialise";

function sign(bytes: Uint8Array, privateKey: Uint8Array): Uint8Array {
function sign(
bytes: Uint8Array,
privateKey: Uint8Array,
type: "secp256k1" | "ethsecp256k1"
): Uint8Array {
// Required polyfills for secp256k1 that must be called before any sign ops.
// See: https://github.com/paulmillr/noble-secp256k1?tab=readme-ov-file#usage
secp256k1.etc.hmacSha256Sync = (k, ...m) =>
hmac(sha256, k, secp256k1.etc.concatBytes(...m));

return secp256k1.sign(sha256(bytes), privateKey).toCompactRawBytes();
const hash = type === "secp256k1" ? sha256(bytes) : keccak_256(bytes);
return secp256k1.sign(hash, privateKey).toCompactRawBytes();
}

/**
* Signs the given amino-encoded `stdSignDoc` with the given `privateKey` using
* secp256k1, and returns the signature bytes.
* secp256k1, and returns the signature bytes. For Injective, the `type` param
* must be set to `ethsecp256k1`.
*/
export function signAmino(
stdSignDoc: StdSignDoc,
privateKey: Uint8Array
privateKey: Uint8Array,
type: "secp256k1" | "ethsecp256k1" = "secp256k1"
): Uint8Array {
return sign(serialiseSignDoc(stdSignDoc), privateKey);
return sign(serialiseSignDoc(stdSignDoc), privateKey, type);
}

/**
* Signs the given proto-encoded `signDoc` with the given `privateKey` using
* secp256k1, and returns the signature bytes.
* secp256k1, and returns the signature bytes. For Injective, the `type` param
* must be set to `ethsecp256k1`.
*/
export function signDirect(
signDoc: SignDoc,
privateKey: Uint8Array
privateKey: Uint8Array,
type: "secp256k1" | "ethsecp256k1" = "secp256k1"
): Uint8Array {
return sign(signDoc.toBinary(), privateKey);
return sign(signDoc.toBinary(), privateKey, type);
}

/**
Expand Down
15 changes: 8 additions & 7 deletions src/wallet/wallets/mnemonic/MnemonicWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export type ConnectMnemonicWalletOptions = Prettify<
export class MnemonicWallet extends ConnectedWallet {
public readonly publicKey: string;
public readonly privateKey: Uint8Array;
public readonly keyType: "secp256k1" | "ethsecp256k1";

constructor({
mnemonic,
Expand All @@ -91,11 +92,10 @@ export class MnemonicWallet extends ConnectedWallet {
coinType,
index,
});
const address = resolveBech32Address(
publicKey,
bech32Prefix,
chainId.startsWith("injective-") ? "ethsecp256k1" : "secp256k1"
);
const keyType = chainId.startsWith("injective-")
? "ethsecp256k1"
: "secp256k1";
const address = resolveBech32Address(publicKey, bech32Prefix, keyType);
super(
// We typecast here instead of adding "mnemonic" to `WalletName` and
// `WalletType` as this wallet is considered a special wallet that is
Expand All @@ -110,6 +110,7 @@ export class MnemonicWallet extends ConnectedWallet {
);
this.publicKey = base64.encode(publicKey);
this.privateKey = privateKey;
this.keyType = keyType;
}

public async signArbitrary(data: string): Promise<SignArbitraryResponse> {
Expand All @@ -134,7 +135,7 @@ export class MnemonicWallet extends ConnectedWallet {
],
memo: "",
};
const signature = signAmino(doc, this.privateKey);
const signature = signAmino(doc, this.privateKey, this.keyType);
return {
data,
pubKey: this.publicKey,
Expand All @@ -160,7 +161,7 @@ export class MnemonicWallet extends ConnectedWallet {
memo,
timeoutHeight,
});
const signature = signDirect(doc, this.privateKey);
const signature = signDirect(doc, this.privateKey, this.keyType);
return RpcClient.broadcastTx(this.rpc, tx.toSignedDirect(doc, signature));
}
}

0 comments on commit 76b733e

Please sign in to comment.