Add support for multisig in encodeAminoPubkey
This commit is contained in:
parent
61aa989fb3
commit
99e1ac36b8
@ -7,7 +7,7 @@ import {
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./encoding";
|
||||
import { Pubkey } from "./pubkeys";
|
||||
import { MultisigThresholdPubkey, Pubkey } from "./pubkeys";
|
||||
|
||||
describe("encoding", () => {
|
||||
describe("encodeSecp256k1Pubkey", () => {
|
||||
@ -135,5 +135,50 @@ describe("encoding", () => {
|
||||
"coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq",
|
||||
);
|
||||
});
|
||||
|
||||
it("works for multisig", () => {
|
||||
// ./build/wasmd keys add test1
|
||||
// ./build/wasmd keys add test2
|
||||
// ./build/wasmd keys add test3
|
||||
// ./build/wasmd keys add testgroup1 --multisig=test1,test2,test3 --multisig-threshold 2
|
||||
// ./build/wasmd keys add testgroup2 --multisig=test1,test2,test3 --multisig-threshold 1
|
||||
// ./build/wasmd keys add testgroup3 --multisig=test3,test1 --multisig-threshold 2
|
||||
|
||||
const test1 = decodeBech32Pubkey(
|
||||
"wasmpub1addwnpepqwxttx8w2sfs6d8cuzqcuau84grp8xsw95qzdjkmvc44tnckskdxw3zw2km",
|
||||
);
|
||||
const test2 = decodeBech32Pubkey(
|
||||
"wasmpub1addwnpepq2gx7x7e29kge5a4ycunytyqr0u8ynql5h583s8r9wdads9m3v8ks6y0nhc",
|
||||
);
|
||||
const test3 = decodeBech32Pubkey(
|
||||
"wasmpub1addwnpepq0xfx5vavxmgdkn0p6x0l9p3udttghu3qcldd7ql08wa3xy93qq0xuzvtxc",
|
||||
);
|
||||
|
||||
// 2/3 multisig
|
||||
const testgroup1: MultisigThresholdPubkey = {
|
||||
type: "tendermint/PubKeyMultisigThreshold",
|
||||
value: {
|
||||
threshold: "2",
|
||||
pubkeys: [test1, test2, test3],
|
||||
},
|
||||
};
|
||||
const expected1 = Bech32.decode(
|
||||
"wasmpub1ytql0csgqgfzd666axrjzquvkkvwu4qnp5603cyp3emc02sxzwdqutgqym9dke3t2h83dpv6vufzd666axrjzq5sdudaj5tv3nfm2f3exgkgqxlcwfxplf0g0rqwx2um6mqthzc0dqfzd666axrjzq7vjdge6cdksmdx7r5vl72rrc6kk30ezp376mup77wamzvgtzqq7v7aysdd",
|
||||
).data;
|
||||
expect(encodeAminoPubkey(testgroup1)).toEqual(expected1);
|
||||
|
||||
// 1/3 multisig
|
||||
const testgroup2: MultisigThresholdPubkey = {
|
||||
type: "tendermint/PubKeyMultisigThreshold",
|
||||
value: {
|
||||
threshold: "1",
|
||||
pubkeys: [test1, test2, test3],
|
||||
},
|
||||
};
|
||||
const expected2 = Bech32.decode(
|
||||
"wasmpub1ytql0csgqyfzd666axrjzquvkkvwu4qnp5603cyp3emc02sxzwdqutgqym9dke3t2h83dpv6vufzd666axrjzq5sdudaj5tv3nfm2f3exgkgqxlcwfxplf0g0rqwx2um6mqthzc0dqfzd666axrjzq7vjdge6cdksmdx7r5vl72rrc6kk30ezp376mup77wamzvgtzqq7vc4ejke",
|
||||
).data;
|
||||
expect(encodeAminoPubkey(testgroup2)).toEqual(expected2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Bech32, fromBase64, fromHex, toBase64, toHex } from "@cosmjs/encoding";
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
import { arrayContentStartsWith } from "@cosmjs/utils";
|
||||
|
||||
import { Pubkey, pubkeyType, Secp256k1Pubkey } from "./pubkeys";
|
||||
import { isMultisigThresholdPubkey, Pubkey, pubkeyType, Secp256k1Pubkey } from "./pubkeys";
|
||||
|
||||
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): Secp256k1Pubkey {
|
||||
if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) {
|
||||
@ -19,6 +20,8 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): Secp256k1Pubkey {
|
||||
const pubkeyAminoPrefixSecp256k1 = fromHex("eb5ae987" + "21" /* fixed length */);
|
||||
const pubkeyAminoPrefixEd25519 = fromHex("1624de64" + "20" /* fixed length */);
|
||||
const pubkeyAminoPrefixSr25519 = fromHex("0dfb1005" + "20" /* fixed length */);
|
||||
/** See https://github.com/tendermint/tendermint/commit/38b401657e4ad7a7eeb3c30a3cbf512037df3740 */
|
||||
const pubkeyAminoPrefixMultisigThreshold = fromHex("22c1f7e2" /* variable length not included */);
|
||||
|
||||
/**
|
||||
* Decodes a pubkey in the Amino binary format to a type/value object.
|
||||
@ -67,10 +70,28 @@ export function decodeBech32Pubkey(bechEncoded: string): Pubkey {
|
||||
return decodeAminoPubkey(data);
|
||||
}
|
||||
|
||||
function encodeSmallUint(value: number | string): number[] {
|
||||
const checked = Uint53.fromString(value.toString()).toNumber();
|
||||
if (checked > 127) throw new Error("Encoding numbers > 127 is not supported here.");
|
||||
return [checked];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a public key to binary Amino.
|
||||
*/
|
||||
export function encodeAminoPubkey(pubkey: Pubkey): Uint8Array {
|
||||
if (isMultisigThresholdPubkey(pubkey)) {
|
||||
const out = Array.from(pubkeyAminoPrefixMultisigThreshold);
|
||||
out.push(8); // TODO: What is this?
|
||||
out.push(...encodeSmallUint(pubkey.value.threshold));
|
||||
for (const pubkeyData of pubkey.value.pubkeys.map((p) => encodeAminoPubkey(p))) {
|
||||
out.push(18); // TODO: What is this?
|
||||
out.push(...encodeSmallUint(pubkeyData.length));
|
||||
out.push(...pubkeyData);
|
||||
}
|
||||
return new Uint8Array(out);
|
||||
}
|
||||
|
||||
let aminoPrefix: Uint8Array;
|
||||
switch (pubkey.type) {
|
||||
// Note: please don't add cases here without writing additional unit tests
|
||||
|
||||
@ -18,6 +18,7 @@ export const pubkeyType = {
|
||||
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,
|
||||
multisigThreshold: "tendermint/PubKeyMultisigThreshold" as const,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user