Merge pull request #64 from confio/unused-account

Add unused account for more explicit testing of authAccounts
This commit is contained in:
Simon Warta 2020-02-09 14:43:39 +01:00 committed by GitHub
commit 4cd2aff735
36 changed files with 410 additions and 294 deletions

View File

@ -1,7 +1,7 @@
import { Algorithm, PubkeyBytes } from "@iov/bcp";
import { Encoding } from "@iov/encoding";
import { decodeCosmosPubkey, isValidAddress, pubkeyToAddress } from "./address";
import { decodeCosmosPubkey, pubkeyToAddress } from "./address";
const { fromBase64, fromHex } = Encoding;
@ -17,23 +17,6 @@ describe("address", () => {
});
});
describe("isValidAddress", () => {
it("accepts valid addresses", () => {
expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true);
expect(isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual(true);
expect(isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual(true);
});
it("rejects invalid addresses", () => {
// Bad size
expect(isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false);
// Bad checksum
expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false);
// Bad prefix
expect(isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false);
});
});
describe("pubkeyToAddress", () => {
it("works for Secp256k1 compressed", () => {
const prefix = "cosmos";

View File

@ -1,10 +1,8 @@
import { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress, types } from "@cosmwasm/sdk";
import { CosmosAddressBech32Prefix, decodeBech32Pubkey, encodeAddress, types } from "@cosmwasm/sdk";
import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp";
import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
export { CosmosBech32Prefix, isValidAddress };
const { fromBase64, toBase64 } = Encoding;
export function decodeCosmosPubkey(
@ -22,7 +20,7 @@ export function decodeCosmosPubkey(
}
// 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: CosmosAddressBech32Prefix): Address {
let sdkKey: types.PubKey;
if (pubkey.algo === Algorithm.Secp256k1) {
sdkKey = {

View File

@ -7,6 +7,27 @@ import { chainId, nonce, sendTxJson, signedTxBin, signedTxEncodedJson, signedTxJ
const { toUtf8 } = Encoding;
describe("cosmWasmCodec", () => {
describe("isValidAddress", () => {
it("accepts valid addresses", () => {
expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true);
expect(cosmWasmCodec.isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual(
true,
);
expect(cosmWasmCodec.isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual(
true,
);
});
it("rejects invalid addresses", () => {
// Bad size
expect(cosmWasmCodec.isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false);
// Bad checksum
expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false);
// Bad prefix
expect(cosmWasmCodec.isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false);
});
});
it("properly generates bytes to sign", () => {
const expected = {
bytes: toUtf8(

View File

@ -1,5 +1,12 @@
/* eslint-disable @typescript-eslint/camelcase */
import { makeSignBytes, marshalTx, types, unmarshalTx } from "@cosmwasm/sdk";
import {
CosmosAddressBech32Prefix,
isValidAddress,
makeSignBytes,
marshalTx,
types,
unmarshalTx,
} from "@cosmwasm/sdk";
import {
Address,
ChainId,
@ -15,18 +22,18 @@ import {
UnsignedTransaction,
} from "@iov/bcp";
import { CosmosBech32Prefix, isValidAddress, pubkeyToAddress } from "./address";
import { pubkeyToAddress } from "./address";
import { Caip5 } from "./caip5";
import { parseTx } from "./decode";
import { buildSignedTx, buildUnsignedTx } from "./encode";
import { nonceToAccountNumber, nonceToSequence, TokenInfos } from "./types";
export class CosmWasmCodec implements TxCodec {
private readonly prefix: CosmosBech32Prefix;
private readonly addressPrefix: CosmosAddressBech32Prefix;
private readonly tokens: TokenInfos;
public constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos) {
this.prefix = prefix;
public constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos) {
this.addressPrefix = addressPrefix;
this.tokens = tokens;
}
@ -76,7 +83,7 @@ export class CosmWasmCodec implements TxCodec {
}
public identityToAddress(identity: Identity): Address {
return pubkeyToAddress(identity.pubkey, this.prefix);
return pubkeyToAddress(identity.pubkey, this.addressPrefix);
}
public isValidAddress(address: string): boolean {
@ -84,7 +91,7 @@ export class CosmWasmCodec implements TxCodec {
}
}
const defaultPrefix = "cosmos" as CosmosBech32Prefix;
const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix;
const defaultTokens: TokenInfos = [
{

View File

@ -1,3 +1,4 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import {
Address,
Algorithm,
@ -14,7 +15,6 @@ import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol";
import { CosmosBech32Prefix } from "./address";
import { CosmWasmCodec, cosmWasmCodec } from "./cosmwasmcodec";
import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection";
import { signedTxJson, txId } from "./testdata.spec";
@ -43,7 +43,7 @@ describe("CosmWasmConnection", () => {
const faucetPath = HdPaths.cosmos(0);
const defaultRecipient = "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" as Address;
const defaultPrefix = "cosmos" as CosmosBech32Prefix;
const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix;
// this is for wasmd blockchain
const defaultTokens: TokenConfiguration = [

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/camelcase */
import { RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk";
import { CosmosAddressBech32Prefix, RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk";
import {
Account,
AccountQuery,
@ -34,7 +34,7 @@ import equal from "fast-deep-equal";
import { ReadonlyDate } from "readonly-date";
import { Stream } from "xstream";
import { CosmosBech32Prefix, decodeCosmosPubkey, pubkeyToAddress } from "./address";
import { decodeCosmosPubkey, pubkeyToAddress } from "./address";
import { Caip5 } from "./caip5";
import { decodeAmount, parseTxsResponse } from "./decode";
import { accountToNonce, TokenInfo } from "./types";
@ -75,12 +75,12 @@ export class CosmWasmConnection implements BlockchainConnection {
// we must know prefix and tokens a priori to understand the chain
public static async establish(
url: string,
prefix: CosmosBech32Prefix,
addressPrefix: CosmosAddressBech32Prefix,
tokens: TokenConfiguration,
): Promise<CosmWasmConnection> {
const restClient = new RestClient(url);
const chainData = await this.initialize(restClient);
return new CosmWasmConnection(restClient, chainData, prefix, tokens);
return new CosmWasmConnection(restClient, chainData, addressPrefix, tokens);
}
private static async initialize(restClient: RestClient): Promise<ChainData> {
@ -90,26 +90,22 @@ export class CosmWasmConnection implements BlockchainConnection {
private readonly restClient: RestClient;
private readonly chainData: ChainData;
private readonly _prefix: CosmosBech32Prefix;
private readonly addressPrefix: CosmosAddressBech32Prefix;
private readonly tokenInfo: readonly TokenInfo[];
// these are derived from arguments (cached for use in multiple functions)
private readonly primaryToken: Token;
private readonly supportedTokens: readonly Token[];
private get prefix(): CosmosBech32Prefix {
return this._prefix;
}
private constructor(
restClient: RestClient,
chainData: ChainData,
prefix: CosmosBech32Prefix,
addressPrefix: CosmosAddressBech32Prefix,
tokens: TokenConfiguration,
) {
this.restClient = restClient;
this.chainData = chainData;
this._prefix = prefix;
this.addressPrefix = addressPrefix;
this.tokenInfo = tokens;
this.supportedTokens = tokens.map(info => ({
@ -149,7 +145,7 @@ export class CosmWasmConnection implements BlockchainConnection {
}
public async getAccount(query: AccountQuery): Promise<Account | undefined> {
const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address;
const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address;
const { result } = await this.restClient.authAccounts(address);
const account = result.value;
if (!account.address) {
@ -172,7 +168,7 @@ export class CosmWasmConnection implements BlockchainConnection {
}
public async getNonce(query: AddressQuery | PubkeyQuery): Promise<Nonce> {
const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address;
const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address;
const { result } = await this.restClient.authAccounts(address);
const account = result.value;
return accountToNonce(account);

View File

@ -1,6 +1,6 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import { ChainConnector, ChainId } from "@iov/bcp";
import { CosmosBech32Prefix } from "./address";
import { CosmWasmCodec } from "./cosmwasmcodec";
import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection";
@ -9,13 +9,13 @@ import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection";
*/
export function createCosmWasmConnector(
url: string,
prefix: CosmosBech32Prefix,
addressPrefix: CosmosAddressBech32Prefix,
tokens: TokenConfiguration,
expectedChainId?: ChainId,
): ChainConnector<CosmWasmConnection> {
const codec = new CosmWasmCodec(prefix, tokens);
const codec = new CosmWasmCodec(addressPrefix, tokens);
return {
establishConnection: async () => CosmWasmConnection.establish(url, prefix, tokens),
establishConnection: async () => CosmWasmConnection.establish(url, addressPrefix, tokens),
codec: codec,
expectedChainId: expectedChainId,
};

View File

@ -1,10 +1,9 @@
import { CosmosBech32Prefix, isValidAddress } from "@cosmwasm/sdk";
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp";
export { CosmosBech32Prefix, isValidAddress };
export declare function decodeCosmosPubkey(
encodedPubkey: string,
): {
readonly algo: Algorithm;
readonly data: PubkeyBytes;
};
export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address;
export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosAddressBech32Prefix): Address;

View File

@ -1,3 +1,4 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import {
Address,
ChainId,
@ -10,12 +11,11 @@ import {
TxCodec,
UnsignedTransaction,
} from "@iov/bcp";
import { CosmosBech32Prefix } from "./address";
import { TokenInfos } from "./types";
export declare class CosmWasmCodec implements TxCodec {
private readonly prefix;
private readonly addressPrefix;
private readonly tokens;
constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos);
constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos);
bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob;
bytesToPost(signed: SignedTransaction): PostableBytes;
identifier(_signed: SignedTransaction): TransactionId;

View File

@ -1,3 +1,4 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import {
Account,
AccountQuery,
@ -20,7 +21,6 @@ import {
UnsignedTransaction,
} from "@iov/bcp";
import { Stream } from "xstream";
import { CosmosBech32Prefix } from "./address";
import { TokenInfo } from "./types";
export declare type TokenConfiguration = ReadonlyArray<
TokenInfo & {
@ -30,17 +30,16 @@ export declare type TokenConfiguration = ReadonlyArray<
export declare class CosmWasmConnection implements BlockchainConnection {
static establish(
url: string,
prefix: CosmosBech32Prefix,
addressPrefix: CosmosAddressBech32Prefix,
tokens: TokenConfiguration,
): Promise<CosmWasmConnection>;
private static initialize;
private readonly restClient;
private readonly chainData;
private readonly _prefix;
private readonly addressPrefix;
private readonly tokenInfo;
private readonly primaryToken;
private readonly supportedTokens;
private get prefix();
private constructor();
disconnect(): void;
chainId(): ChainId;

View File

@ -1,12 +1,12 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import { ChainConnector, ChainId } from "@iov/bcp";
import { CosmosBech32Prefix } from "./address";
import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection";
/**
* A helper to connect to a cosmos-based chain at a given url
*/
export declare function createCosmWasmConnector(
url: string,
prefix: CosmosBech32Prefix,
addressPrefix: CosmosAddressBech32Prefix,
tokens: TokenConfiguration,
expectedChainId?: ChainId,
): ChainConnector<CosmWasmConnection>;

View File

@ -1,21 +1,10 @@
import { Encoding } from "@iov/encoding";
import { decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
import { encodeAddress, isValidAddress } from "./address";
const { toBase64, fromHex } = Encoding;
describe("address", () => {
describe("decodeBech32Pubkey", () => {
it("works", () => {
expect(
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
).toEqual({
type: "tendermint/PubKeySecp256k1",
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
});
});
});
describe("isValidAddress", () => {
it("accepts valid addresses", () => {
expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true);

View File

@ -1,69 +1,17 @@
import { Ripemd160, Sha256 } from "@iov/crypto";
import { Bech32, Encoding } from "@iov/encoding";
import equal from "fast-deep-equal";
import { Bech32PubKey, PubKey, pubkeyType } from "./types";
import { PubKey, pubkeyType } from "./types";
const { fromBase64, toBase64 } = Encoding;
const { fromBase64 } = Encoding;
// TODO: make this much more configurable
export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper";
export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
export type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix;
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);
}
// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163
// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography
// Last bytes is varint-encoded length prefix
const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721");
const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420");
const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005");
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
const { prefix, data } = Bech32.decode(bech);
if (!isCosmosPubkeyBech32Prefix(prefix)) {
throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`);
}
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
const rest = data.slice(pubkeyAminoPrefixLength);
if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) {
if (rest.length !== 33) {
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
}
return {
type: pubkeyType.secp256k1,
value: toBase64(rest),
};
} else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) {
if (rest.length !== 32) {
throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey).");
}
return {
type: pubkeyType.ed25519,
value: toBase64(rest),
};
} else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) {
if (rest.length !== 32) {
throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey).");
}
return {
type: pubkeyType.sr25519,
value: toBase64(rest),
};
} else {
throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix));
}
}
export function isValidAddress(address: string): boolean {
try {
const { prefix, data } = Bech32.decode(address);

View File

@ -2,9 +2,14 @@ import * as logs from "./logs";
import * as types from "./types";
export { logs, types };
export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address";
export { unmarshalTx } from "./decoding";
export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
export { RestClient, TxsResponse } from "./restclient";
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
export { encodeSecp256k1Pubkey } from "./pubkey";
export {
CosmosPubkeyBech32Prefix,
decodeBech32Pubkey,
encodeBech32Pubkey,
encodeSecp256k1Pubkey,
} from "./pubkey";

View File

@ -1,6 +1,7 @@
import { Encoding } from "@iov/encoding";
import { encodeSecp256k1Pubkey } from "./pubkey";
import { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
import { PubKey } from "./types";
const { fromBase64 } = Encoding;
@ -24,4 +25,27 @@ describe("pubkey", () => {
});
});
});
describe("decodeBech32Pubkey", () => {
it("works", () => {
expect(
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
).toEqual({
type: "tendermint/PubKeySecp256k1",
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
});
});
});
describe("encodeBech32Pubkey", () => {
it("works for secp256k1", () => {
const pubkey: PubKey = {
type: "tendermint/PubKeySecp256k1",
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
};
expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual(
"cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5",
);
});
});
});

View File

@ -1,7 +1,8 @@
import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { Bech32, Encoding } from "@iov/encoding";
import equal from "fast-deep-equal";
import { PubKey, pubkeyType } from "./types";
import { Bech32PubKey, PubKey, pubkeyType } from "./types";
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
return {
@ -9,3 +10,70 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
value: Encoding.toBase64(Secp256k1.compressPubkey(pubkey)),
};
}
export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
const validPubkeyPrefixes = ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"];
function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix {
return validPubkeyPrefixes.includes(prefix);
}
// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163
// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography
// Last bytes is varint-encoded length prefix
const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721");
const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420");
const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005");
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
const { prefix, data } = Bech32.decode(bech);
if (!isCosmosPubkeyBech32Prefix(prefix)) {
throw new Error(`Invalid bech32 prefix. Must be one of ${validPubkeyPrefixes.join(", ")}.`);
}
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
const rest = data.slice(pubkeyAminoPrefixLength);
if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) {
if (rest.length !== 33) {
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
}
return {
type: pubkeyType.secp256k1,
value: Encoding.toBase64(rest),
};
} else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) {
if (rest.length !== 32) {
throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey).");
}
return {
type: pubkeyType.ed25519,
value: Encoding.toBase64(rest),
};
} else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) {
if (rest.length !== 32) {
throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey).");
}
return {
type: pubkeyType.sr25519,
value: Encoding.toBase64(rest),
};
} else {
throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix));
}
}
export function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey {
let aminoPrefix: Uint8Array;
switch (pubkey.type) {
// Note: please don't add cases here without writing additional unit tests
case pubkeyType.secp256k1:
aminoPrefix = pubkeyAminoPrefixSecp256k1;
break;
default:
throw new Error("Unsupported pubkey type");
}
const data = new Uint8Array([...aminoPrefix, ...Encoding.fromBase64(pubkey.value)]);
return Bech32.encode(prefix, data);
}

View File

@ -6,6 +6,7 @@ import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
import { leb128Encode } from "./leb128.spec";
import { findAttribute, parseLogs } from "./logs";
import { Pen, Secp256k1Pen } from "./pen";
import { encodeBech32Pubkey } from "./pubkey";
import { PostTxsResponse, RestClient } from "./restclient";
import contract from "./testdata/contract.json";
import cosmoshub from "./testdata/cosmoshub.json";
@ -25,10 +26,19 @@ const { fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding;
const httpUrl = "http://localhost:1317";
const defaultNetworkId = "testing";
const faucetMnemonic =
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone";
const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6";
const faucet = {
mnemonic:
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
pubkey: {
type: "tendermint/PubKeySecp256k1",
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
},
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
};
const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k";
const unusedAccount = {
address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u",
};
function pendingWithoutCosmos(): void {
if (!process.env.COSMOS_ENABLED) {
@ -80,7 +90,7 @@ async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResp
const theMsg: MsgStoreCode = {
type: "wasm/store-code",
value: {
sender: faucetAddress,
sender: faucet.address,
wasm_byte_code: toBase64(getRandomizedContract()),
source: "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm",
builder: "cosmwasm-opt:0.6.2",
@ -96,7 +106,7 @@ async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResp
gas: "89000000",
};
const account = (await client.authAccounts(faucetAddress)).result.value;
const account = (await client.authAccounts(faucet.address)).result.value;
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -114,10 +124,10 @@ async function instantiateContract(
const theMsg: MsgInstantiateContract = {
type: "wasm/instantiate",
value: {
sender: faucetAddress,
sender: faucet.address,
code_id: codeId.toString(),
init_msg: {
verifier: faucetAddress,
verifier: faucet.address,
beneficiary: beneficiaryAddress,
},
init_funds: transferAmount || [],
@ -133,7 +143,7 @@ async function instantiateContract(
gas: "89000000",
};
const account = (await client.authAccounts(faucetAddress)).result.value;
const account = (await client.authAccounts(faucet.address)).result.value;
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -149,7 +159,7 @@ async function executeContract(
const theMsg: MsgExecuteContract = {
type: "wasm/execute",
value: {
sender: faucetAddress,
sender: faucet.address,
contract: contractAddress,
msg: {},
sent_funds: [],
@ -165,7 +175,7 @@ async function executeContract(
gas: "89000000",
};
const account = (await client.authAccounts(faucetAddress)).result.value;
const account = (await client.authAccounts(faucet.address)).result.value;
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -188,13 +198,40 @@ describe("RestClient", () => {
});
describe("authAccounts", () => {
it("works", async () => {
it("works for unused account without pubkey", async () => {
pendingWithoutCosmos();
const client = new RestClient(httpUrl);
const { result } = await client.authAccounts(faucetAddress);
const account = result.value;
expect(account.account_number).toEqual(4);
expect(account.sequence).toBeGreaterThanOrEqual(0);
const { result } = await client.authAccounts(unusedAccount.address);
expect(result).toEqual({
type: "cosmos-sdk/Account",
value: {
address: unusedAccount.address,
public_key: "", // not known to the chain
coins: [
{
amount: "1000000000",
denom: "ucosm",
},
{
amount: "1000000000",
denom: "ustake",
},
],
account_number: 5,
sequence: 0,
},
});
});
it("has correct pubkey for faucet", async () => {
pendingWithoutCosmos();
const client = new RestClient(httpUrl);
const { result } = await client.authAccounts(faucet.address);
expect(result.value).toEqual(
jasmine.objectContaining({
public_key: encodeBech32Pubkey(faucet.pubkey, "cosmospub"),
}),
);
});
});
@ -210,13 +247,13 @@ describe("RestClient", () => {
describe("post", () => {
it("can send tokens", async () => {
pendingWithoutCosmos();
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
const memo = "My first contract on chain";
const theMsg: MsgSend = {
type: "cosmos-sdk/MsgSend",
value: {
from_address: faucetAddress,
from_address: faucet.address,
to_address: emptyAddress,
amount: [
{
@ -238,7 +275,7 @@ describe("RestClient", () => {
};
const client = new RestClient(httpUrl);
const account = (await client.authAccounts(faucetAddress)).result.value;
const account = (await client.authAccounts(faucet.address)).result.value;
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
@ -250,7 +287,7 @@ describe("RestClient", () => {
it("can upload, instantiate and execute wasm", async () => {
pendingWithoutCosmos();
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
const client = new RestClient(httpUrl);
const transferAmount: readonly Coin[] = [
@ -316,7 +353,7 @@ describe("RestClient", () => {
describe("query", () => {
it("can list upload code", async () => {
pendingWithoutCosmos();
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
const client = new RestClient(httpUrl);
// check with contracts were here first to compare
@ -336,17 +373,17 @@ describe("RestClient", () => {
expect(newInfos.length).toEqual(numExisting + 1);
const lastInfo = newInfos[newInfos.length - 1];
expect(lastInfo.id).toEqual(codeId);
expect(lastInfo.creator).toEqual(faucetAddress);
expect(lastInfo.creator).toEqual(faucet.address);
// TODO: check code hash matches expectation
// expect(lastInfo.code_hash).toEqual(faucetAddress);
// expect(lastInfo.code_hash).toEqual(faucet.address);
// TODO: download code and check against auto-gen
});
it("can list contracts and get info", async () => {
pendingWithoutCosmos();
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
const client = new RestClient(httpUrl);
const beneficiaryAddress = makeRandomAddress();
const transferAmount: readonly Coin[] = [
@ -390,7 +427,7 @@ describe("RestClient", () => {
// check out info
const myInfo = await client.getContractInfo(myAddress);
expect(myInfo.code_id).toEqual(codeId);
expect(myInfo.creator).toEqual(faucetAddress);
expect(myInfo.creator).toEqual(faucet.address);
expect((myInfo.init_msg as any).beneficiary).toEqual(beneficiaryAddress);
// make sure random addresses don't give useful info
@ -459,7 +496,7 @@ describe("RestClient", () => {
// we can query the verifier properly
const verifier = await client.queryContractSmart(contractAddress, { verifier: {} });
expect(verifier).toEqual(faucetAddress);
expect(verifier).toEqual(faucet.address);
// invalid query syntax throws an error
await client.queryContractSmart(contractAddress, { nosuchkey: {} }).then(

View File

@ -1,7 +1,7 @@
import { Encoding } from "@iov/encoding";
import axios, { AxiosInstance } from "axios";
import { AminoTx, BaseAccount, CodeInfo, ContractInfo, isAminoStdTx, StdTx, WasmData } from "./types";
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, isAminoStdTx, StdTx, WasmData } from "./types";
const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding;
@ -37,7 +37,8 @@ interface BlocksResponse {
interface AuthAccountsResponse {
readonly result: {
readonly value: BaseAccount;
readonly type: "cosmos-sdk/Account";
readonly value: CosmosSdkAccount;
};
}

View File

@ -151,7 +151,7 @@ export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.
// bech32-encoded amino-binary encoded PubKey interface. oof.
export type Bech32PubKey = string;
export interface BaseAccount {
export interface CosmosSdkAccount {
/** Bech32 account address */
readonly address: string;
readonly coins: ReadonlyArray<Coin>;
@ -160,8 +160,8 @@ export interface BaseAccount {
readonly sequence: number;
}
/** The data we need from BaseAccount to create a nonce */
export type NonceInfo = Pick<BaseAccount, "account_number" | "sequence">;
/** The data we need from CosmosSdkAccount to create a nonce */
export type NonceInfo = Pick<CosmosSdkAccount, "account_number" | "sequence">;
export interface CodeInfo {
readonly id: number;

View File

@ -1,7 +1,4 @@
import { Bech32PubKey, PubKey } from "./types";
import { PubKey } from "./types";
export declare type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper";
export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
export declare type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix;
export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey;
export declare function isValidAddress(address: string): boolean;
export declare function encodeAddress(pubkey: PubKey, prefix: string): string;

View File

@ -1,9 +1,14 @@
import * as logs from "./logs";
import * as types from "./types";
export { logs, types };
export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address";
export { unmarshalTx } from "./decoding";
export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
export { RestClient, TxsResponse } from "./restclient";
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
export { encodeSecp256k1Pubkey } from "./pubkey";
export {
CosmosPubkeyBech32Prefix,
decodeBech32Pubkey,
encodeBech32Pubkey,
encodeSecp256k1Pubkey,
} from "./pubkey";

View File

@ -1,2 +1,5 @@
import { PubKey } from "./types";
import { Bech32PubKey, PubKey } from "./types";
export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey;
export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey;
export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey;

View File

@ -1,4 +1,4 @@
import { AminoTx, BaseAccount, CodeInfo, ContractInfo, StdTx, WasmData } from "./types";
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, StdTx, WasmData } from "./types";
interface NodeInfo {
readonly network: string;
}
@ -26,7 +26,8 @@ interface BlocksResponse {
}
interface AuthAccountsResponse {
readonly result: {
readonly value: BaseAccount;
readonly type: "cosmos-sdk/Account";
readonly value: CosmosSdkAccount;
};
}
declare type WasmResponse = WasmSuccess | WasmError;

View File

@ -110,7 +110,7 @@ export declare const pubkeyType: {
};
export declare const pubkeyTypes: readonly string[];
export declare type Bech32PubKey = string;
export interface BaseAccount {
export interface CosmosSdkAccount {
/** Bech32 account address */
readonly address: string;
readonly coins: ReadonlyArray<Coin>;
@ -118,8 +118,8 @@ export interface BaseAccount {
readonly account_number: number;
readonly sequence: number;
}
/** The data we need from BaseAccount to create a nonce */
export declare type NonceInfo = Pick<BaseAccount, "account_number" | "sequence">;
/** The data we need from CosmosSdkAccount to create a nonce */
export declare type NonceInfo = Pick<CosmosSdkAccount, "account_number" | "sequence">;
export interface CodeInfo {
readonly id: number;
/** Bech32 account address */

View File

@ -78,3 +78,12 @@ You should get output matching the following:
threshold: 0
pubkeys: []
```
## Preset accounts
1. Faucet<br>
economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone<br>
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
2. Unused: for testing account state; this account never changes balances or nonces<br>
oyster design unusual machine spread century engine gravity focus cave carry slot<br>
cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u

View File

@ -26,6 +26,7 @@ const defaultFee = {
const faucetMnemonic =
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone";
const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6";
const unusedAccount = "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u";
async function uploadContract(client, pen, wasm) {
const memo = "Upload ERC20 contract";
@ -96,6 +97,10 @@ async function main() {
address: faucetAddress,
amount: "11",
},
{
address: unusedAccount,
amount: "12812345",
},
],
};
const instantiationResult = await instantiateContract(client, pen, codeId, initMsg);

View File

@ -2,22 +2,24 @@
set -o errexit -o nounset -o pipefail
command -v shellcheck > /dev/null && shellcheck "$0"
# Choose from https://hub.docker.com/r/cosmwasm/wasmd/tags
REPOSITORY="cosmwasm/wasmd"
VERSION="manual"
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
# shellcheck source=./env
# shellcheck disable=SC1091
source "$SCRIPT_DIR"/env
rm -rf "$SCRIPT_DIR/template"
mkdir "$SCRIPT_DIR/template"
# any any more addresses you want to fund in genesis below
# The usage of the accounts below is documented in README.md of this directory
docker run --rm \
-e PASSWORD=my-secret-password \
--mount type=bind,source="$SCRIPT_DIR/template",target=/root \
"$REPOSITORY:$VERSION" \
./setup.sh \
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u
# this is created as root, let's make it ours
sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template"
# The ./template folder is created by the docker daemon's user (root on Linux, current user
# when using Docker Desktop on macOS), let's make it ours if needed
if [ ! -x "$SCRIPT_DIR/template/.wasmd/config/gentx" ]; then
sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template"
fi

View File

@ -1 +0,0 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNzA4NjQ4OSArMDAwMCBVVEMgbT0rMC4yMjM1NjMwMDAiLCJlbmMiOiJBMjU2R0NNIiwicDJjIjo4MTkyLCJwMnMiOiJmU2Q5OUVVUldWQW9EY0Z5In0.KuQ7PWpuxAAjkdWw6e9IUPi_o3Ud-L_MhTNQ5NNwI1MFxvc0Jg__Bg.y7kp74vcKuEgrxUa.pLhY4Qup_jmjSpWjJN0NSJ84IMdhpyOT-IOFfdjNvvihg3ohZWFROrLP1LzZ9FINwbnFMqrmIxgxbrNMOH45U1OahlaswRUP8eVcbF4E4ZF-ZfpYEpCClNG41T-cBV2SzMySkdYAv_u-FJ4_b66nfJ7wYkfOJrff5e8g-FDlIe90PBrGR6c6YLr0XOH6X9uZVF3mWFfYc_jxKT_uoJMcbkefOEPr0W3mVFc-RAvaQ54Az6n_o1tOC6iQBoZ2PHc.I5HjgFmEZwtYqYQfM7VnHg

View File

@ -0,0 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNjg2NzQ1ICswMDAwIFVUQyBtPSswLjIyNTA4MDAwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6ImR3S2hTZDJfT1c4UDkyY00ifQ._x85VK6XkQ6XVU4zoSEEjAtMO7qCoSGWiVIo0OJtbksUCWsYhbRPTg.09Qg67smHfoMlScZ.YDYvL193V0G2u9fuJYF-1CSykfctJv8VFpQR3eYroPT233CQI9uXb2KUAK0lP_4AIrDREvkVv1CWQ3Wa0WTGSrOFepIB2X3AFGAf2gw8OsZybdsRiN2Y__7Ljmo7rNjMur9L53fiY7Y4eN83oP9034FovfByDeAL85Lwc0r1Jbf9u4wEB4QudtlFGjfbgfUw4MBDImpmI1dPfnw_1izqWgvlbDlpAzQUALo90gCHtwuCOsVgpCNeFOci5eV60LA.kNLZneL-i5Dzi8Xhi8bU_w

View File

@ -1 +1 @@
$2a$10$vAg6eRcBB2poo3HKW0wpreHFth9sb9oYoFskLYc9H39ApJiPsGriG
$2a$10$wE2S5ENI/eoNUjFTtNCisOmJWW0h0yIVHBr1CjlrDzcCDBRozAZqO

View File

@ -1 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNjI2NzMwNDUgKzAwMDAgVVRDIG09KzAuMjE1MzcxMTY3IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiLUNHTldlMFg4bjEwZDl1VyJ9.Cxq-oR7LM1CmAaNO6O0nihb4f-4FFY6qnW-XGO3Trbq9694n4LFBlw.da-kCbllD1_XoMHF.oiuts-8U9mWmJs9xOnWC0NJabUM4FRgSnHKgBce3XzhdSnrhODbbaKkR9EhZFHNWw_h1o27ZxeEtHmPyqv-A5lz4zwwbapi1g7qcZhQW_dI0_4yJ16U5AMdvo7PH5lWXK9z6H0ReG8CIW5aw_CrQBd4egjyGMxQVAABOFAhQ747KGGu76L5vIpfi2b7wJx_z7gS1x6PNSHHR7KOvgQ9hqG6B5VkjPo85JdyRRz00jJec88JXutvdKVbpvVldB8BGsURHFVyYvR3Nj0a7daSroxxkk63T1pZTLIPncYn-XFruKTJE3xmzAu-ojjB1VevGp0dQ8drWcNE_D2nphXP3PLdd-zhfpNkIWfSB8Kh1geeK9xFi.XXG7ekj8VeF6RZaLbTsH0w
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNDgzNjkzICswMDAwIFVUQyBtPSswLjIwNDc3NjcwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6IkRfU1A3Ni1zU3lCRkY0cUQifQ.CPLPgBUrK53I4uLXRR7ba78yQlfio1QI6xedzWjCnTlKEUIdso1c7g.SvJq7pwz3Z86LrNU.03eoFsTiIAfHa2XH14Rgh7bvUnzkH_q4ljLyweN93GVIQIgWjqhRXzaf3ZdZ34i5H0TIs9xr7LcvbttvsUpetw1GjujFboY6hDWhMD0hOE67NysQPIYIsIbC76y5O5_Q6HVZ14vxuEbxgF8qJjGUnpAwqoNwUDBQr8Nju8ZpcAt9Y9VGDw-wiYS3TuYLEED84XQuUwWAIbQNbqvRaY6ZuVtL30-j1cVpy6AyuHmKlFS5L7ddB64eQfni9LErc2VqTnBZypuuaJ1CuGwL1gM0cQrtpRXM-rmSFvu0nXciDqJ2bIUa3qBwULtnBaVqSSAkrj-DgTbHPWhX7RyJoVObEqtQ_XRrB252aKj5HudlYjUThE3O.JWWfqTMVbUQpqUTfepEixA

View File

@ -1,5 +1,5 @@
{
"genesis_time": "2020-01-30T20:58:17.838935022Z",
"genesis_time": "2020-02-09T11:05:31.7520515Z",
"chain_id": "testing",
"consensus_params": {
"block": {
@ -19,18 +19,25 @@
},
"app_hash": "",
"app_state": {
"slashing": {
"distribution": {
"params": {
"signed_blocks_window": "100",
"min_signed_per_window": "0.500000000000000000",
"downtime_jail_duration": "600000000000",
"slash_fraction_double_sign": "0.050000000000000000",
"slash_fraction_downtime": "0.010000000000000000"
"community_tax": "0.020000000000000000",
"base_proposer_reward": "0.010000000000000000",
"bonus_proposer_reward": "0.040000000000000000",
"withdraw_addr_enabled": true
},
"signing_infos": {},
"missed_blocks": {}
"fee_pool": {
"community_pool": []
},
"delegator_withdraw_infos": [],
"previous_proposer": "",
"outstanding_rewards": [],
"validator_accumulated_commissions": [],
"validator_historical_rewards": [],
"validator_current_rewards": [],
"delegator_starting_infos": [],
"validator_slash_events": []
},
"params": null,
"gov": {
"starting_proposal_id": "1",
"deposits": null,
@ -54,12 +61,96 @@
"veto": "0.334000000000000000"
}
},
"slashing": {
"params": {
"signed_blocks_window": "100",
"min_signed_per_window": "0.500000000000000000",
"downtime_jail_duration": "600000000000",
"slash_fraction_double_sign": "0.050000000000000000",
"slash_fraction_downtime": "0.010000000000000000"
},
"signing_infos": {},
"missed_blocks": {}
},
"supply": {
"supply": []
},
"wasm": {
"codes": null,
"contracts": null
},
"mint": {
"minter": {
"inflation": "0.130000000000000000",
"annual_provisions": "0.000000000000000000"
},
"params": {
"mint_denom": "ustake",
"inflation_rate_change": "0.130000000000000000",
"inflation_max": "0.200000000000000000",
"inflation_min": "0.070000000000000000",
"goal_bonded": "0.670000000000000000",
"blocks_per_year": "6311520"
}
},
"genutil": {
"gentxs": [
{
"type": "cosmos-sdk/StdTx",
"value": {
"msg": [
{
"type": "cosmos-sdk/MsgCreateValidator",
"value": {
"description": {
"moniker": "testing",
"identity": "",
"website": "",
"security_contact": "",
"details": ""
},
"commission": {
"rate": "0.100000000000000000",
"max_rate": "0.200000000000000000",
"max_change_rate": "0.010000000000000000"
},
"min_self_delegation": "1",
"delegator_address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg",
"validator_address": "cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm",
"pubkey": "cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88",
"value": {
"denom": "ustake",
"amount": "250000000"
}
}
}
],
"fee": {
"amount": [],
"gas": "200000"
},
"signatures": [
{
"pub_key": {
"type": "tendermint/PubKeySecp256k1",
"value": "AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ"
},
"signature": "+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A=="
}
],
"memo": "67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656"
}
}
]
},
"evidence": {
"params": {
"max_evidence_age": "120000000000"
},
"evidence": []
},
"params": null,
"upgrade": {},
"staking": {
"params": {
"unbonding_time": "1814400000000000",
@ -76,35 +167,6 @@
"redelegations": null,
"exported": false
},
"distribution": {
"params": {
"community_tax": "0.020000000000000000",
"base_proposer_reward": "0.010000000000000000",
"bonus_proposer_reward": "0.040000000000000000",
"withdraw_addr_enabled": true
},
"fee_pool": {
"community_pool": []
},
"delegator_withdraw_infos": [],
"previous_proposer": "",
"outstanding_rewards": [],
"validator_accumulated_commissions": [],
"validator_historical_rewards": [],
"validator_current_rewards": [],
"delegator_starting_infos": [],
"validator_slash_events": []
},
"bank": {
"send_enabled": true
},
"crisis": {
"constant_fee": {
"denom": "ustake",
"amount": "1000"
}
},
"upgrade": {},
"auth": {
"params": {
"max_memo_characters": "256",
@ -117,7 +179,7 @@
{
"type": "cosmos-sdk/Account",
"value": {
"address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w",
"address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg",
"coins": [
{
"denom": "ucosm",
@ -151,79 +213,36 @@
"account_number": 0,
"sequence": 0
}
}
]
},
"mint": {
"minter": {
"inflation": "0.130000000000000000",
"annual_provisions": "0.000000000000000000"
},
"params": {
"mint_denom": "ustake",
"inflation_rate_change": "0.130000000000000000",
"inflation_max": "0.200000000000000000",
"inflation_min": "0.070000000000000000",
"goal_bonded": "0.670000000000000000",
"blocks_per_year": "6311520"
}
},
"wasm": {
"codes": null,
"contracts": null
},
"supply": {
"supply": []
},
"genutil": {
"gentxs": [
},
{
"type": "cosmos-sdk/StdTx",
"type": "cosmos-sdk/Account",
"value": {
"msg": [
"address": "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u",
"coins": [
{
"type": "cosmos-sdk/MsgCreateValidator",
"value": {
"description": {
"moniker": "testing",
"identity": "",
"website": "",
"security_contact": "",
"details": ""
},
"commission": {
"rate": "0.100000000000000000",
"max_rate": "0.200000000000000000",
"max_change_rate": "0.010000000000000000"
},
"min_self_delegation": "1",
"delegator_address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w",
"validator_address": "cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka",
"pubkey": "cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9",
"value": {
"denom": "ustake",
"amount": "250000000"
}
}
"denom": "ucosm",
"amount": "1000000000"
},
{
"denom": "ustake",
"amount": "1000000000"
}
],
"fee": {
"amount": [],
"gas": "200000"
},
"signatures": [
{
"pub_key": {
"type": "tendermint/PubKeySecp256k1",
"value": "AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH"
},
"signature": "zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA=="
}
],
"memo": "c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656"
"public_key": "",
"account_number": 0,
"sequence": 0
}
}
]
},
"crisis": {
"constant_fee": {
"denom": "ustake",
"amount": "1000"
}
},
"bank": {
"send_enabled": true
}
}
}

View File

@ -0,0 +1 @@
{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg","validator_address":"cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm","pubkey":"cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ"},"signature":"+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A=="}],"memo":"67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656"}}

View File

@ -1 +0,0 @@
{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w","validator_address":"cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka","pubkey":"cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH"},"signature":"zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA=="}],"memo":"c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656"}}

View File

@ -1 +1 @@
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"G0VvywcXFSI5HASlbKRK/vAI2NNolDw1P/2fgWtfva/P8L9yiw2luZfu6cKbijEg/op2lOqV3CbfMo+B1P6G3w=="}}
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"i42pVrwetpGZFC78UUNhL6Bk41/N3sKDW9XKNz+IOm/JX5aN10vUrpA52DXOQNug55lTvTyuPR8izLSBcovIrg=="}}

View File

@ -1,11 +1,11 @@
{
"address": "9CBD80593D47022DFE9A0356F350A4D233E92AEB",
"address": "3FBF50B72FE062495F150AEB78D1981E7DAEBE60",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "tfkKoKWpnpcNBhjAXUTA4i9oMs+EXOlujriy/2Jz29o="
"value": "ff4Kip9dNfI/3PFdFkdlRQu4Ptb3yWnQDJ1OrXoHKW8="
},
"priv_key": {
"type": "tendermint/PrivKeyEd25519",
"value": "NkIf2Dije6K8xOqZ7ni+f3+TDjuOrV5Q68g0coD8j6O1+Qqgpamelw0GGMBdRMDiL2gyz4Rc6W6OuLL/YnPb2g=="
"value": "yMKZJArmVw5zXDTHbYR0sNRqugzW3HNbO6yK5bOHYBp9/gqKn1018j/c8V0WR2VFC7g+1vfJadAMnU6tegcpbw=="
}
}