Deduplicate pubkey type strings

This commit is contained in:
Simon Warta 2020-02-05 12:34:34 +01:00
parent 0b3b1559f7
commit 651ba497d9
7 changed files with 44 additions and 35 deletions

View File

@ -1,4 +1,4 @@
import { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "@cosmwasm/sdk"; import { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress, types } from "@cosmwasm/sdk";
import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp";
import { Secp256k1 } from "@iov/crypto"; import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding"; import { Encoding } from "@iov/encoding";
@ -12,9 +12,9 @@ export function decodeCosmosPubkey(
): { readonly algo: Algorithm; readonly data: PubkeyBytes } { ): { readonly algo: Algorithm; readonly data: PubkeyBytes } {
const sdkPubKey = decodeBech32Pubkey(encodedPubkey); const sdkPubKey = decodeBech32Pubkey(encodedPubkey);
switch (sdkPubKey.type) { switch (sdkPubKey.type) {
case "tendermint/PubKeySecp256k1": case types.pubkeyType.secp256k1:
return { algo: Algorithm.Secp256k1, data: fromBase64(sdkPubKey.value) as PubkeyBytes }; return { algo: Algorithm.Secp256k1, data: fromBase64(sdkPubKey.value) as PubkeyBytes };
case "tendermint/PubKeyEd25519": case types.pubkeyType.ed25519:
return { algo: Algorithm.Ed25519, data: fromBase64(sdkPubKey.value) as PubkeyBytes }; return { algo: Algorithm.Ed25519, data: fromBase64(sdkPubKey.value) as PubkeyBytes };
default: default:
throw new Error("Unsupported Pubkey type: " + sdkPubKey.type); throw new Error("Unsupported Pubkey type: " + sdkPubKey.type);
@ -23,22 +23,20 @@ export function decodeCosmosPubkey(
// See https://github.com/tendermint/tendermint/blob/f2ada0a604b4c0763bda2f64fac53d506d3beca7/docs/spec/blockchain/encoding.md#public-key-cryptography // See https://github.com/tendermint/tendermint/blob/f2ada0a604b4c0763bda2f64fac53d506d3beca7/docs/spec/blockchain/encoding.md#public-key-cryptography
export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address { export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address {
let pubkeyType: "tendermint/PubKeySecp256k1" | "tendermint/PubKeyEd25519"; let sdkKey: types.PubKey;
let pubkeyData: Uint8Array = pubkey.data;
if (pubkey.algo === Algorithm.Secp256k1) { if (pubkey.algo === Algorithm.Secp256k1) {
pubkeyType = "tendermint/PubKeySecp256k1"; sdkKey = {
if (pubkeyData.length > 33) { type: types.pubkeyType.secp256k1,
pubkeyData = Secp256k1.compressPubkey(pubkey.data); value: toBase64(pubkey.data.length > 33 ? Secp256k1.compressPubkey(pubkey.data) : pubkey.data),
} };
} else if (pubkey.algo === Algorithm.Ed25519) { } else if (pubkey.algo === Algorithm.Ed25519) {
pubkeyType = "tendermint/PubKeyEd25519"; sdkKey = {
type: types.pubkeyType.ed25519,
value: toBase64(pubkey.data),
};
} else { } else {
throw new Error(`Unsupported algorithm: ${pubkey.algo}`); throw new Error(`Unsupported algorithm: ${pubkey.algo}`);
} }
const sdkKey = {
type: pubkeyType,
value: toBase64(pubkeyData),
};
return encodeAddress(sdkKey, prefix) as Address; return encodeAddress(sdkKey, prefix) as Address;
} }

View File

@ -25,14 +25,12 @@ const { fromBase64 } = Encoding;
export function decodePubkey(pubkey: types.PubKey): PubkeyBundle { export function decodePubkey(pubkey: types.PubKey): PubkeyBundle {
switch (pubkey.type) { switch (pubkey.type) {
// https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 case types.pubkeyType.secp256k1:
case "tendermint/PubKeySecp256k1":
return { return {
algo: Algorithm.Secp256k1, algo: Algorithm.Secp256k1,
data: fromBase64(pubkey.value) as PubkeyBytes, data: fromBase64(pubkey.value) as PubkeyBytes,
}; };
// https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 case types.pubkeyType.ed25519:
case "tendermint/PubKeyEd25519":
return { return {
algo: Algorithm.Ed25519, algo: Algorithm.Ed25519,
data: fromBase64(pubkey.value) as PubkeyBytes, data: fromBase64(pubkey.value) as PubkeyBytes,

View File

@ -20,12 +20,12 @@ export function encodePubkey(pubkey: PubkeyBundle): types.PubKey {
switch (pubkey.algo) { switch (pubkey.algo) {
case Algorithm.Secp256k1: case Algorithm.Secp256k1:
return { return {
type: "tendermint/PubKeySecp256k1", type: types.pubkeyType.secp256k1,
value: toBase64(pubkey.data), value: toBase64(pubkey.data),
}; };
case Algorithm.Ed25519: case Algorithm.Ed25519:
return { return {
type: "tendermint/PubKeyEd25519", type: types.pubkeyType.ed25519,
value: toBase64(pubkey.data), value: toBase64(pubkey.data),
}; };
default: default:

View File

@ -2,7 +2,7 @@ import { Ripemd160, Sha256 } from "@iov/crypto";
import { Bech32, Encoding } from "@iov/encoding"; import { Bech32, Encoding } from "@iov/encoding";
import equal from "fast-deep-equal"; import equal from "fast-deep-equal";
import { Bech32PubKey, PubKey } from "./types"; import { Bech32PubKey, PubKey, pubkeyType } from "./types";
const { fromBase64, toBase64 } = Encoding; const { fromBase64, toBase64 } = Encoding;
@ -40,7 +40,7 @@ export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey)."); throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
} }
return { return {
type: "tendermint/PubKeySecp256k1", type: pubkeyType.secp256k1,
value: toBase64(rest), value: toBase64(rest),
}; };
} else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) { } else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) {
@ -48,7 +48,7 @@ export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey)."); throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey).");
} }
return { return {
type: "tendermint/PubKeyEd25519", type: pubkeyType.ed25519,
value: toBase64(rest), value: toBase64(rest),
}; };
} else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) { } else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) {
@ -56,7 +56,7 @@ export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey)."); throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey).");
} }
return { return {
type: "tendermint/PubKeySr25519", type: pubkeyType.sr25519,
value: toBase64(rest), value: toBase64(rest),
}; };
} else { } else {
@ -81,7 +81,7 @@ export function isValidAddress(address: string): boolean {
export function encodeAddress(pubkey: PubKey, prefix: string): string { export function encodeAddress(pubkey: PubKey, prefix: string): string {
const pubkeyBytes = fromBase64(pubkey.value); const pubkeyBytes = fromBase64(pubkey.value);
switch (pubkey.type) { switch (pubkey.type) {
case "tendermint/PubKeySecp256k1": { case pubkeyType.secp256k1: {
if (pubkeyBytes.length !== 33) { if (pubkeyBytes.length !== 33) {
throw new Error(`Invalid Secp256k1 pubkey length (compressed): ${pubkeyBytes.length}`); throw new Error(`Invalid Secp256k1 pubkey length (compressed): ${pubkeyBytes.length}`);
} }
@ -89,14 +89,14 @@ export function encodeAddress(pubkey: PubKey, prefix: string): string {
const hash2 = new Ripemd160(hash1).digest(); const hash2 = new Ripemd160(hash1).digest();
return Bech32.encode(prefix, hash2); return Bech32.encode(prefix, hash2);
} }
case "tendermint/PubKeyEd25519": { case pubkeyType.ed25519: {
if (pubkeyBytes.length !== 32) { if (pubkeyBytes.length !== 32) {
throw new Error(`Invalid Ed25519 pubkey length: ${pubkeyBytes.length}`); throw new Error(`Invalid Ed25519 pubkey length: ${pubkeyBytes.length}`);
} }
const hash = new Sha256(pubkeyBytes).digest(); const hash = new Sha256(pubkeyBytes).digest();
return Bech32.encode(prefix, hash.slice(0, 20)); return Bech32.encode(prefix, hash.slice(0, 20));
} }
case "tendermint/PubKeySr25519": { case pubkeyType.sr25519: {
if (pubkeyBytes.length !== 32) { if (pubkeyBytes.length !== 32) {
throw new Error(`Invalid Sr25519 pubkey length: ${pubkeyBytes.length}`); throw new Error(`Invalid Sr25519 pubkey length: ${pubkeyBytes.length}`);
} }

View File

@ -1,7 +1,7 @@
import { Secp256k1 } from "@iov/crypto"; import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding"; import { Encoding } from "@iov/encoding";
import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; import { Msg, NonceInfo, pubkeyType, StdFee, StdSignature, StdTx } from "./types";
const { toBase64, toUtf8 } = Encoding; const { toBase64, toUtf8 } = Encoding;
@ -62,7 +62,7 @@ export function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Arr
return { return {
// eslint-disable-next-line @typescript-eslint/camelcase // eslint-disable-next-line @typescript-eslint/camelcase
pub_key: { pub_key: {
type: "tendermint/PubKeySecp256k1", type: pubkeyType.secp256k1,
value: toBase64(Secp256k1.compressPubkey(pubkey)), value: toBase64(Secp256k1.compressPubkey(pubkey)),
}, },
// Recovery seems to be unused // Recovery seems to be unused

View File

@ -110,11 +110,16 @@ export interface PubKey {
readonly value: string; readonly value: string;
} }
export const pubkeyTypes: readonly string[] = [ export const pubkeyType = {
"tendermint/PubKeySecp256k1", /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */
"tendermint/PubKeyEd25519", secp256k1: "tendermint/PubKeySecp256k1" as const,
"tendermint/PubKeySr25519", /** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */
]; ed25519: "tendermint/PubKeyEd25519" as const,
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */
sr25519: "tendermint/PubKeySr25519" as const,
};
export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.ed25519, pubkeyType.sr25519];
// bech32-encoded amino-binary encoded PubKey interface. oof. // bech32-encoded amino-binary encoded PubKey interface. oof.
export type Bech32PubKey = string; export type Bech32PubKey = string;

View File

@ -74,6 +74,14 @@ export interface PubKey {
readonly type: string; readonly type: string;
readonly value: string; readonly value: string;
} }
export declare const pubkeyType: {
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */
secp256k1: "tendermint/PubKeySecp256k1";
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */
ed25519: "tendermint/PubKeyEd25519";
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */
sr25519: "tendermint/PubKeySr25519";
};
export declare const pubkeyTypes: readonly string[]; export declare const pubkeyTypes: readonly string[];
export declare type Bech32PubKey = string; export declare type Bech32PubKey = string;
export interface BaseAccount { export interface BaseAccount {