Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ADR-028 implementation and test CosmWasm contract addresses #857

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packages/proto-signing/src/adr28.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Bech32 } from "@cosmjs/encoding";
import { Uint64 } from "@cosmjs/math";

import { moduleAddressRaw } from "./adr28";

describe("adr28", () => {
describe("moduleAddressRaw", () => {
it("can be used for wasm contract address derivation", () => {
function contractAddressRaw(codeId: number, contractId: number): Uint8Array {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very cool. glad to see this cross-test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you want to expose this function not just in tests? (but i guess in cosmwasm package?)

The slice(0, 20) is unique to our 0.42-compatible code. The 0.43 sdk has 32 byte addresses 😱 (actually a mix between 20 and 32 I think) hope that doesn't break other tests

Copy link
Member Author

@webmaster128 webmaster128 Jul 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just to test the generic ADR-28 implementation. Turns out no CosmWasm client needs to know how contract addresses are generated. They just use them. So I don't see a point in exposing that.

const key = new Uint8Array([
...Uint64.fromNumber(codeId).toBytesBigEndian(),
...Uint64.fromNumber(contractId).toBytesBigEndian(),
]);
return moduleAddressRaw("wasm", key).slice(0, 20);
}

function contractAddress(codeId: number, contractId: number): string {
return Bech32.encode("cosmos", contractAddressRaw(codeId, contractId));
}

// Test vectors from https://github.com/CosmWasm/wasmd/pull/565
expect(contractAddress(1, 1)).toEqual("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6");
expect(contractAddress(1, 100)).toEqual("cosmos1mujpjkwhut9yjw4xueyugc02evfv46y04aervg");
expect(contractAddress(2 ** 32, 17)).toEqual("cosmos1673hrexz4h6s0ft04l96ygq667djzh2nvy7fsu");
expect(contractAddress(22, 2 ** 32)).toEqual("cosmos10q3pgfvmeyy0veekgtqhxujxkhz0vm9z65ckqh");
});
});
});
34 changes: 34 additions & 0 deletions packages/proto-signing/src/adr28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Sha256, sha256 } from "@cosmjs/crypto";
import { Bech32, toUtf8 } from "@cosmjs/encoding";

/**
* Creates a basic address according to [ADR-028].
*
* This is called `Hash` in the document.
*
* [ADR-028]: https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md
*/
export function basicAddressRaw(type: string, key: Uint8Array): Uint8Array {
const innerHash = sha256(toUtf8(type));
const outerHash = new Sha256(innerHash).update(key).digest();
// `A_LEN` is 32 and `hash` is sha256 so we avoid all the truncation clutter.
return outerHash;
}

/**
* Creates a raw (i.e. binary) module address accoding to [ADR-028].
*
* [ADR-028]: https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md
*/
export function moduleAddressRaw(moduleName: string, key: Uint8Array): Uint8Array {
return basicAddressRaw("module", new Uint8Array([...toUtf8(moduleName), 0x00, ...key]));
}

/**
* Creates a bech32 encoded module address accoding to [ADR-028].
*
* [ADR-028]: https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md
*/
export function moduleAddress(moduleName: string, key: Uint8Array, prefix: string): string {
return Bech32.encode(prefix, moduleAddressRaw(moduleName, key));
}