Add decodeCosmosPubkey

This commit is contained in:
Simon Warta 2020-01-23 17:20:34 +01:00
parent c428e40e79
commit cae35522ce
3 changed files with 47 additions and 2 deletions

View File

@ -1,7 +1,7 @@
import { Address, Algorithm, PubkeyBytes } from "@iov/bcp";
import { Encoding } from "@iov/encoding";
import { decodeCosmosAddress, isValidAddress, pubkeyToAddress } from "./address";
import { decodeCosmosAddress, decodeCosmosPubkey, isValidAddress, pubkeyToAddress } from "./address";
const { fromBase64, fromHex } = Encoding;
@ -28,6 +28,17 @@ describe("address", () => {
});
});
describe("decodeCosmosPubkey", () => {
it("works", () => {
expect(
decodeCosmosPubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
).toEqual({
prefix: "cosmospub",
data: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"),
});
});
});
describe("isValidAddress", () => {
it("accepts valid addresses", () => {
expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true);

View File

@ -1,15 +1,23 @@
import { Address, Algorithm, PubkeyBundle } from "@iov/bcp";
import { Ripemd160, Secp256k1, Sha256 } from "@iov/crypto";
import { Bech32 } from "@iov/encoding";
import { Bech32, Encoding } from "@iov/encoding";
import equal from "fast-deep-equal";
export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper";
export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
export type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix;
// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163
const pubkeyAminoPrefix = Encoding.fromHex("eb5ae98721");
function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBech32Prefix {
return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix);
}
function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix {
return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix);
}
export function decodeCosmosAddress(
address: Address,
): { readonly prefix: CosmosAddressBech32Prefix; readonly data: Uint8Array } {
@ -23,6 +31,26 @@ export function decodeCosmosAddress(
return { prefix: prefix, data: data };
}
export function decodeCosmosPubkey(
encodedPubkey: string,
): { readonly prefix: CosmosPubkeyBech32Prefix; readonly data: Uint8Array } {
const { prefix, data } = Bech32.decode(encodedPubkey);
if (!isCosmosPubkeyBech32Prefix(prefix)) {
throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`);
}
if (!equal(data.slice(0, pubkeyAminoPrefix.length), pubkeyAminoPrefix)) {
throw new Error("Pubkey does not have the expected amino prefix " + Encoding.toHex(pubkeyAminoPrefix));
}
const rest = data.slice(pubkeyAminoPrefix.length);
if (rest.length !== 33) {
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
}
return { prefix: prefix, data: rest };
}
export function isValidAddress(address: string): boolean {
try {
decodeCosmosAddress(address as Address);

6
types/address.d.ts vendored
View File

@ -8,5 +8,11 @@ export declare function decodeCosmosAddress(
readonly prefix: CosmosAddressBech32Prefix;
readonly data: Uint8Array;
};
export declare function decodeCosmosPubkey(
encodedPubkey: string,
): {
readonly prefix: CosmosPubkeyBech32Prefix;
readonly data: Uint8Array;
};
export declare function isValidAddress(address: string): boolean;
export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address;