From 8034ae7bc6a659ea8fc74ee367118284e0868008 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 01:16:28 +0100 Subject: [PATCH 01/14] Move sortJson into @cosmwasm/sdk --- packages/bcp/src/cosmwasmcodec.ts | 20 +------------------- packages/sdk/src/encoding.ts | 18 ++++++++++++++++++ packages/sdk/src/index.ts | 2 +- packages/sdk/types/encoding.d.ts | 1 + packages/sdk/types/index.d.ts | 2 +- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index caf46ad7..7602830f 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { marshalTx, unmarshalTx } from "@cosmwasm/sdk"; +import { marshalTx, sortJson, unmarshalTx } from "@cosmwasm/sdk"; import { Address, ChainId, @@ -24,24 +24,6 @@ import { nonceToAccountNumber, nonceToSequence, TokenInfos } from "./types"; const { toUtf8 } = Encoding; -function sortJson(json: any): any { - if (typeof json !== "object" || json === null) { - return json; - } - if (Array.isArray(json)) { - return json.map(sortJson); - } - const sortedKeys = Object.keys(json).sort(); - const result = sortedKeys.reduce( - (accumulator, key) => ({ - ...accumulator, - [key]: sortJson(json[key]), - }), - {}, - ); - return result; -} - export class CosmWasmCodec implements TxCodec { private readonly prefix: CosmosBech32Prefix; private readonly tokens: TokenInfos; diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index 6f6d9be3..3cee29af 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -2,6 +2,24 @@ import { Encoding } from "@iov/encoding"; import { StdTx } from "./types"; +export function sortJson(json: any): any { + if (typeof json !== "object" || json === null) { + return json; + } + if (Array.isArray(json)) { + return json.map(sortJson); + } + const sortedKeys = Object.keys(json).sort(); + const result = sortedKeys.reduce( + (accumulator, key) => ({ + ...accumulator, + [key]: sortJson(json[key]), + }), + {}, + ); + return result; +} + export function marshalTx(tx: StdTx): Uint8Array { const json = JSON.stringify(tx); return Encoding.toUtf8(json); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index d84968e5..23e94da1 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,6 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { marshalTx } from "./encoding"; +export { marshalTx, sortJson } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index 7a33940a..591bdbb4 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,2 +1,3 @@ import { StdTx } from "./types"; +export declare function sortJson(json: any): any; export declare function marshalTx(tx: StdTx): Uint8Array; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 4420e59b..0c6dcc71 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,5 +1,5 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { marshalTx } from "./encoding"; +export { marshalTx, sortJson } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; From 28a4518edf3b650d1c8f6d9655a5c9c3d38e005b Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 11:28:09 +0100 Subject: [PATCH 02/14] Test wasm upload in RestServer --- packages/sdk/package.json | 2 + packages/sdk/src/restclient.spec.ts | 82 ++++++++++++++++++++++++- packages/sdk/src/testdata/contract.json | 4 ++ packages/sdk/src/types.ts | 13 +++- packages/sdk/types/types.d.ts | 12 +++- 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 packages/sdk/src/testdata/contract.json diff --git a/packages/sdk/package.json b/packages/sdk/package.json index ab71861e..12243e6f 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -42,5 +42,7 @@ "axios": "^0.19.0" }, "devDependencies": { + "@iov/bcp": "^2.0.0-alpha.7", + "@iov/keycontrol": "^2.0.0-alpha.7" } } diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 33f27ffd..48fd024f 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -1,14 +1,23 @@ /* eslint-disable @typescript-eslint/camelcase */ +import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; +import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; +import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; +import { types } from "src"; +import { marshalTx, sortJson } from "./encoding"; import { RestClient } from "./restclient"; +import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { StdTx } from "./types"; +import { StdSignature, StdTx } from "./types"; -const { fromBase64 } = Encoding; +const { fromBase64, toBase64, toUtf8 } = 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 faucetPath = HdPaths.cosmos(0); const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; function pendingWithoutCosmos(): void { @@ -51,4 +60,73 @@ describe("RestClient", () => { expect(await client.encodeTx(tx)).toEqual(fromBase64(data.tx_data)); }); }); + + describe("post", () => { + it("can upload wasm", async () => { + pendingWithoutCosmos(); + const wallet = Secp256k1HdWallet.fromMnemonic(faucetMnemonic); + const signer = await wallet.createIdentity("abc" as ChainId, faucetPath); + + const memo = "My first contract on chain"; + const theMsg: types.Msg = { + type: "wasm/store-code", + value: { + sender: faucetAddress, + wasm_byte_code: contract.data, + source: "https://mycoderepo.example/134", + builder: "v0.0.1", + }, + }; + + const unsigned: StdTx = { + msg: [theMsg], + memo: memo, + signatures: [], + fee: { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "200000", + }, + }; + + const client = new RestClient(httpUrl); + const account = (await client.authAccounts(faucetAddress)).result.value; + + const signMsg = sortJson({ + account_number: account.account_number.toString(), + chain_id: defaultNetworkId, + fee: unsigned.fee, + memo: memo, + msgs: unsigned.msg, + sequence: account.sequence.toString(), + }); + + const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes; + const signature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); + const fullSignature: StdSignature = { + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: toBase64(Secp256k1.compressPubkey(signer.pubkey.data)), + }, + // Recovery seems to be unused + signature: toBase64(Secp256k1.trimRecoveryByte(signature)), + }; + + const tx: StdTx = { + msg: unsigned.msg, + fee: unsigned.fee, + memo: memo, + signatures: [fullSignature], + }; + + const postableBytes = marshalTx(tx); + const result = await client.postTx(postableBytes); + // console.log("Raw log:", result.raw_log); + expect(result.code).toBeFalsy(); + }); + }); }); diff --git a/packages/sdk/src/testdata/contract.json b/packages/sdk/src/testdata/contract.json new file mode 100644 index 00000000..9619452a --- /dev/null +++ b/packages/sdk/src/testdata/contract.json @@ -0,0 +1,4 @@ +{ + "// source": "https://github.com/confio/cosmwasm/blob/0.7/lib/vm/testdata/contract_0.6.wasm", + "data": "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BEAgFBAVCyAcBEAgExAVCwJAIBBFDQAgGARAIBAgGEEYbGohASAQIQADQCAAQQRqKAIABEAgACgCABAVCyAAQRBqKAIABEAgAEEMaigCABAVCyAAQRhqIgIhACABIAJHDQALCyAdRQ0AIBAQFQsgGgRAIBYQFQsgC0UNGCARBEAgCyARQRhsaiEBIAshAANAIABBBGooAgAEQCAAKAIAEBULIABBEGooAgAEQCAAQQxqKAIAEBULIABBGGoiAiEAIAEgAkcNAAsLIBdFDRggCxAVDBgLIABBADYCACAAQdQAaiARNgIAIABB0ABqIBc2AgAgAEHMAGogCzYCACAAQcgAaiAhNgIAIABBxABqIBo2AgAgAEFAayAWNgIAIABBPGogGDYCACAAQThqIB02AgAgAEE0aiAQNgIAIABBMGogIjYCACAAQSxqIBw2AgAgAEEoaiATNgIAIABBIGogJTcDACAAQRxqIB42AgAgAEEYaiAUNgIAIABBEGogJzcDACAAQQxqICM2AgAgAEEIaiAkNgIADBcLIB4EQCAgEBULIApFIQVBAQwSC0EDIQELIAZFIAJFIAlBD0dyckUEQCAEEBULAkACQAJAAkACQAJAIAFBAk0EQCABQQFrDgIEAwELIANB0AFqIAwQSiADKALQASICQRFGDQEgAygC2AEhBiADKALUASEEIAMgAygC3AEiBzYC/AEgAyAGNgL4ASADIAQ2AvQBIAMgAjYC8AEMFQsgFA0LIANB0AFqIAwQSiADKALQASICQRFHBEAgAygC3AEhByADKALYASEGIAMoAtQBIQQMFQsgA0EwaiAMEE0gAy0AMEEBcUUEQEEDIQIMEgsgAy0AMUH7AEcEQEEKIQIMEgsgDBB0IANBKGogDBCDAUEBIQIgAygCKCEBIAMgAy0ALEEBcSIKOgDsASADIAE2AugBIANBIGogARBNIAMtACBBAXFFDRQgAy0AISEJQQAhFEIAISUgCiEIQgAhJgNAAkACQAJAIAlB/wFxIgJBLEcEQCACQf0ARg0BIApB/wFxDQJBBiECDBULIAhB/wFxDQEgARB0IANBGGogARBNIAMtABhBAXFFDRMgAy0AGSEJDAILICVCAVIEQCADQdABakGfgMAAQQYQXAwSCyAmQgFSBEAgA0HQAWpBpYDAAEEEEFwMEgsgFEUEQCADQdABakGpgMAAQQgQXCADQdwBaigCACEHIANB2AFqKAIADBALIANB0AFqIAwQRyADKALQASICQRFHBEAgAygC3AEhByADKALYASEGIAMoAtQBIQQgDUUNGCAUEBUMGAsgKEIgiKchIyAnpyEHIA+tISUgKKchJCANIR4gFCEgDAYLQQAhCiADQQA6AOwBCyAJQf8BcSIEQSJHBEBBDkEMIARB/QBGGyECDBILIANBEGogARBNIAMtABBBAXFFDRAgAy0AEUEiRwRAQQohAgwSCyABEHQgA0HQAWogARA+IAMoAtwBIQYgAygC2AEhBCADKALUASECIAMoAtABIghBAUYEQCADKALgASEHDBILAkACQCAEQXxqIglBBEsNAAJAAkACQCAJQQFrDgQDAAMCAQtBACEHIAJBn4DAAEYNAyACQZ+AwABBBhBkRQ0DDAILQQEhByACQaWAwABGDQIgAigAAEH00rWrBkcNAQwCC0ECIQcgAkGpgMAARg0BIAIpAABC49CFy+bt17TkAFENAQtBAyEHCyAGRSAIRSACQQ9HcnJFBEAgBBAVCwJAAkACQAJAAkACQAJAIAdBAk0EQCAHQQFrDgICAwELIANB0AFqIAEQSiADKALQASICQRFGDQMgAygC2AEhBiADKALUASEEIANB/AFqIAMoAtwBIgc2AgAgA0H4AWogBjYCACADIAQ2AvQBIAMgAjYC8AEMGAsgJUIBUgRAIANB0AFqIANB6AFqECAgAygC0AFBAUYNFSADKQPYASEoQgEhJQwFCyADQdABakGfgMAAQQYQXQwVCyAmQgFRDQQgA0HQAWogA0HoAWoQICADKALQAUEBRg0TIAMpA9gBISdCASEmDAMLIBRFBEAgA0HwAWogARBKIAMoAvABIgJBEUYNAiADKAL4ASEGIAMoAvQBIQQgA0HgAWogAygC/AEiBzYCACADIAY2AtwBIAMgBDYC2AEgAyACNgLUASADQQE2AtABDBoLIANB0AFqQamAwABBCBBdDBMLIANB8AFqIAEQDyADKALwASICQRFGDQEgA0H8AWooAgAhByADQfgBaigCACEGIAMoAvQBIQQMFAsgA0HQAWogARAvIAMoAtABQQFGBEAgA0HgAWooAgAhByADKALcASEGIAMoAtgBIQQgAygC1AEhAgwYCyADKALcASEPIAMoAtgBIQ0gAygC1AEhFAsgA0EIaiABEE1BASECQQAhCCADLQAJIQkgAy0ACEEBcQ0BDBILCyADQdABakGlgMAAQQQQXQwOCyADQfABaiAMEA8gAygC8AEiAkERRg0CIAMoAvwBIQcgAygC+AEhBiADKAL0ASEEDBMLAkACQAJAAkACQCAWRQRAIANB0AFqIAwQSkEAIQ0gAygC0AEiAkERRwRAIAMoAtwBIQcgAygC2AEhBiADKALUASEEDBwLIANBkAFqIAwQTSADLQCQAUEBcUUEQEEDIQIMBgsgAy0AkQFB+wBHBEBBCiECDAYLIAwQdCADQYgBaiAMEIMBQQEhAiADKAKIASEOIAMgAy0AjAFBAXEiDzoA7AEgAyAONgLoASADQYABaiAOEE0gAy0AgAFBAXFFDQQgAy0AgQEhAUEAIRIgDyEJQQAhFkEAIRUDQCAKIREgCyEXIAUhCAJAAkACQCABQf8BcSICQSxHBEAgAkH9AEYNASAPQf8BcQ0CQQYhAgwHCyAJQf8BcQ0BIA4QdCADQfgAaiAOEE0gAy0AeEEBcUUNBSADLQB5IQEMAgsgEkUEQCADQdABakHBgMAAQQcQXCADQdwBaigCACEHIANB2AFqKAIAIQYgAygC1AEhBCADKALQASECQQAhEgwGCyAVQQFGIQICQCAIRSAVQQJJcg0AIBEEQCAIIBFBGGxqIQYgCCEBA0AgAUEEaigCAARAIAEoAgAQFQsgAUEQaigCACIEBEAgAUEMaigCABAVCyABQRhqIgUhASAFIAZHDQALCyAXRQ0AIAgQFQsgCEEAIAIbIQsgA0HQAWogDBBHIAMoAtABIgJBEUYNCiADKALcASEHIAMoAtgBIQYgAygC1AEhBCAaBEAgFhAVCyALRQRAQQAhBQwfCyARBEAgCyARQRhsaiEFIAshAQNAIAFBBGooAgAEQCABKAIAEBULIAFBEGooAgAEQCABQQxqKAIAEBULIAFBGGoiCCEBIAUgCEcNAAsLIBdFBEBBACEFDB8LIAsQFUEAIQUMHgtBACEPIANBADoA7AELIAFB/wFxIgFBIkcEQEEMIQIgAUH9AEcNBEEOIQIMBAsgA0HwAGogDhBNIAMtAHBBAXFFDQIgAy0AcUEiRwRAQQohAgwECyAOEHQgA0HQAWogDhA+IAMoAtwBIQYgAygC2AEhBCADKALUASECIAMoAtABIgVBAUYEQCADKALgASEHDAQLAkAgBEEHRgRAQQAhASACQcGAwABGDQEgAkHBgMAAQQcQZEUNAUEBIQEgAkHIgMAARg0BIAJByIDAAEEHEGRFDQELQQIhAQsgBkUgBUUgAkEPR3JyRQRAIAQQFQsCQAJAAkACQAJAAkACQAJAIAFBAU0EQCABQQFrDQEMAgsgA0HQAWogDhBKIAMoAtABIgJBEUYNAiADKALYASEGIAMoAtQBIQQgA0H8AWogAygC3AEiBzYCACADQfgBaiAGNgIAIAMgBDYC9AEgAyACNgLwAQwLCyASRQRAIANB0AFqIANB6AFqEBIgAygC0AFBAUcNBSADQeABaigCACEHIAMoAtwBIQYgAygC2AEhBCADKALUASECQQAhEgwLCyADQdABakHBgMAAQQcQXSADQdwBaigCACEHIANB2AFqKAIAIQYgAygC1AEhBCADKALQASECDAoLIBVBAUYNBSADQdABaiADQegBahAHIAMoAtwBIQogAygC2AEhCyADKALUASEFIAMoAtABIgJBAUcEQAJAIBVFIAhFcg0AIBEEQCAIIBFBGGxqIQYgCCEBA0AgAUEEaigCAARAIAEoAgAQFQsgAUEQaigCACIEBEAgAUEMaigCABAVCyABQRhqIgkhASAGIAlHDQALCyAXBEAgCBAVCyACRSAFQQ9Hcg0AIAoNAwtBASEVDAULIANB4AFqKAIAIQcgBSECIAshBCAKIQYMCQsgA0HwAWogDhAPIAMoAvABIgJBEUcNASARIQogFyELIAghBQwDCyALEBVBASEVDAILIANB/AFqKAIAIQcgA0H4AWooAgAhBiADKAL0ASEEDAYLIAMoAtwBISEgAygC2AEhGiARIQogFyELIAghBSADKALUASIWIRILIANB6ABqIA4QTUEBIQJBACEJIAMtAGkhASADLQBoQQFxDQEMBQsLIANB0AFqQciAwABBBxBdIANB3AFqKAIAIQcgA0HYAWooAgAhBiADKALUASEEIAMoAtABIQJBASEVDAILIANB0AFqQZeAwABBCBBdIANB3AFqKAIAIQcgA0HYAWooAgAhBiADKALUASEEIAMoAtABIQJBACENDBkLQQMhAgsgESEKIBchCyAIIQULAkAgBUUgFUVyDQAgCgRAIAUgCkEYbGohCCAFIQEDQCAB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YEEBRgRAIAJB/ABqKAIAIQcgAkH4AGooAgAhCiACQfQAaigCACEGIAJB8ABqKAIAIQAgAkHsAGooAgAhASACQegAaigCACEDIAIoAmQhFAwJCyACQdgAaiACQeAAakEEciIFQSBqKAIAIgA2AgAgAkHQAGogBUEYaikCACIlNwMAIAJByABqIAVBEGopAgAiJjcDACACQUBrIAVBCGopAgAiJzcDACACIAUpAgAiJDcDOCABIAA2AgAgAkGkAWogJTcCACAHICY3AgAgAkGUAWogJzcCACACICQ3AowBIAJBADYCiAEgAkHgAGogAkGIAWoQCCACQYgBakEEciEAIAItAGBBAUYEQCACLQBhIAAQH0EIdEEFciEUQaGEwAAhA0EOIQEMCQsgAkHsAGooAgAhASACKQJkISQgABAfIAIgATYCkAEgAiAkNwOIASACQYgBahBtIQAgDARAIA4QFQsgC0UNCyANEBUMCwtBAiEECyAFRSAPRSADQQ9HcnJFBEAgARAVCwJAAkACQAJ/AkACQCAEQQFNBEAgBEEBaw0BDAILIAJBiAFqIAkQSiACKAKIASIDQRFGDQMgAigCkAEhBSACKAKMASEBIAIgAigClAEiBjYCbCACIAU2AmggAiABNgJkIAIgAzYCYAwJCyAIRQRAIAJBiAFqIAkQSiACKAKIASIDQRFHBEAgAigClAEhBiACKAKQASEFIAIoAowBIQEMCgsgAkGIAWogCRAvIAIoApQBISAgAigCkAEhASACKAKMASEIIAIoAogBQQFHDQQgAkGYAWooAgAhBiAIIQMgICEFQQAhCAwJCyACQYgBakGAhcAAQQgQXSACQZQBaigCACEGIAJBkAFqKAIADAELIAdFBEAgAkGIAWogCRBKIAIoAogBIgNBEUcEQCACKAKUASEGIAIoApABIQUgAigCjAEhAQwKCyACQYgBaiAJEC8gAigClAEhHyACKAKQASERIAIoAowBIQcgAigCiAFBAUcNBCACQZgBaigCACEGIAchAyARIQEgHyEFDAkLIAJBiAFqQYiFwABBCxBdIAJBlAFqKAIAIQYgAkGQAWooAgALIQUgAigCjAEhASACKAKIASEDDAYLIAJB4ABqIAkQDyACKAJgIgNBEUYNASACKAJsIQYgAigCaCEFIAIoAmQhAQwFCyABIRALIAJBCGog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NgIAIAJBjAFqIAY2AgAgAkGIAWogADYCACACIAo2AoQBIAIgDDYCgAEgAkGAAWoQKSEACyACQeABaiQAIAAL5Q0CDn8BfiMAQaABayIDJAAgA0HoAGogAhA6IANB0ABqIgUgA0GEAWoiCCgCADYCACADIANB/ABqIgYpAgA3A0ggA0H4AGoiCSgCACEMIANB9ABqIg0oAgAhByADQfAAaiILKAIAIQQgAygCbCEKAkACQAJAIAMoAmgiDkEBRgRAIAAgCjYCBCAAQQE2AgAgAEEQaiAMNgIAIABBDGogBzYCACAAQQhqIAQ2AgAgAEEUaiADKQNINwIAIABBHGogBSgCADYCAAwBCyADQegAaiACQQxqIhAQOiADQeAAaiAIKAIANgIAIAMgBikCADcDWCAJKAIAIQ8gDSgCACEIIAsoAgAhBSADKAJsIQkCQAJAAkACQAJAAkACQCADKAJoIg1BAUYEQCAAIAk2AgQgAEEBNgIAIABBEGogDzYCACAAQQxqIAg2AgAgAEEIaiAFNgIAIABBFGogAykDWDcCACAAQRxqIANB4ABqKAIANgIAIAQEQCAKEBULIA5FDQggCkH/AXFBf2oiAEEGSw0IIABBAWsOBggIAggIAwELIANBNGogCDYCACADQTBqIAU2AgAgA0FAayABQShqKAIANgIAIAMgCTYCLCADIAc2AiggAyAENgIkIAMgCjYCICADIAEpAiA3AzggA0GIAWoQhAEgA0HoAGogA0GIAWoQQSADLQBoQQFHBEAgAyADKAJsNgKYASADIANB8ABqLQAAOgCcASADQZgBakGAhcAAQQggA0EgahAZQf8BcSIGQQJHDQYgA0GYAWpBiIXAAEELIANBLGoQGUH/AXEiBkECRw0GIANBmAFqQZOFwABBBiADQThqEBlB/wFxIgZBAkcNBiADKAKYASADLQCcARBFQf8BcSIGQQJHDQcgA0EQaiADQRxqKAIANgIAIAMgAykCFDcDCCADKAKMASADKAKIASILIAMoApABEFsEQCALEBULIAQEQCAKEBULIAUEQCAJEBULIANBPGooAgAEQCADKAI4EBULIA0NBAwFCyADLQBpIQYMBgsgB0UNBiAEEBUMBgsgDEUgBEEPR3INBSAHEBUMBQsgB0UNBCAEEBUMBAsgCUH/AXFBf2oiBkEGSw0AAkACQAJA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cQRAIAItACFB2wBHBEAgAEEKNgIADAQLIAEQdCACQRhqIAEQgwEgAigCGCEDIAIgAi0AHEEBcToAZCACIAM2AmAgAkHwAGohAwJ/AkADQCACQegAaiACQeAAahAsIAItAGhBAUYNASACLQBpDQALQREMAQsgAkHYAGogA0EIaigCADYCACACIAMpAgA3A1AgAigCbAshAyACQcgAaiIEIAJB2ABqKAIANgIAIAIgAikDUDcDQCADQRFGDQEgACADNgIAIAAgAikDQDcCBCAAQQxqIAQoAgA2AgAMAwsgAEEDNgIADAILIAJB6ABqIAEQNyACKAJoIgFBEUcEQCACQfQAaigCACEDIAJB8ABqKAIAIQQgACACKAJsNgIEIAAgATYCACAAQQxqIAM2AgAgAEEIaiAENgIADAILIABBETYCAAwBCyACQQhqIAEQaiACLQAIQQFxBEAgAi0ACSEDA0AgA0EsRiADQf0ARnJFQQAgA0HdAEcbRQRAIABBETYCAAwDCyABEHQgAiABEGogAi0AASEDIAItAABBAXENAAsLIABBAjYCAAsgAkGAAWokAAuaCAEIfyMAQUBqIgMkACADQSRqIAE2AgAgA0E0aiACQRRqKAIAIgQ2AgAgA0EDOgA4IANBLGogAigCECIFIARBA3RqNgIAIANCgICAgIAENwMIIAMgADYCICADQQA2AhggA0EANgIQIAMgBTYCMCADIAU2AigCQAJAAkACQCACKAIIIgZFBEAgAigCACEIIAIoAgQiCSAEIAQgCUsbIgZFDQFBASEEIAAgCCgCACAIKAIEIAEoAgwRCAANBCAIQQxqIQJBASEHA0AgBSgCACADQQhqIAVBBGooAgARBgAEQAwGCyAHIAZPDQIgAkF8aiEAIAIoAgAhASACQQhqIQIgBUEIaiEFIAdBAWohByADKAIgIAAoAgAgASADKAIkKAIMEQgARQ0ACwwECyACKAIAIQggAigCBCIJIAJBDGooAgAiAiACIAlLGyIKRQ0AQQEhBCAAIAgoAgAgCCgCBCABKAIMEQgADQMgCEEMaiECIAZBEGohBUEBIQcDQCADIAVBeGooAgA2AgwgAyAFQRBqLQAAOgA4IAMgBUF8aigCADYCCEEAIQFBACEEAkACQAJAAkAgBUEIaigCAEEBaw4DAQIDAAsgBUEMaigCACEAQQEhBAwCCyAFQQxqKAIAIgYgAygCNCIESQRAQQAhBCADKAIwIAZBA3RqIgYoAgRBNUcNAiAGKAIAKAIAIQBBASEEDAILQficwAAgBiAEEFIACyADKAIoIgYgAygCLEYNACADIAZBCGo2AiggBigCBEE1Rw0AIAYoAgAoAgAhAEEBIQQLIAMgADYCFCADIAQ2AhACQAJ/AkACQAJAAkACQCAFKAIAQQFrDgMBAAYECyADKAIoIgAgAygCLEcNAQwFCyAFQQRqKAIAIgAgAygCNCIETw0BIAMoAjAgAEEDdGoiACgCBEE1Rw0EIAAoAgAoAgAMAwsgAyAAQQhqNgIoIAAoAgRBNUcNAyAAKAIAKAIADAILQficwAAgACAEEFIACyAFQQRqKAIACyEEQQEhAQsgAyAENgIcIAMgATYCGAJAIAVBcGooAgBBAUcEQCADKAIoIgQgAygCLEYNBCADIARBCGo2AigMAQsgBUF0aigCACIAIAMoAjQiAU8NBCADKAIwIABBA3RqIQQLIAQoAgAgA0EIaiAEQQRqKAIAEQYABEBBASEEDAULIAcgCk8NASACQXxqIQAgAigCACEBIAJBCGohAiAFQSRqIQVBASEEIAdBAWohByADKAIgIAAoAgAgASADKAIkKAIMEQgARQ0ACwwDCyAJIAdLBEBBASEEIAMoAiAgCCAHQQN0aiIAKAIAIAAoAgQgAygCJCgCDBEIAA0DC0EAIQQMAgtB4JbAABBjAAtB6JzAACAAIAEQUgALIANBQGskACAEC68HAQp/IwBBgAFrIgEkACABQThqEEICfyABKAI4IgVFBEBBASEHQRIhBEEAIQVB0oTAAAwBCyAFQYB+cSEDIAFBQGsoAgAhBCABKAI8CyEJIAFB+ABqIgIgAUEYaigCADYCACABIAEpAhA3A3AgAyAFQf8BcXIhCAJAIAcEQCAAIAg2AgQgAEEBNgIAIABBDGogBDYCACAAQQhqIAk2AgAgAEEUaiABKQNwNwIAIABBHGogAigCADYCAAwBCyABQThqIAggBBAMIAFByABqIgQoAgAhCiABQcQAaiIFKAIAIQYgAUFAaygCACEDIAEoAjwhAgJAIAEoAjhBAUYEQCAAQoGAgIDAADcCACAAQRxqQQU2AgAgAEEYakHNhMAANgIAIABBFGogCjYCACAAQRBqIAY2AgAgAEEMaiADNgIAIABBCGogAjYCAAwBCyABQTBqIAFB3ABqKAIANgIAIAFBIGogAUHMAGoiBykCADcDACABIAo2AhwgASAGNgIYIAEgAzYCFCABIAI2AhAgASABQdQAaiICKQIANwMoIAFBOGogAUEQahA7IAFB+ABqIgMgAigCADYCACABIAcpAgA3A3AgBCgCACEHIAUoAgAhBiABQUBrKAIAIQQgASgCPCEFIAEoAjgiAkEBRgRAIAAgBTYCBCAAQQE2AgAgAEEQaiAHNgIAIABBDGogBjYCACAAQQhqIAQ2AgAgAEEUaiABKQNwNwIAIABBHGogAygCADYCACABKAIUBEAgASgCEBAVCyABKAIgBEAgASgCHBAVCyABKAIsRQ0BIAEoAigQFQwBCyABIAY2AmggASAENgJkIAEgBTYCYAJAIAJFDQAgBUH/AXFBf2oiAkEGSw0AAkACQAJAIAJBAWsOBgMDAQMDAgALIAZFDQIgBBAVDAILIAdFIARBD0dyDQEgBhAVDAELIAZFDQAgBBAVCyABQQhqIgMgAUHgAGoiAigCCDYCBCADIAIoAgA2AgACQCABKAIMIgNBf0oEQCABKAIIIQICQCADRQRAQQEhBAwBCyADQQEQggEiBEUNAgsgBCACIAMQbCECIABBDGogAzYCACAAQQhqIAM2AgAgACACNgIEIABBADYCACABKAJkBEAgASgCYBAVCyABKAIUBEAgASgCEBAVCyABKAIgBEAgASgCHBAVCyABKAIsBEAgASgCKBAVCyAJRQ0DIAgQFQwDCxCSAQALIANBARCPAQALIAlFDQAgCBAVCyABQYABaiQAC/AGAQp/IwBB0ABrIgIkACACQUBrIAEoAgAQSgJAIAIoAkAiBkERRwRAIAJBzABqKAIAIQEgAkHIAGooAgAhBSACKAJEIQMgACAGNgIEIABBEGogATYCACAAQQxqIAU2AgAgAEEIaiADNgIAQQEhAQwBCyACQThqIAEoAgAiChBNQQEhAQJAIAItADhBAXFFBEBBAyEDDAELIAItADlB2wBHBEBBCiEDDAELIAoQdCACQTBqIAoQgwEgAi0ANCACQShqIAIoAjAiBhBNIAItAChBAXFFDQAgAi0AKSEEQQFxIQtBASEIQQAhBQJAAkACQANAAkACQAJAAkAgBEH/AXEiA0EsRwRAIANB3QBGDQIgC0EAIQsNAUEFIQMMCAsgBhB0IAJBIGogBhBNIAItACBBAXFFBEBBAyEDDAgLIAItACEhBAsgBEH/AXFB3QBGBEBBDiEDDAcLIAJBGGogBhBNIAItABhBAXFFBEBBAyEDDAcLQQkhAwJAAkAgAi0AGSIEQVNqIgdBA0sNACAHQQFrDgMAAAEICyAEQU9qQf8BcUEJSQ0CQQohAwwHCyAGEHRBACEEDAILIAJBQGsgChA3IAIoAkAiA0ERRwRAIAJBzABqKAIAIQYgAkHIAGooAgAhBCACKAJEIQcgBUUNByAIEBUMBwsgACAINgIEIABBDGogCTYCACAAQQhqIAU2AgBBACEBDAcLIAYQdCACQRBqIAYQaiAEQVBqIQQgAi0AESIHQVBqQf8BcUEJSw0AIAItABBBAXFFDQADQCAGEHQgBEH/AXGtQgp+pyIEQQh2DQUgBEH/AXEgB0FQakH/AXFqIgRB/wFxIARHDQUgAkEIaiAGEGogAi0ACSIHQVBqQf8BcUEJSw0BIAItAAhBAXENAAsLIAUgCUYEQCAFQQFqIgMgBUkNAyAFQQF0IgcgAyAHIANLGyIDQQBIDQMCfyAFRQRAIANBARCCAQwBCyAIIAVBASADEHwLIghFDQIgAyEFCyAIIAlqIAQ6AAAgAiAGEE0gCUEBaiEJIAItAAEhBCACLQAAQQFxDQALQQAhAwwCCyADQQEQjwEACxCRAQALIAVFDQAgCBAVCyAAIAM2AgQgAEEQaiAGNgIAIABBDGogBDYCACAAQQhqIAc2AgALIAAgATYCACACQdAAaiQAC4YGAQZ/AkACQAJAAkACQAJAIAJFDQBBACABa0EAIAFBA3EbIQggAkF5akEAIAJBB0sbIQcDQAJAAkACQCABIANqLQAAIgVBGHRBGHUiBkF/TARAAkACQAJAIAVBgZnAAGotAABBfmoiBEECTQRAIARBAWsOAgIDAQsMCgsgA0EBaiIEIAJPBEAMCwsgASAEai0AAEHAAXFBgAFGDQMMCQsgA0EBaiIEIAJPBEAMCgsgASAEai0AACEEAkACQCAFQaB+aiIFQQ1LDQACQAJAIAVBAWsODQICAgICAgICAgICAgEACyAEQeABcUGgAUcNCgwCCyAEQRh0QRh1QX9KDQkgBEGgAUkNAQwJCyAGQR9qQf8BcUELTQRAIARBGHRBGHVBf0ogBEHAAU9yDQkMAQsgBkH+AXFB7gFHIARBvwFLciAEQRh0QRh1QX9Kcg0ICyADQQJqIgQgAk8EQAwKCyABIARqLQAAQcABcUGAAUYNAgwKCyADQQFqIgQgAk8EQAwJCyABIARqLQAAIQQCQAJAIAVBkH5qIgVBBEsNAAJAAkAgBUEBaw4EAgICAQALIARB8ABqQf8BcUEwTw0KDAILIARBGHRBGHVBf0oNCSAEQZABSQ0BDAkLIARBvwFLIAZBD2pB/wFxQQJLciAEQRh0QRh1QX9Kcg0ICyADQQJqIgQgAk8EQAwJCyABIARqLQAAQcABcUGAAUcNCSADQQNqIgQgAk8EQAwJCyABIARqLQAAQcABcUGAAUYNASAAQYEGOwEEDAoLIAggA2tBA3ENAQJAIAMgB08NAANAIAEgA2oiBEEEaigCACAEKAIAckGAgYKEeHENASADQQhqIgMgB0kNAAsLIAMgAk8NAgNAIAEgA2osAABBAEgNAyACIANBAWoiA0cNAAsMBAsgBEEBaiEDDAELIANBAWohAwsgAyACSQ0ACwsgAEECOgAEDwsgAEGBAjsBBCAAIAM2AgAPCyAAQYECOwEEDAILIABBADoABAwBCyAAQYEEOwEECyAAIAM2AgALuAYBDH8gACgCECEDAkACQAJAAkAgACgCCCINQQFHBEAgAw0BIAAoAhggASACIABBHGooAgAoAgwRCAAhAwwDCyADRQ0BCwJAIAJFBEBBACECDAELIAEgAmohByAAQRRqKAIAQQFqIQogASIDIQsDQCADQQFqIQUCQAJ/IAMsAAAiBEF/TARAAn8gBSAHRgRAQQAhCCAHDAELIAMtAAFBP3EhCCADQQJqIgULIQMgBEEfcSEJIAggCUEGdHIgBEH/AXEiDkHfAU0NARoCfyADIAdGBEBBACEMIAcMAQsgAy0AAEE/cSEMIANBAWoiBQshBCAMIAhBBnRyIQggCCAJQQx0ciAOQfABSQ0BGgJ/IAQgB0YEQCAFIQNBAAwBCyAEQQFqIQMgBC0AAEE/cQsgCUESdEGAgPAAcSAIQQZ0cnIiBEGAgMQARw0CDAQLIARB/wFxCyEEIAUhAwsgCkF/aiIKBEAgBiALayADaiEGIAMhCyADIAdHDQEMAgsLIARBgIDEAEYNAAJAIAZFIAIgBkZyRQRAQQAhAyAGIAJPDQEgASAGaiwAAEFASA0BCyABIQMLIAYgAiADGyECIAMgASADGyEBCyANDQAMAgtBACEFIAIEQCACIQQgASEDA0AgBSADLQAAQcABcUGAAUZqIQUgA0EBaiEDIARBf2oiBA0ACwsgAiAFayAAKAIMIgdPDQFBACEGQQAhBSACBEAgAiEEIAEhAwNAIAUgAy0AAEHAAXFBgAFGaiEFIANBAWohAyAEQX9qIgQNAAsLIAUgAmsgB2ohBAJAAkACQEEAIAAtADAiAyADQQNGG0EBaw4DAAEAAgsgBCEGQQAhBAwBCyAEQQF2IQYgBEEBakEBdiEECyAGQQFqIQMCQANAIANBf2oiA0UNASAAKAIYIAAoAgQgACgCHCgCEBEGAEUNAAtBAQ8LIAAoAgQhBUEBIQMgACgCGCABIAIgACgCHCgCDBEIAA0AIARBAWohAyAAKAIcIQEgACgCGCEAA0AgA0F/aiIDRQRAQQAPCyAAIAUgASgCEBEGAEUNAAtBAQ8LIAMPCyAAKAIYIAEgAiAAQRxqKAIAKAIMEQgAC6YHAQV/IABBeGoiASAAQXxqKAIAIgNBeHEiAGohAgJAAkACQAJAIANBAXENACADQQNxRQ0BIAEoAgAiAyAAaiEAIAEgA2siAUG4oMAAKAIARgRAIAIoAgRBA3FBA0cNAUGwoMAAIAA2AgAgAiACKAIEQX5xNgIEIAEgAEEBcjYCBCAAIAFqIAA2AgAPCyADQYACTwRAIAEQNQwBCyABKAIMIgQgASgCCCIFRwRAIAUgBDYCDCAEIAU2AggMAQtBoJ3AAEGgncAAKAIAQX4gA0EDdndxNgIACwJAIAIoAgQiA0ECcQRAIAIgA0F+cTYCBCABIABBAXI2AgQgACABaiAANgIADAELAkAgAkG8oMAAKAIARwRAQbigwAAoAgAgAkcNAUG4oMAAIAE2AgBBsKDAAEGwoMAAKAIAIABqIgA2AgAgASAAQQFyNgIEIAAgAWogADYCAA8LQbygwAAgATYCAEG0oMAAQbSgwAAoAgAgAGoiADYCACABIABBAXI2AgRBuKDAACgCACABRgRAQbCgwABBADYCAEG4oMAAQQA2AgALQdigwAAoAgAiAiAATw0CQbygwAAoAgAiAEUNAgJAQbSgwAAoAgAiA0EpSQ0AQcigwAAhAQNAIAEoAgAiBCAATQRAIAQgASgCBGogAEsNAgsgASgCCCIBDQALC0HgoMAAAn9B/x9B0KDAACgCACIARQ0AGkEAIQEDQCABQQFqIQEgACgCCCIADQALIAFB/x8gAUH/H0sbCzYCACADIAJNDQJB2KDAAEF/NgIADwsgA0F4cSIEIABqIQACQCAEQYACTwRAIAIQNQwBCyACKAIMIgQgAigCCCICRwRAIAIgBDYCDCAEIAI2AggMAQtBoJ3AAEGgncAAKAIAQX4gA0EDdndxNgIACyABIABBAXI2AgQgACABaiAANgIAIAFBuKDAACgCAEcNAEGwoMAAIAA2AgAMAQsgAEGAAkkNASABIAAQMEHgoMAAQeCgwAAoAgBBf2oiADYCACAADQBB0KDAACgCACIADQJB4KDAAEH/HzYCAA8LDwsgAEEDdiICQQN0QaidwABqIQACf0GgncAAKAIAIgNBASACQR9xdCICcQRAIAAoAggMAQtBoJ3AACACIANyNgIAIAALIQIgACABNgIIIAIgATYCDCABIAA2AgwgASACNgIIDwtBACEBA0AgAUEBaiEBIAAoAggiAA0AC0HgoMAAIAFB/x8gAUH/H0sbNgIAC4QGAQR/AkACQAJAAkACQCAALQAERQRAAkAgACgCACIFKAIIIgQgBUEEaigCAEcEQCAFKAIAIQYMAQsgBEEBaiIGIARJDQYgBEEBdCIHIAYgByAGSxsiB0EASA0GAn8gBEUEQCAHQQEQggEMAQsgBSgCACAEQQEgBxB8CyIGRQ0CIAUgBjYCACAFQQRqIAc2AgAgBSgCCCEECyAEIAZqQSw6AAAgBSAFKAIIQQFqNgIICyAAQQA6AAQCQCAAKAIAIgUoAggiBCAFQQRqKAIARwRAIAUoAgAhBgwBCyAEQQFqIgYgBEkNBSAEQQF0IgcgBiAHIAZLGyIHQQBIDQUCfyAERQRAIAdBARCCAQwBCyAFKAIAIARBASAHEHwLIgZFDQIgBSAGNgIAIAVBBGogBzYCACAFKAIIIQQLIAQgBmpBIjoAACAFIAUoAghBAWo2AggCQCAAKAIAIgVBBGooAgAiBiAFQQhqKAIAIgRrIAJPBEAgBSgCACEGDAELIAIgBGoiByAESQ0FIAZBAXQiBCAHIAQgB0sbIgRBAEgNBQJ/IAZFBEAgBEEBEIIBDAELIAUoAgAgBkEBIAQQfAsiBkUNAyAFIAY2AgAgBUEEaiAENgIAIAVBCGooAgAhBAsgBUEIaiACIARqNgIAIAQgBmogASACEGwaAkAgACgCACIBQQRqKAIAIgIgAUEIaigCACIEa0ECTwRAIAEoAgAhAgwBCyAEQQJqIgYgBEkNBSACQQF0IgQgBiAEIAZLGyIEQQBIDQUCfyACRQRAIARBARCCAQwBCyABKAIAIAJBASAEEHwLIgJFDQQgASACNgIAIAFBBGogBDYCACABQQhqKAIAIQQLIAFBCGogBEECajYCACACIARqQaL0ADsAACAAKAIAIQBBAgJ/IAMoAgAiAUUEQCAAEENB/wFxDAELIAAgASADQQhqKAIAECJB/wFxCyIAQQFxIABBAkYbDwsgB0EBEI8BAAsgB0EBEI8BAAsgBEEBEI8BAAsgBEEBEI8BAAsQkQEAC7YGAQF/IwBBMGsiAiQAAn8CQAJAAkACQAJAAkACQAJAAkACQCAALQAAQQFrDgkBAgMEBQYHCAkACyACIABBBGo2AgQgAkEcakEBNgIAIAJCATcCDCACQYSJwAA2AgggAkEPNgIkIAIgAkEgajYCGCACIAJBBGo2AiAgASACQQhqEFUMCQsgAiAAQQRqNgIEIAJBHGpBATYCACACQgE3AgwgAkGEicAANgIIIAJBDjYCJCACIAJBIGo2AhggAiACQQRqNgIgIAEgAkEIahBVDAgLIAIgAEEEajYCBCACQRxqQQE2AgAgAkICNwIMIAJB5IjAADYCCCACQQ82AiQgAiACQSBqNgIYIAIgAkEEajYCICABIAJBCGoQVQwHCyACQgQ3AxggAkIBNwIMIAJB0IjAADYCCCABIAJBCGoQVQwGCyACIABBFGo2AgAgAiAAQQRqNgIEIAJBHGpBAjYCACACQSxqQRA2AgAgAkICNwIMIAJBnIjAADYCCCACQQ82AiQgAiACQSBqNgIYIAIgAkEEajYCKCACIAI2AiAgASACQQhqEFUMBQsgAiAAQQRqNgIAIAIgAEEBajYCBCACQRxqQQI2AgAgAkEsakERNgIAIAJCAjcCDCACQfyHwAA2AgggAkEPNgIkIAIgAkEgajYCGCACIAJBBGo2AiggAiACNgIgIAEgAkEIahBVDAQLIAIgAEEEajYCBCACQRxqQQE2AgAgAkIBNwIMIAJB4IfAADYCCCACQRI2AiQgAiACQSBqNgIYIAIgAkEEajYCICABIAJBCGoQVQwDCyACIABBBGo2AgQgAkEcakEBNgIAIAJCATcCDCACQeCHwAA2AgggAkETNgIkIAIgAkEgajYCGCACIAJBBGo2AiAgASACQQhqEFUMAgsgAkIENwMYIAJCATcCDCACQcCHwAA2AgggASACQQhqEFUMAQsgAiAAQQRqNgIAIAIgAEEMajYCBCACQRxqQQI2AgAgAkEsakEPNgIAIAJCAjcCDCACQaSHwAA2AgggAkEPNgIkIAIgAkEgajYCGCACIAJBBGo2AiggAiACNgIgIAEgAkEIahBVCyACQTBqJAAL6AUBBH8CQAJAAkACQAJAIAAtAARFBEACQCAAKAIAIgUoAggiBCAFQQRqKAIARwRAIAUoAgAhBgwBCyAEQQFqIgYgBEkNBiAEQQF0IgcgBiAHIAZLGyIHQQBIDQYCfyAERQRAIAdBARCCAQwBCyAFKAIAIARBASAHEHwLIgZFDQIgBSAGNgIAIAVBBGogBzYCACAFKAIIIQQLIAQgBmpBLDoAACAFIAUoAghBAWo2AggLIABBADoABAJAIAAoAgAiBSgCCCIEIAVBBGooAgBHBEAgBSgCACEGDAELIARBAWoiBiAESQ0FIARBAXQiByAGIAcgBksbIgdBAEgNBQJ/IARFBEAgB0EBEIIBDAELIAUoAgAgBEEBIAcQfAsiBkUNAiAFIAY2AgAgBUEEaiAHNgIAIAUoAgghBAsgBCAGakEiOgAAIAUgBSgCCEEBajYCCAJAIAAoAgAiBUEEaigCACIGIAVBCGooAgAiBGsgAk8EQCAFKAIAIQYMAQsgAiAEaiIHIARJDQUgBkEBdCIEIAcgBCAHSxsiBEEASA0FAn8gBkUEQCAEQQEQggEMAQsgBSgCACAGQQEgBBB8CyIGRQ0DIAUgBjYCACAFQQRqIAQ2AgAgBUEIaigCACEECyAFQQhqIAIgBGo2AgAgBCAGaiABIAIQbBoCQCAAKAIAIgFBBGooAgAiAiABQQhqKAIAIgRrQQJPBEAgASgCACECDAELIARBAmoiBiAESQ0FIAJBAXQiBCAGIAQgBksbIgRBAEgNBQJ/IAJFBEAgBEEBEIIBDAELIAEoAgAgAkEBIAQQfAsiAkUNBCABIAI2AgAgAUEEaiAENgIAIAFBCGooAgAhBAsgAUEIaiAEQQJqNgIAIAIgBGpBovQAOwAAQQIgACgCACADKAIAIAMoAggQIkH/AXEiAEEBcSAAQQJGGw8LIAdBARCPAQALIAdBARCPAQALIARBARCPAQALIARBARCPAQALEJEBAAvgBQEEfwJAAkACQAJAAkAgAC0ABEUEQAJAIAAoAgAiBSgCCCIEIAVBBGooAgBHBEAgBSgCACEGDAELIARBAWoiBiAESQ0GIARBAXQiByAGIAcgBksbIgdBAEgNBgJ/IARFBEAgB0EBEIIBDAELIAUoAgAgBEEBIAcQfAsiBkUNAiAFIAY2AgAgBUEEaiAHNgIAIAUoAgghBAsgBCAGakEsOgAAIAUgBSgCCEEBajYCCAsgAEEAOgAEAkAgACgCACIFKAIIIgQgBUEEaigCAEcEQCAFKAIAIQYMAQsgBEEBaiIGIARJDQUgBEEBdCIHIAYgByAGSxsiB0EASA0FAn8gBEUEQCAHQQEQggEMAQsgBSgCACAEQQEgBxB8CyIGRQ0CIAUgBjYCACAFQQRqIAc2AgAgBSgCCCEECyAEIAZqQSI6AAAgBSAFKAIIQQFqNgIIAkAgACgCACIFQQRqKAIAIgYgBUEIaigCACIEayACTwRAIAUoAgAhBgwBCyACIARqIgcgBEkNBSAGQQF0IgQgByAEIAdLGyIEQQBIDQUCfyAGRQRAIARBARCCAQwBCyAFKAIAIAZBASAEEHwLIgZFDQMgBSAGNgIAIAVBBGogBDYCACAFQQhqKAIAIQQLIAVBCGogAiAEajYCACAEIAZqIAEgAhBsGgJAIAAoAgAiAUEEaigCACICIAFBCGooAgAiBGtBAk8EQCABKAIAIQIMAQsgBEECaiIGIARJDQUgAkEBdCIEIAYgBCAGSxsiBEEASA0FAn8gAkUEQCAEQQEQggEMAQsgASgCACACQQEgBBB8CyICRQ0EIAEgAjYCACABQQRqIAQ2AgAgAUEIaigCACEECyABQQhqIARBAmo2AgAgAiAEakGi9AA7AABBAiADIAAoAgAQK0H/AXEiAEEBcSAAQQJGGw8LIAdBARCPAQALIAdBARCPAQALIARBARCPAQALIARBARCPAQALEJEBAAvTBQEIfwJAIAFBzP97Sw0AQRAgAUELakF4cSABQQtJGyECIABBfGoiBigCACIHQXhxIQMCQAJAAkACQAJAAkAgB0EDcQRAIABBeGoiCCADaiEFIAMgAk8NAUG8oMAAKAIAIAVGDQJBuKDAACgCACAFRg0DIAUoAgQiB0ECcQ0GIAdBeHEiCSADaiIDIAJPDQQMBgsgAkGAAkkgAyACQQRySXIgAyACa0GBgAhPcg0FDAQLIAMgAmsiAUEQSQ0DIAYgAiAHQQFxckECcjYCACACIAhqIgQgAUEDcjYCBCAFIAUoAgRBAXI2AgQgBCABEB0MAwtBtKDAACgCACADaiIDIAJNDQMgBiACIAdBAXFyQQJyNgIAIAIgCGoiASADIAJrIgRBAXI2AgRBtKDAACAENgIAQbygwAAgATYCAAwCC0GwoMAAKAIAIANqIgMgAkkNAgJAIAMgAmsiAUEPTQRAIAYgB0EBcSADckECcjYCACADIAhqIgEgASgCBEEBcjYCBEEAIQEMAQsgBiACIAdBAXFyQQJyNgIAIAIgCGoiBCABQQFyNgIEIAMgCGoiAiABNgIAIAIgAigCBEF+cTYCBAtBuKDAACAENgIAQbCgwAAgATYCAAwBCyADIAJrIQECQCAJQYACTwRAIAUQNQwBCyAFKAIMIgQgBSgCCCIFRwRAIAUgBDYCDCAEIAU2AggMAQtBoJ3AAEGgncAAKAIAQX4gB0EDdndxNgIACyABQRBPBEAgBiACIAYoAgBBAXFyQQJyNgIAIAIgCGoiBCABQQNyNgIEIAMgCGoiAiACKAIEQQFyNgIEIAQgARAdDAELIAYgAyAGKAIAQQFxckECcjYCACADIAhqIgEgASgCBEEBcjYCBAsgACEEDAELIAEQBSICRQ0AIAIgACABIAYoAgAiBEF4cUEEQQggBEEDcRtrIgQgBCABSxsQbCAAEBUPCyAEC8YEAQV/QStBgIDEACAAKAIAIgRBAXEiAxshBiACIANqIQVBy5XAAEEAIARBBHEbIQcCQAJAIAAoAghBAUcEQCAAIAYgBxBlDQEMAgsgAEEMaigCACIDIAVNBEAgACAGIAcQZQ0BDAILAkAgBEEIcUUEQCADIAVrIQNBACEEAkACQAJAQQEgAC0AMCIFIAVBA0YbQQFrDgMAAQACCyADIQRBACEDDAELIANBAXYhBCADQQFqQQF2IQMLIARBAWohBANAIARBf2oiBEUNAiAAKAIYIAAoAgQgACgCHCgCEBEGAEUNAAtBAQ8LIABBAToAMCAAQTA2AgQgACAGIAcQZQ0BIAMgBWshA0EAIQQCQAJAAkBBASAALQAwIgUgBUEDRhtBAWsOAwABAAILIAMhBEEAIQMMAQsgA0EBdiEEIANBAWpBAXYhAwsgBEEBaiEEAkADQCAEQX9qIgRFDQEgACgCGCAAKAIEIAAoAhwoAhARBgBFDQALQQEPCyAAKAIEIQQgACgCGCABIAIgACgCHCgCDBEIAA0BIANBAWohAyAAKAIcIQEgACgCGCEAA0AgA0F/aiIDRQRAQQAPCyAAIAQgASgCEBEGAEUNAAsMAQsgACgCBCEEIAAgBiAHEGUNACAAKAIYIAEgAiAAKAIcKAIMEQgADQAgA0EBaiEDIAAoAhwhASAAKAIYIQADQCADQX9qIgNFBEBBAA8LIAAgBCABKAIQEQYARQ0ACwtBAQ8LIAAoAhggASACIABBHGooAgAoAgwRCAALgAUBBH8jAEEQayICJAAgAUEEaiEFIAIQhAECQAJAAkACQAJAIAEoAgBBAUcEQAJAIAIoAggiASACKAIERwRAIAIoAgAhBAwBCyABQQFqIgMgAUkNAyABQQF0IgQgAyAEIANLGyIDQQBIDQMCfyABRQRAIANBARCCAQwBCyACKAIAIAFBASADEHwLIgRFDQYgAiADNgIEIAIgBDYCAAsgASAEakH7ADoAACACIAIoAghBAWo2AgggAkGfhMAAQQIQIkH/AXEiAUECRwRAIAFBAXEhAQwCCwJAIAIoAggiASACKAIERwRAIAIoAgAhBAwBCyABQQFqIgMgAUkNAyABQQF0IgQgAyAEIANLGyIDQQBIDQMCfyABRQRAIANBARCCAQwBCyACKAIAIAFBASADEHwLIgRFDQYgAiADNgIEIAIgBDYCACACKAIIIQELIAEgBGpBOjoAACACIAIoAghBAWo2AgggBSACECtB/wFxIgFBAkcEQCABQQFxIQEMAgsCQCACKAIIIgEgAigCBEcEQCACKAIAIQQMAQsgAUEBaiIDIAFJDQMgAUEBdCIEIAMgBCADSxsiA0EASA0DAn8gAUUEQCADQQEQggEMAQsgAigCACABQQEgAxB8CyIERQ0GIAIgAzYCBCACIAQ2AgAgAigCCCEBCyABIARqQf0AOgAAIAIgAigCCEEBajYCCAwDCyACIAUQISIBQf8BcUECRg0CCyAAQQE6AAAgACABQQFxOgABIAIoAgRFDQIgAigCABAVDAILEJEBAAsgAEEAOgAAIABBBGogAikDADcCACAAQQxqIAJBCGooAgA2AgALIAJBEGokAA8LIANBARCPAQALhwUBBH8gACABaiECAkACQAJAIAAoAgQiA0EBcQ0AIANBA3FFDQEgACgCACIDIAFqIQEgACADayIAQbigwAAoAgBGBEAgAigCBEEDcUEDRw0BQbCgwAAgATYCACACIAIoAgRBfnE2AgQgACABQQFyNgIEIAIgATYCAA8LIANBgAJPBEAgABA1DAELIAAoAgwiBCAAKAIIIgVHBEAgBSAENgIMIAQgBTYCCAwBC0GgncAAQaCdwAAoAgBBfiADQQN2d3E2AgALIAIoAgQiA0ECcQRAIAIgA0F+cTYCBCAAIAFBAXI2AgQgACABaiABNgIADAILAkAgAkG8oMAAKAIARwRAQbigwAAoAgAgAkcNAUG4oMAAIAA2AgBBsKDAAEGwoMAAKAIAIAFqIgE2AgAgACABQQFyNgIEIAAgAWogATYCAA8LQbygwAAgADYCAEG0oMAAQbSgwAAoAgAgAWoiATYCACAAIAFBAXI2AgQgAEG4oMAAKAIARw0BQbCgwABBADYCAEG4oMAAQQA2AgAPCyADQXhxIgQgAWohAQJAIARBgAJPBEAgAhA1DAELIAIoAgwiBCACKAIIIgJHBEAgAiAENgIMIAQgAjYCCAwBC0GgncAAQaCdwAAoAgBBfiADQQN2d3E2AgALIAAgAUEBcjYCBCAAIAFqIAE2AgAgAEG4oMAAKAIARw0BQbCgwAAgATYCAAsPCyABQYACTwRAIAAgARAwDwsgAUEDdiICQQN0QaidwABqIQECf0GgncAAKAIAIgNBASACQR9xdCICcQRAIAEoAggMAQtBoJ3AACACIANyNgIAIAELIQIgASAANgIIIAIgADYCDCAAIAE2AgwgACACNgIIC78EAQR/IwBBEGsiBCQAIAAoAgAhAAJAAkACQAJAAkACQCABQYABTwRAIARBADYCDCABQYAQSQ0BIAFBgIAESQRAIAQgAUE/cUGAAXI6AA4gBCABQQZ2QT9xQYABcjoADSAEIAFBDHZBD3FB4AFyOgAMQQMhAQwECyAEIAFBP3FBgAFyOgAPIAQgAUESdkHwAXI6AAwgBCABQQZ2QT9xQYABcjoADiAEIAFBDHZBP3FBgAFyOgANQQQhAQwDCwJAIAAoAggiAiAAQQRqKAIARwRAIAAoAgAhAwwBCyACQQFqIgMgAkkNBiACQQF0IgUgAyAFIANLGyIFQQBIDQYCfyACRQRAIAVBARCCAQwBCyAAKAIAIAJBASAFEHwLIgNFDQIgACADNgIAIABBBGogBTYCACAAKAIIIQILIAIgA2ogAToAACAAIAAoAghBAWo2AggMAwsgBCABQT9xQYABcjoADSAEIAFBBnZBH3FBwAFyOgAMQQIhAQwBCyAFQQEQjwEACwJAIABBBGooAgAiAyAAQQhqKAIAIgJrIAFPBEAgACgCACEDDAELIAEgAmoiBSACSQ0DIANBAXQiAiAFIAIgBUsbIgJBAEgNAwJ/IANFBEAgAkEBEIIBDAELIAAoAgAgA0EBIAIQfAsiA0UNAiAAIAM2AgAgAEEEaiACNgIAIABBCGooAgAhAgsgAEEIaiABIAJqNgIAIAIgA2ogBEEMaiABEGwaCyAEQRBqJABBAA8LIAJBARCPAQALEJEBAAvKAwEFfyAAKAIIIgEEQCAAKAIAIgQgAUEobGohBQNAIAQiAUEoaiEEAkAgASgCACIDQQFNBEAgA0EBawRAIAFBCGooAgAEQCABKAIEEBULIAFBFGooAgAEQCABQRBqKAIAEBULIAFBJGooAgAiAwRAIAFBHGooAgAhAiADQRhsIQMDQCACQQRqKAIABEAgAigCABAVCyACQRBqKAIABEAgAkEMaigCABAVCyACQRhqIQIgA0FoaiIDDQALCyABQSBqKAIARQ0CIAEoAhwQFQwCCyABQQhqKAIABEAgASgCBBAVCyABQRRqKAIABEAgAUEQaigCABAVCyABQSRqKAIAIgMEQCABQRxqKAIAIQIgA0EYbCEDA0AgAkEEaigCAARAIAIoAgAQFQsgAkEQaigCAARAIAJBDGooAgAQFQsgAkEYaiECIANBaGoiAw0ACwsgAUEgaigCAEUNASABKAIcEBUMAQsgAUEIaigCAEUNACABKAIEEBULIAQgBUcNAAsLIABBBGooAgAEQCAAKAIAEBULAkAgACgCDCIERQ0AIABBEGooAgBFDQAgBBAVCwJAIAAoAhgiBEUNACAAQRxqKAIARQ0AIAQQFQsLlAQCBH8DfiMAQUBqIgIkACACQTBqIAEoAgAQSgJAIAIoAjAiA0ERRwRAIAJBPGooAgAhASACQThqKAIAIQQgAigCNCEFIAAgAzYCBCAAQRBqIAE2AgAgAEEMaiAENgIAIABBCGogBTYCAEEBIQEMAQsgAkEoaiABKAIAIgMQTUEBIQECQAJAIAItAChBAXEEQEIBIQcgAi0AKUEtRgRAIAMQdEJ/IQcLIAJBIGogAxBqIAItACBBAXFFDQECQCACLQAhIgFBMEcEQCABQU9qQf8BcUEJSQRAIAMQdCACQRhqIAMQaiAHIAFBUGqtQv8Bg34hBiACLQAZIgFBUGpB/wFxQQlLDQUgAi0AGEEBcUUNBQwCCyAAQQo2AgRBASEBDAULIAMQdCAAQQhqQgA3AwBBACEBDAQLA0ACQCACQQhqIAYgBkI/hxBMIAMQdCACKQMQIAIpAwgiBkI/h1INACAGQn9VIgQgByABQVBqrUL/AYN+IghCf1VGIAQgBiAIfCIGQn9VR3FBAUYEQCAAQgk3AgQgAEEMakIANwIAQQEhAQwGCyACIAMQaiACLQABIgFBUGpB/wFxQQlLDQQgAi0AAEEBcQ0BDAQLCyAAQgk3AgQgAEEMakIANwIAQQEhAQwDCyAAQQM2AgQMAgsgAEEDNgIEDAELIABBCGogBjcDAEEAIQELIAAgATYCACACQUBrJAALqgQBA38CQAJAAkACQAJAIAAoAggiAiAAQQRqKAIARwRAIAAoAgAhAwwBCyACQQFqIgMgAkkNBCACQQF0IgQgAyAEIANLGyIEQQBIDQQCfyACRQRAIARBARCCAQwBCyAAKAIAIAJBASAEEHwLIgNFDQEgACADNgIAIABBBGogBDYCACAAKAIIIQILIAIgA2pB+wA6AAAgACAAKAIIQQFqNgIIIABBnITAAEEDECJB/wFxIgJBAkcEQCACQQFxDwsCQCAAKAIIIgIgAEEEaigCAEcEQCAAKAIAIQMMAQsgAkEBaiIDIAJJDQQgAkEBdCIEIAMgBCADSxsiBEEASA0EAn8gAkUEQCAEQQEQggEMAQsgACgCACACQQEgBBB8CyIDRQ0CIAAgAzYCACAAQQRqIAQ2AgAgACgCCCECCyACIANqQTo6AAAgACAAKAIIQQFqNgIIIAAgASgCACABKAIIECJB/wFxIgFBAkcEQCABQQFxDwsCQCAAKAIIIgIgAEEEaigCAEcEQCAAKAIAIQMMAQsgAkEBaiIBIAJJDQQgAkEBdCIDIAEgAyABSxsiAUEASA0EAn8gAkUEQCABQQEQggEMAQsgACgCACACQQEgARB8CyIDRQ0DIAAgAzYCACAAQQRqIAE2AgAgACgCCCECCyACIANqQf0AOgAAIAAgACgCCEEBajYCCEECDwsgBEEBEI8BAAsgBEEBEI8BAAsgAUEBEI8BAAsQkQEAC4cEAQN/AkACQAJAAkACQCAAQQhqKAIAIgMgAEEEaigCAEcEQCAAKAIAIQQMAQsgA0EBaiIEIANJDQQgA0EBdCIFIAQgBSAESxsiBUEASA0EAn8gA0UEQCAFQQEQggEMAQsgACgCACADQQEgBRB8CyIERQ0BIAAgBDYCACAAQQRqIAU2AgAgAEEIaigCACEDCyADIARqQSI6AAAgAEEIaiIDIAMoAgBBAWoiAzYCAAJAIABBBGooAgAiBCADayACTwRAIAAoAgAhBAwBCyACIANqIgUgA0kNBCAEQQF0IgMgBSADIAVLGyIDQQBIDQQCfyAERQRAIANBARCCAQwBCyAAKAIAIARBASADEHwLIgRFDQIgACAENgIAIABBBGogAzYCACAAQQhqKAIAIQMLIABBCGoiBSACIANqNgIAIAMgBGogASACEGwaAkAgBSgCACIDIABBBGooAgBHBEAgACgCACECDAELIANBAWoiASADSQ0EIANBAXQiAiABIAIgAUsbIgFBAEgNBAJ/IANFBEAgAUEBEIIBDAELIAAoAgAgA0EBIAEQfAsiAkUNAyAAIAI2AgAgAEEEaiABNgIAIABBCGooAgAhAwsgAiADakEiOgAAIABBCGoiACAAKAIAQQFqNgIAQQIPCyAFQQEQjwEACyADQQEQjwEACyABQQEQjwEACxCRAQAL9gMBA38CQAJAAkAgASgCCCIEIAFBBGooAgBHBEAgASgCACEGDAELIARBAWoiBSAESQ0BIARBAXQiBiAFIAYgBUsbIgVBAEgNAQJ/IARFBEAgBUEBEIIBDAELIAEoAgAgBEEBIAUQfAsiBkUNAiABIAY2AgAgAUEEaiAFNgIAIAEoAgghBAsgBCAGakH7ADoAACABIAEoAghBAWo2AgggASACIAMQIhoCQCABKAIIIgQgAUEEaigCAEcEQCABKAIAIQYMAQsgBEEBaiICIARJDQEgBEEBdCIDIAIgAyACSxsiBUEASA0BAn8gBEUEQCAFQQEQggEMAQsgASgCACAEQQEgBRB8CyIGRQ0CIAEgBjYCACABQQRqIAU2AgAgASgCCCEECyAEIAZqQTo6AAAgASABKAIIQQFqIgQ2AggCQCABQQRqKAIAIARHBEAgASgCACEGDAELIARBAWoiAiAESQ0BIARBAXQiAyACIAMgAksbIgVBAEgNAQJ/IARFBEAgBUEBEIIBDAELIAEoAgAgBEEBIAUQfAsiBkUNAiABIAY2AgAgAUEEaiAFNgIAIAEoAgghBAsgBCAGakH7ADoAACAAQQA6AAAgAEEIakEBOgAAIABBBGogATYCACABIAEoAghBAWo2AggPCxCRAQALIAVBARCPAQALwgMBBX8jAEEwayICJAAgAkEQaiABKAIAEE0CQAJAIAItABBBAXFFBEBBASEDDAELAn8CQAJAAkAgAi0AESIEIgNB/QBHBEACQCADQSxGBEAgAS0ABEUNAQwDCyABLQAEDQJBBgwFCyABKAIAEHQgAkEIaiABKAIAEE0gAi0ACEEBcUUNAyACLQAJIQQMAgsgAEEAOwEADAULIAFBADoABAsCQCAEQf8BcSIDQf0ARwRAQQwgA0EiRw0DGiACIAEoAgAiAxBNIAItAABBAXFFDQJBCiACLQABQSJHDQMaIAMQdCACQRhqIAMQPiACQSRqKAIAIQQgAkEgaigCACEFIAIoAhwhAyACKAIYIgZBAUcEQCAERSAGRSADQQ9HcnINAiAFEBUMAgsgA0ERRg0BIAJBKGooAgAhAQwEC0EODAILIAJBGGogARBQIAIoAhhBEUcEQCAAQQE6AAAgAEEEaiACKQMYNwIAIABBDGogAkEgaikDADcCAAwECyAAQYACOwEADAMLQQMLIQMLIABBAToAACAAQRBqIAE2AgAgAEEMaiAENgIAIABBCGogBTYCACAAQQRqIAM2AgALIAJBMGokAAviAgEFfwJAQc3/eyAAQRAgAEEQSxsiAGsgAU0NACAAQRAgAUELakF4cSABQQtJGyIEakEMahAFIgJFDQAgAkF4aiEBAkAgAEF/aiIDIAJxRQRAIAEhAAwBCyACQXxqIgUoAgAiBkF4cSACIANqQQAgAGtxQXhqIgIgACACaiACIAFrQRBLGyIAIAFrIgJrIQMgBkEDcQRAIAAgAyAAKAIEQQFxckECcjYCBCAAIANqIgMgAygCBEEBcjYCBCAFIAIgBSgCAEEBcXJBAnI2AgAgACAAKAIEQQFyNgIEIAEgAhAdDAELIAEoAgAhASAAIAM2AgQgACABIAJqNgIACwJAIAAoAgQiAUEDcUUNACABQXhxIgIgBEEQak0NACAAIAQgAUEBcXJBAnI2AgQgACAEaiIBIAIgBGsiBEEDcjYCBCAAIAJqIgIgAigCBEEBcjYCBCABIAQQHQsgAEEIaiEDCyADC5IDAQN/IwBBMGsiAiQAAn8gACgCBCIEQQJNBEACQAJAAkAgBEEBaw4CAQIACxBzAAsgAkEsakEBNgIAIAJCAjcCHCACQYSRwAA2AhggAkEbNgIEIAIgACgCADYCACACIAI2AiggASACQRhqEFUMAgsgAkEMakEbNgIAIAJBLGpBAjYCACACQgM3AhwgAkGckcAANgIYIAJBGzYCBCACIAAoAgAiADYCACACIABBCGo2AgggAiACNgIoIAEgAkEYahBVDAELIAJCBDcDKCACQgE3AhwgAkHwkMAANgIYQQEgASACQRhqEFUNABogBEEDdEF4akEDdkEBaiEEIAAoAgAhAAJAA0AgAiAANgIUIAMEQCACQgQ3AyggAkIBNwIcIAJB/JDAADYCGCABIAJBGGoQVQ0CCyACQQE2AiwgAkICNwIcIAJBhJHAADYCGCACQRw2AgQgAiACNgIoIAIgAkEUajYCACABIAJBGGoQVQ0BIABBCGohACAEIANBAWoiA0cNAAtBAAwBC0EBCyACQTBqJAAL+AIBBn8jAEEwayICJAAgASgCACEGAkAgASgCBCIHQQN0IgVFBEAMAQsgBkEEaiEEA0AgBCgCACADaiEDIARBCGohBCAFQXhqIgUNAAsLAkACQAJAAkACQCABQRRqKAIARQRAIAMhBAwBCyAHRQRAQbiUwABBAEEAEFIACwJAIANBD00EQCAGKAIERQ0BCyADIANqIgQgA08NAQtBASEFQQAhBCACQQhqIQMMAQsgBEF/TA0BIAJBCGohAyAERQRAQQEhBUEAIQQMAQsgBEEBEIIBIgVFDQILIAJBADYCECACIAQ2AgwgAiAFNgIIIAIgAkEIajYCFCACQShqIAFBEGopAgA3AwAgAkEgaiABQQhqKQIANwMAIAIgASkCADcDGCACQRRqQdCTwAAgAkEYahAQDQIgACADKQIANwIAIABBCGogA0EIaigCADYCACACQTBqJAAPCxCSAQALIARBARCPAQALQZiVwABBMyACQRhqQciUwAAQTwAL1gIBBX8jAEEQayIEJAAgBEEAOwEMIAQgAUH/AXEiAkEKcEEwcjoADkECIQMCQAJAAkACQCACQQpPBEBBAiECA0AgAUH/AXEiBUEKbiEBIAJBf2oiAyACSw0CIARBDGogA2ogAUEKcEEwcjoAACADIQIgBUHkAE8NAAsgA0EETw0CCwJAIABBBGooAgAiBiAAQQhqKAIAIgFrQQMgA2siBU8EQCAAKAIAIQIMAQsgASAFaiICIAFJDQQgBkEBdCIBIAIgASACSxsiAUEASA0EAn8gBkUEQCABQQEQggEMAQsgACgCACAGQQEgARB8CyICRQ0DIAAgAjYCACAAQQRqIAE2AgAgAEEIaigCACEBCyAAQQhqIAEgBWo2AgAgASACaiAEQQxqIANqIAUQbBogBEEQaiQAQQIPC0GEkMAAEGMACyADQQMQUwALIAFBARCPAQALEJEBAAu8AgEDfyMAQdAAayIBJAAgAUEYaiAAEDYgAUE0aiABQSBqKAIANgIAIAEgASkDGDcCLCABQQE2AiggAUEYaiABQShqEAggAS0AGEEBRwRAIAFBEGogAUEkaigCADYCACABIAEpAhw3AwggAUEwaigCAARAIAEoAiwQFQsgAUEwaiABQRBqKAIANgIAIAEgASkDCDcDKCABQShqEG0CQCAALQAAQX9qIgNBBksNAAJAAkACQCADQQFrDgYDAwEDAwIACyAAQQhqKAIARQ0CIABBBGooAgAQFQwCCyAAQQRqKAIAQQ9HDQEgAEEMaigCAEUNASAAQQhqKAIAEBUMAQsgAEEIaigCAEUNACAAQQRqKAIAEBULIAFB0ABqJAAPCyABIAEtABk6AAhBuIHAAEErIAFBCGpB5IHAABBPAAulAwECfyMAQTBrIgIkAAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCACIDQQ9NBEAgA0EBaw4PAgMEBQYHCAkKCwwNDg8QAQsgAkGUicAANgIoQQwMEAsgAkG3jcAANgIoQRkMDwsgAkGbjcAANgIoQRwMDgsgAkGAjcAANgIoQRsMDQsgAkHhjMAANgIoQR8MDAsgAkG7jMAANgIoQSYMCwsgAkGEjMAANgIoQTcMCgsgAkHMi8AANgIoQTgMCQsgAkGUi8AANgIoQTgMCAsgAkHmisAANgIoQS4MBwsgAkHXisAANgIoQQ8MBgsgAkHLisAANgIoQQwMBQsgAkGwisAANgIoQRsMBAsgAkGVisAANgIoQRsMAwsgAkHZicAANgIoQTwMAgsgAkGgicAANgIoQTkMAQsgAiAAKAIENgIoIABBDGooAgALIQAgAkEcakEBNgIAIAJBGjYCJCACIAA2AiwgAkIBNwIMIAJBjInAADYCCCACIAJBKGo2AiAgAiACQSBqNgIYIAEgAkEIahBVIAJBMGokAAvBAgEGfyMAQRBrIgMkACAAKAIAIQUgAyABIAAoAggiBhBAAn8CQAJAAkAgAy0AAEEBRwRAIANBCGotAAAhASADKAIEIgBBBGohBwNAIAZFDQQgAUH/AXFFBEACQCAAKAIIIgEgBygCAEcEQCAAKAIAIQIMAQsgAUEBaiICIAFJDQUgAUEBdCIEIAIgBCACSxsiBEEASA0FAn8gAUUEQCAEQQEQggEMAQsgACgCACABQQEgBBB8CyICRQ0EIAAgAjYCACAHIAQ2AgAgACgCCCEBCyABIAJqQSw6AAAgACAAKAIIQQFqNgIICyAGQX9qIQYgBS0AACECQQAhASAFQQFqIQUgACACEChB/wFxIgJBAkYNAAsgAkEBcQwECyADLQABDAMLIARBARCPAQALEJEBAAsgABBEQf8BcQsgA0EQaiQAC8oCAQN/IwBBIGsiAiQAIAJBCGogASgCABBNQQEhAwJAAkACQCACLQAIQQFxBEACQAJAIAItAAkiAyIEQSxHBEAgBEHdAEcNAUEAIQMgAEEAOgABDAYLIAEoAgAQdCACIAEoAgAQTUEBIQMgAi0AAEEBcUUNAyACLQABIQMMAQsgAS0ABEUEQCAAQQRqQQU2AgBBASEDDAULIAFBADoABAsgA0HdAEYNAiACQRBqIAEoAgAQDyACKAIQIgFBEUcEQCACQRhqKAIAIQMgAigCFCEEIABBEGogAkEcaigCADYCACAAQQxqIAM2AgAgAEEIaiAENgIAIABBBGogATYCAEEBIQMMBAsgAEEBOgABQQAhAwwDCyAAQQRqQQA2AgAMAgsgAEEEakEDNgIADAELIABBBGpBDjYCAEEBIQMLIAAgAzoAACACQSBqJAALywIBAn8CQAJAAkACQCAAKAIIIgEgAEEEaigCAEcEQCAAKAIAIQIMAQsgAUEBaiICIAFJDQMgAUEBdCIDIAIgAyACSxsiA0EASA0DAn8gAUUEQCADQQEQggEMAQsgACgCACABQQEgAxB8CyICRQ0BIAAgAjYCACAAQQRqIAM2AgAgACgCCCEBCyABIAJqQf0AOgAAIAAgACgCCEEBaiIBNgIIAkAgAEEEaigCACABRwRAIAAoAgAhAgwBCyABQQFqIgIgAUkNAyABQQF0IgMgAiADIAJLGyIDQQBIDQMCfyABRQRAIANBARCCAQwBCyAAKAIAIAFBASADEHwLIgJFDQIgACACNgIAIABBBGogAzYCACAAKAIIIQELIAEgAmpB/QA6AAAgACAAKAIIQQFqNgIIQQIPCyADQQEQjwEACyADQQEQjwEACxCRAQALtwICBX8BfiMAQTBrIgQkAEEnIQICQCAAQpDOAFQEQCAAIQcMAQsDQCAEQQlqIAJqIgNBfGogACAAQpDOAIAiB0KQzgB+faciBUH//wNxQeQAbiIGQQF0QYGbwABqLwAAOwAAIANBfmogBSAGQeQAbGtB//8DcUEBdEGBm8AAai8AADsAACACQXxqIQIgAEL/wdcvViAHIQANAAsLIAenIgNB4wBKBEAgAkF+aiICIARBCWpqIAenIgMgA0H//wNxQeQAbiIDQeQAbGtB//8DcUEBdEGBm8AAai8AADsAAAsCQCADQQpOBEAgAkF+aiICIARBCWpqIANBAXRBgZvAAGovAAA7AAAMAQsgAkF/aiICIARBCWpqIANBMGo6AAALIAEgBEEJaiACakEnIAJrEBsgBEEwaiQAC58CAQV/IwBBIGsiAiQAIAIgARBNQQEhAwJAAkACQCACLQAAQQFxBEAgAi0AAUEiRwRAIABBCjYCBAwCCyABEHQgAkEIaiABED4gAkEUaigCACEGIAJBEGooAgAhASACKAIMIQQgAigCCCIFQQFGBEAgAkEYaigCACEFIAAgBDYCBCAAQRBqIAU2AgAgAEEMaiAGNgIAIABBCGogATYCAAwCCyABQX9MDQIgAQRAIAFBARCCASIDRQ0ECyADIAQgARBsIQMgBkUgBUUgBEEPR3JyRQRAIAEQFQsgACADNgIEIABBDGogATYCACAAQQhqIAE2AgBBACEDDAELIABBAzYCBAsgACADNgIAIAJBIGokAA8LEJIBAAsgAUEBEI8BAAu9AgEEfyAAQgA3AhAgAAJ/QQAgAUEIdiICRQ0AGkEfIAFB////B0sNABogAUEGIAJnIgJrQR9xdkEBcSACQQF0a0E+agsiAzYCHCADQQJ0QbCfwABqIQUCQAJAAkACQEGkncAAKAIAIgRBASADQR9xdCICcQRAIAUoAgAiAigCBEF4cSABRw0BIAIhBAwCC0GkncAAIAIgBHI2AgAgBSAANgIAIAAgBTYCGAwDCyABQQBBGSADQQF2a0EfcSADQR9GG3QhAwNAIAIgA0EddkEEcWpBEGoiBSgCACIERQ0CIANBAXQhAyAEIgIoAgRBeHEgAUcNAAsLIAQoAggiASAANgIMIAQgADYCCCAAQQA2AhggACAENgIMIAAgATYCCA8LIAUgADYCACAAIAI2AhgLIAAgADYCDCAAIAA2AggLvAIBAn8jAEEQayICJAACQCAAKAIAIgACfwJAIAFBgAFPBEAgAkEANgIMIAFBgBBJDQEgAUGAgARJBEAgAiABQT9xQYABcjoADiACIAFBBnZBP3FBgAFyOgANIAIgAUEMdkEPcUHgAXI6AAxBAwwDCyACIAFBP3FBgAFyOgAPIAIgAUESdkHwAXI6AAwgAiABQQZ2QT9xQYABcjoADiACIAFBDHZBP3FBgAFyOgANQQQMAgsgACgCCCIDIAAoAgRGBH8gAEEBEEkgACgCCAUgAwsgACgCAGogAToAACAAIAAoAghBAWo2AggMAgsgAiABQT9xQYABcjoADSACIAFBBnZBH3FBwAFyOgAMQQILIgEQSSAAIAAoAggiAyABajYCCCADIAAoAgBqIAJBDGogARBsGgsgAkEQaiQAQQALtQIBAn8jAEEQayICJAACQCAAAn8CQCABQYABTwRAIAJBADYCDCABQYAQSQ0BIAFBgIAESQRAIAIgAUE/cUGAAXI6AA4gAiABQQZ2QT9xQYABcjoADSACIAFBDHZBD3FB4AFyOgAMQQMMAwsgAiABQT9xQYABcjoADyACIAFBEnZB8AFyOgAMIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADUEEDAILIAAoAggiAyAAKAIERgR/IABBARBJIAAoAggFIAMLIAAoAgBqIAE6AAAgACAAKAIIQQFqNgIIDAILIAIgAUE/cUGAAXI6AA0gAiABQQZ2QR9xQcABcjoADEECCyIBEEkgACAAKAIIIgMgAWo2AgggAyAAKAIAaiACQQxqIAEQbBoLIAJBEGokAAu8AgICfwF+IwBBQGoiAiQAIAIgATYCBCACQQA2AhAgAkIBNwMIIAJBAzYCHCACIAJBBGo2AhggAiACQQhqNgIkIAJBPGpBATYCACACQgE3AiwgAkHQgMAANgIoIAIgAkEYajYCOAJAAkAgAkEkakGQgcAAIAJBKGoQEEUEQCACKAIMIgMgAigCECIBRwRAIAMgAUkNAgJAIAFFBEAgAwRAIAIoAggQFQsgAkEBNgIIQQAhAQwBCyACKAIIIANBASABEHwiA0UNBCACIAM2AggLIAIgATYCDAsgAkEwaiACQRBqKAIAIgE2AgAgAiACKQMIIgQ3AyggAEEMaiABNgIAIAAgBDcCBCAAQQ82AgAgAkFAayQADwtB2IDAAEE3IAJBKGpBqIHAABBPAAtBsILAABBjAAsgAUEBEI8BAAuzAgEEfyMAQUBqIgIkACABKAIEIgNFBEAgAUEEaiEDIAEoAgAhBCACQQA2AiAgAkIBNwMYIAIgAkEYajYCJCACQThqIARBEGopAgA3AwAgAkEwaiAEQQhqKQIANwMAIAIgBCkCADcDKCACQSRqQaySwAAgAkEoahAQGiACQRBqIgQgAigCIDYCACACIAIpAxg3AwgCQCABKAIEIgVFDQAgAUEIaigCAEUNACAFEBULIAMgAikDCDcCACADQQhqIAQoAgA2AgAgAygCACEDCyABQQE2AgQgAUEMaigCACEEIAFBCGoiASgCACEFIAFCADcCAEEMQQQQggEiAUUEQEEMQQQQjwEACyABIAQ2AgggASAFNgIEIAEgAzYCACAAQcCTwAA2AgQgACABNgIAIAJBQGskAAuyAgEFfyAAKAIYIQQCQAJAIAAgACgCDCIBRgRAIABBFEEQIABBFGoiASgCACIDG2ooAgAiAg0BQQAhAQwCCyAAKAIIIgIgATYCDCABIAI2AggMAQsgASAAQRBqIAMbIQMDQCADIQUgAiIBQRRqIgMoAgAiAkUEQCABQRBqIQMgASgCECECCyACDQALIAVBADYCAAsCQCAERQ0AAkAgACAAKAIcQQJ0QbCfwABqIgIoAgBGBEAgAiABNgIAIAENAUGkncAAQaSdwAAoAgBBfiAAKAIcd3E2AgAPCyAEQRBBFCAEKAIQIABGG2ogATYCACABRQ0BCyABIAQ2AhggACgCECICBEAgASACNgIQIAIgATYCGAsgAEEUaigCACIARQ0AIAFBFGogADYCACAAIAE2AhgLC54CAQJ/IwBBQGoiAiQAIAIgATYCBCACQQA2AhAgAkIBNwMIIAJBAjYCHCACIAJBBGo2AhggAiACQQhqNgIkIAJBPGpBATYCACACQgE3AiwgAkHQgMAANgIoIAIgAkEYajYCOAJAAkAgAkEkakGQgcAAIAJBKGoQEEUEQCACKAIMIgMgAigCECIBRwRAIAMgAUkNAgJAIAFFBEAgAwRAIAIoAggQFQsgAkEBNgIIQQAhAQwBCyACKAIIIANBASABEHwiA0UNBCACIAM2AggLIAIgATYCDAsgACACKQMINwIAIABBCGogAkEQaigCADYCACACQUBrJAAPC0HYgMAAQTcgAkEoakGogcAAEE8AC0GwgsAAEGMACyABQQEQjwEAC7ECAQZ/IAEoAgQiBCABKAIIIgJNBEAgAEEANgIADwsgASgCACEGAkACQAJAAkACQANAQQ0hByACIAZqLQAAIgNBd2oiBUEjSwRAIANB3QBHDQYgAkEBaiIDIAJJDQMgASADNgIIIABBETYCAA8LAkAgBUECaw4iBgYABgYGBgYGBgYGBgYGBgYGBgYGAAYGBgYGBgYGBgYGAgALIAEgAkEBaiICNgIIIAIgBEcNAAsgAEEANgIADwsgAkEBaiIDIAJJDQEgASADNgIIIAQgA00NAwNAIAMgBmotAAAiAkF3aiIFQRdLQQEgBXRBk4CABHFFcg0DIAEgA0EBaiIDNgIIIAMgBEcNAAsMAwtBzI7AABBjAAtBzI7AABBjAAsgAkHdAEcNAEEOIQcLIAAgBzYCAAv3AQEEfyMAQSBrIgIkACACIAEQTQJAIAItAABBAXEEQCACLQABQSJHBEAgAEEKNgIADAILIAEQdCACQQhqIAEQPiACQRRqKAIAIQUgAkEQaigCACEDIAIoAgwhASACKAIIIgRBAUYEQCACQRhqKAIAIQQgACADNgIEIAAgATYCACAAQQxqIAQ2AgAgAEEIaiAFNgIADAILAkACQCADQQhHDQAgAUGAhcAARwRAIAEpAABC9srJy+as2rLyAFINAQsgAEERNgIADAELIAAgASADEEsLIAVFIARFIAFBD0dycg0BIAMQFQwBCyAAQQM2AgALIAJBIGokAAvSAgEGfyMAQUBqIgQkAEEBIQUgAygCDCEGIAMoAgghByADKAIEIQggAygCACEJAkACQAJAQeigwAAoAgBBAUcEQEHooMAAQoGAgIAQNwMADAELQeygwABB7KDAACgCAEEBaiIFNgIAIAVBAksNAQsgBEEwaiIDIAY2AgwgAyAHNgIIIAMgCDYCBCADIAk2AgAgBEEkaiAEQThqKQMANwIAIAQgAjYCGCAEQcSSwAA2AhQgBEEBNgIQIAQgBCkDMDcCHEGUncAAKAIAIgJBf0wNAEGUncAAIAJBAWoiAjYCAEGUncAAQZydwAAoAgAiAwR/QZidwAAoAgAgBEEIaiAAIAEoAhARBQAgBCAEKQMINwMQIARBEGogAygCDBEFAEGUncAAKAIABSACC0F/ajYCACAFQQFNDQELAAsjAEEQayICJAAgAiABNgIMIAIgADYCCAAL4gEBBX8gASgCCCECIAEoAgAhAQJAAkBBCEEEEIIBIgMEQCADIAI2AgQgAyABNgIAQcgAEGciAkUNAUEIQQQQggEiAUUNAiABQcgANgIEIAEgAjYCAAJ/IAMgARACIgRBAEgEQCAAQQA6AAQgAEEIakHQhsAANgIAQQEhBUEgDAELIAEoAgAhBiABKAIEIQIgARAVIABBCGogAjYCACAAIAY2AgQgAiAEIAIgBEkbCyEBIAMQFSAAIAU2AgAgAEEMaiABNgIADwtBCEEEEI8BAAtByABBARCPAQALQQhBBBCPAQAL4gEBBX8gASgCCCECIAEoAgAhAQJAAkBBCEEEEIIBIgMEQCADIAI2AgQgAyABNgIAQcgAEGciAkUNAUEIQQQQggEiAUUNAiABQcgANgIEIAEgAjYCAAJ/IAMgARADIgRBAEgEQCAAQQA6AAQgAEEIakHwhsAANgIAQQEhBUEfDAELIAEoAgAhBiABKAIEIQIgARAVIABBCGogAjYCACAAIAY2AgQgAiAEIAIgBEkbCyEBIAMQFSAAIAU2AgAgAEEMaiABNgIADwtBCEEEEI8BAAtByABBARCPAQALQQhBBBCPAQAL3AEBBH8jAEFAaiICJAAgAUEEaiEEIAEoAgRFBEAgASgCACEDIAJBADYCICACQgE3AxggAiACQRhqNgIkIAJBOGogA0EQaikCADcDACACQTBqIANBCGopAgA3AwAgAiADKQIANwMoIAJBJGpBrJLAACACQShqEBAaIAJBEGoiAyACKAIgNgIAIAIgAikDGDcDCAJAIAEoAgQiBUUNACABQQhqKAIARQ0AIAUQFQsgBCACKQMINwIAIARBCGogAygCADYCAAsgAEHAk8AANgIEIAAgBDYCACACQUBrJAAL2QEBAX8jAEEwayICJAACfyAALQAERQRAIAJBNDYCDCACIAA2AgggAUEcaigCACEAIAEoAhggAkEsakEBNgIAIAJCATcCHCACQbyYwAA2AhggAiACQQhqNgIoIAAgAkEYahAQDAELIAIgAEEFai0AADoAByACQRRqQTQ2AgAgAiAANgIQIAJBODYCDCABQRxqKAIAIQAgAiACQQdqNgIIIAEoAhggAkEsakECNgIAIAJCAjcCHCACQfCYwAA2AhggAiACQQhqNgIoIAAgAkEYahAQCyACQTBqJAALyQEBB38jAEEQayIDJAAgASgCBCEFIAEoAgghBAJAAkADQCAFIAIgBGoiBk0EQCAAQoGAgIAgNwIADAILIAEoAgAgBGoiByACai0AACABIAZBAWo2AgggAkEBaiECQSJHDQALIAIgBGpBf2oiASAESQ0BIAMgByACQX9qEGFBASECQQshASADKAIAQQFHBEAgAEEIaiADQQhqKAIANgIAQQAhAiADKAIEIQELIAAgAjYCACAAIAE2AgQLIANBEGokAA8LIAQgARBTAAu/AQEDfwJAAkACQCAAKAIAIgBBBGooAgAiBCAAQQhqKAIAIgNrIAJPBEAgACgCACEEDAELIAIgA2oiBSADSQ0CIARBAXQiAyAFIAMgBUsbIgNBAEgNAgJ/IARFBEAgA0EBEIIBDAELIAAoAgAgBEEBIAMQfAsiBEUNASAAIAQ2AgAgAEEEaiADNgIAIABBCGooAgAhAwsgAEEIaiACIANqNgIAIAMgBGogASACEGwaQQAPCyADQQEQjwEACxCRAQALxwEBAn8CQAJAAkAgASgCCCIDIAFBBGooAgBHBEAgASgCACECDAELIANBAWoiAiADSQ0CIANBAXQiBCACIAQgAksbIgRBAEgNAgJ/IANFBEAgBEEBEIIBDAELIAEoAgAgA0EBIAQQfAsiAkUNASABIAI2AgAgAUEEaiAENgIAIAEoAgghAwsgAiADakHbADoAACAAQQhqQQE6AAAgAEEEaiABNgIAIABBADoAACABIAEoAghBAWo2AggPCyAEQQEQjwEACxCRAQALxwEBA38CQAJAAkAgASgCCCICIAFBBGooAgBHBEAgASgCACEEDAELIAJBAWoiAyACSQ0CIAJBAXQiBCADIAQgA0sbIgNBAEgNAgJ/IAJFBEAgA0EBEIIBDAELIAEoAgAgAkEBIAMQfAsiBEUNASABIAQ2AgAgAUEEaiADNgIAIAEoAgghAgsgAiAEakH7ADoAACAAQQhqQQE6AAAgAEEEaiABNgIAIABBADoAACABIAEoAghBAWo2AggPCyADQQEQjwEACxCRAQALwAEBBX8CQAJAAkBBCEEEEIIBIgMEQCADQQY2AgQgA0HHhMAANgIAQdAPEGciAkUNAUEIQQQQggEiAUUNAiABQdAPNgIEIAEgAjYCACADIAEQACICQQBIDQMCQCACBEAgASgCACEFIAEoAgQhBCABEBUgACAENgIEIAAgBTYCACAAQQhqIAQgAiAEIAJJGzYCAAwBCyAAQQA2AgALIAMQFQ8LQQhBBBCPAQALQdAPQQEQjwEAC0EIQQQQjwEACxByAAu8AQEDfwJAAkACQCAAQQRqKAIAIgIgAEEIaigCACIBa0EETwRAIAAoAgAhAgwBCyABQQRqIgMgAUkNAiACQQF0IgEgAyABIANLGyIBQQBIDQICfyACRQRAIAFBARCCAQwBCyAAKAIAIAJBASABEHwLIgJFDQEgACACNgIAIABBBGogATYCACAAQQhqKAIAIQELIABBCGogAUEEajYCACABIAJqQe7qseMGNgAAQQIPCyABQQEQjwEACxCRAQALrgEBA38CQAJAAkAgACgCCCIBIABBBGooAgBHBEAgACgCACEDDAELIAFBAWoiAiABSQ0CIAFBAXQiAyACIAMgAksbIgJBAEgNAgJ/IAFFBEAgAkEBEIIBDAELIAAoAgAgAUEBIAIQfAsiA0UNASAAIAM2AgAgAEEEaiACNgIAIAAoAgghAQsgASADakHdADoAACAAIAAoAghBAWo2AghBAg8LIAJBARCPAQALEJEBAAuuAQECfwJAAkACQCAAKAIIIgEgAEEEaigCAEcEQCAAKAIAIQIMAQsgAUEBaiICIAFJDQIgAUEBdCIDIAIgAyACSxsiA0EASA0CAn8gAUUEQCADQQEQggEMAQsgACgCACABQQEgAxB8CyICRQ0BIAAgAjYCACAAQQRqIAM2AgAgACgCCCEBCyABIAJqQf0AOgAAIAAgACgCCEEBajYCCEECDwsgA0EBEI8BAAsQkQEAC4MBAQJ/IABBBGooAgAEQCAAKAIAEBULAkAgACgCDCIBRQ0AIABBFGooAgAiAgRAIAJBGGwhAgNAIAFBBGooAgAEQCABKAIAEBULIAFBEGooAgAEQCABQQxqKAIAEBULIAFBGGohASACQWhqIgINAAsLIABBEGooAgBFDQAgACgCDBAVCwvEAQEGf0EBIQMCQAJAAkAgASgCBCIEIAEoAggiAk0NACABKAIAIQUDQEENIQMgAiAFai0AACIGQXdqIgdBI0sEQCAGQf0ARw0CIAJBAWoiAyACSQ0EIAEgAzYCCCAAQRE2AgAPCwJAIAdBAmsOIgICAAICAgICAgICAgICAgICAgICAgACAgICAgICAgICAgMAC0EBIQMgASACQQFqIgI2AgggAiAERw0ACwsgACADNgIADwsgAEEONgIADwtBzI7AABBjAAuWAQECfyAALQAIIQEgACgCBCICBEAgAUH/AXEhASAAAn9BASABDQAaAkAgAkEBRw0AIAAtAAlFDQAgACgCACICLQAAQQRxDQBBASACKAIYQcmcwABBASACQRxqKAIAKAIMEQgADQEaCyAAKAIAIgEoAhhBgJnAAEEBIAFBHGooAgAoAgwRCAALIgE6AAgLIAFB/wFxQQBHC4ABAQJ/AkACQCAAKAIEIgIgACgCCCIDayABSQRAIAEgA2oiASADSQ0CIAJBAXQiAyABIAMgAUsbIgFBAEgNAgJ/IAJFBEAgAUEBEIIBDAELIAAoAgAgAkEBIAEQfAsiAkUNASAAIAE2AgQgACACNgIACw8LIAFBARCPAQALEJEBAAu8AQEFf0EBIQMCQAJAIAEoAgQiBCABKAIIIgJNDQAgASgCACEFA0BBBCEDIAIgBWotAABBd2oiBkExSw0BAkAgBkECaw4wAgIAAgICAgICAgICAgICAgICAgICAAICAgICAgICAgICAgICAgICAgICAgICAgIDAAtBASEDIAEgAkEBaiICNgIIIAIgBEcNAAsLIAAgAzYCAA8LIAJBAWoiAyACSQRAQcyOwAAQYwALIAEgAzYCCCAAQRE2AgALhgEBAX8jAEFAaiIDJAAgAyACNgIMIAMgATYCCCADQSRqQQI2AgAgA0E0akEENgIAIANCAjcCFCADQayDwAA2AhAgA0EBNgIsIANBATYCPCADQZyFwAA2AjggAyADQShqNgIgIAMgA0E4ajYCMCADIANBCGo2AiggACADQRBqEDMgA0FAayQAC18BAX4gACABQiCIIgNCAH4gAkIKfnxCAHwgA0IKfiABQv////8Pg0IKfiIBQiCIfCICQiCIfCACQv////8Pg0IAfCICQiCIfDcDCCAAIAFC/////w+DIAJCIIaENwMAC3MBBn8CQCABKAIEIgQgASgCCCICTQ0AIAEoAgAhBQNAIAIgBWotAAAiBkF3aiIHQRdLBEBBASEDDAILQQEgB3RBk4CABHFFBEBBASEDDAILIAEgAkEBaiICNgIIIAQgAksNAAsLIAAgBjoAASAAIAM6AAALeQEGf0EDIQJBvIPAACEDA0AgAkUEQCAAQRE2AgAPCyABKAIIIgQgASgCAGpBACABKAIEIgYgBEsbIQUgAy0AACEHIAYgBEsEQCABIARBAWo2AggLIAUEQCADQQFqIQMgAkF/aiECIAcgBS0AAEYNAQsLIABBBzYCAAuAAQEBfyMAQUBqIgQkACAEIAE2AgwgBCAANgIIIAQgAzYCFCAEIAI2AhAgBEEsakECNgIAIARBPGpBNjYCACAEQgI3AhwgBEH8lsAANgIYIARBNzYCNCAEIARBMGo2AiggBCAEQRBqNgI4IAQgBEEIajYCMCAEQRhqQaSXwAAQaQALcQEDfyMAQRBrIgIkACACIAEoAgAQSgJAIAIoAgAiA0ERRwRAIAJBDGooAgAhASACQQhqKAIAIQQgACACKAIENgIEIAAgAzYCACAAQQxqIAE2AgAgAEEIaiAENgIADAELIAAgASgCABAPCyACQRBqJAALeQIEfwF+IwBBMGsiASQAIABBDGoQfyECIAAoAggQfyEDIAFBCGogAikCADcCACABKQMIIQUgAigCCCEEIAEgAigCDDYCHCABIAQ2AhggASAFNwMQIAFBADYCJCABIAM2AiAgAUEgakGsk8AAIAAoAgggAUEQahA5AAtsAQF/IwBBMGsiAyQAIAMgAjYCBCADIAE2AgAgA0EcakECNgIAIANBLGpBNDYCACADQgI3AgwgA0GQlsAANgIIIANBNDYCJCADIANBIGo2AhggAyADNgIoIAMgA0EEajYCICADQQhqIAAQaQALbwEBfyMAQTBrIgIkACACIAE2AgQgAiAANgIAIAJBHGpBAjYCACACQSxqQTQ2AgAgAkICNwIMIAJB8JfAADYCCCACQTQ2AiQgAiACQSBqNgIYIAIgAkEEajYCKCACIAI2AiAgAkEIakGAmMAAEGkAC1YBAn8jAEEgayICJAAgAUEcaigCACEDIAEoAhggAkEYaiAAQRBqKQIANwMAIAJBEGogAEEIaikCADcDACACIAApAgA3AwggAyACQQhqEBAgAkEgaiQAC1YBAn8jAEEgayICJAAgAEEcaigCACEDIAAoAhggAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAyACQQhqEBAgAkEgaiQAC18BA38gAAJ/IAEoAgQiAiABKAIIIgBLBEAgASgCACEDA0BBDSAAIANqLQAAQXdqIgRBF0tBASAEdEGTgIAEcUVyDQIaIAEgAEEBaiIANgIIIAAgAkcNAAsLQRELNgIAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBkIHAACACQQhqEBAgAkEgaiQAC1kBAX8jAEEgayICJAAgAiAAKAIANgIEIAJBGGogAUEQaikCADcDACACQRBqIAFBCGopAgA3AwAgAiABKQIANwMIIAJBBGpBrJLAACACQQhqEBAgAkEgaiQAC0YAAkBBCCACSQRAAn9BCCACSQRAIAIgAxAlDAELIAMQBQsiAg0BQQAPCyAAIAMQGg8LIAIgACADIAEgASADSxsQbCAAEBULWQEBfyMAQSBrIgIkACACIAAoAgA2AgQgAkEYaiABQRBqKQIANwMAIAJBEGogAUEIaikCADcDACACIAEpAgA3AwggAkEEakHQk8AAIAJBCGoQECACQSBqJAALXQECfwJAQQhBBBCCASICBEAgAkEGNgIEIAJBx4TAADYCAEEIQQQQggEiA0UNASADIAE2AgQgAyAANgIAIAIgAxABIAMQFSACEBUPC0EIQQQQ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YEgBEAAPAAAAVwEQAAEAAABkdXBsaWNhdGUgZmllbGQgYAAAAGgBEAARAAAAVwEQAAEAAAB1bmtub3duIHZhcmlhbnQgYGAsIGV4cGVjdGVkIAAAAIwBEAARAAAAnQEQAAwAAAB1bGxDb2luUGFyYW1zUmVzcG9uc2Vsb2dkYXRhQ29zbW9zTXNnb3BhcXVlY29udHJhY3RfYWRkcm1zZ3NlbmRmcm9tX2FkZHJlc3N0b19hZGRyZXNzUXVlcnlSZXN1bHRlcnJva0NvbnRyYWN0UmVzdWx0SGFuZGxlTXNnSW5pdE1zZ1F1ZXJ5TXNnY29uZmlnU3RhdGV1bmluaXRpYWxpemVkIGRhdGFyZWxlYXNlZCBmdW5kcyB0byAAAGQCEAASAAAAdmVyaWZpZXJiZW5lZmljaWFyeWZ1bmRlcgAAAIACEAAIAAAAFAAAAAgAAAAEAAAAFQAAABYAAAAUAAAACAAAAAQAAAAXAAAAGAAAAAAAAAABAAAAGQAAAC91c3IvbG9jYWwvY2FyZ28vZ2l0L2NoZWNrb3V0cy9jb3Ntd2FzbS01YmVjZDY0MDBjODllNmY5Lzc4NjU3MDUvc3JjL2ltcG9ydHMucnMA2AIQAE8AAAA5AAAADQAAAG5lZWRlZCB0byByZWFkIG1vcmUgZGF0YWNhbm9uaWNhbF9hZGRyZXNzIHJldHVybmVkIGVycm9yaHVtYW5pemVfYWRkcmVzcyByZXR1cm5lZCBlcnJvcgC4AhAAAAAAAEludmFsaWQgOiAAAJgDEAAIAAAAoAMQAAIAAABVbmF1dGhvcml6ZWS0AxAADAAAAFVURjggZW5jb2RpbmcgZXJyb3I6IAAAAMgDEAAVAAAARXJyb3Igc2VyaWFsaXppbmcgAADoAxAAEgAAAKADEAACAAAARXJyb3IgcGFyc2luZyAAAAwEEAAOAAAAoAMQAAIAAABSZWNlaXZlZCBudWxsIHBvaW50ZXIsIHJlZnVzZSB0byB1c2UsBBAAJAAAACBub3QgZm91bmQAALgCEAAAAAAAWAQQAAoAAABDb250cmFjdCBlcnJvcjogdAQQABAAAACMBBAAAAAAAEludmFsaWQgSlNPTkpTT04gaGFzIGEgY29tbWEgYWZ0ZXIgdGhlIGxhc3QgdmFsdWUgaW4gYW4gYXJyYXkgb3IgbWFwLkpTT04gaGFzIG5vbi13aGl0ZXNwYWNlIHRyYWlsaW5nIGNoYXJhY3RlcnMgYWZ0ZXIgdGhlIHZhbHVlLk9iamVjdCBrZXkgaXMgbm90IGEgc3RyaW5nLkludmFsaWQgdW5pY29kZSBjb2RlIHBvaW50LkludmFsaWQgdHlwZUludmFsaWQgbnVtYmVyLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIHN0YXJ0IGEgSlNPTiB2YWx1ZS5FeHBlY3RlZCB0byBwYXJzZSBlaXRoZXIgYSBgdHJ1ZWAsIGBmYWxzZWAsIG9yIGEgYG51bGxgLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIGJlIGVpdGhlciBhIGAnLCdgIG9yIGEgYCd9J2AuRXhwZWN0ZWQgdGhpcyBjaGFyYWN0ZXIgdG8gYmUgZWl0aGVyIGEgYCcsJ2Agb3JhIGAnXSdgLkV4cGVjdGVkIHRoaXMgY2hhcmFjdGVyIHRvIGJlIGEgYCc6J2AuRU9GIHdoaWxlIHBhcnNpbmcgYSBKU09OIHZhbHVlLkVPRiB3aGlsZSBwYXJzaW5nIGEgc3RyaW5nLkVPRiB3aGlsZSBwYXJzaW5nIGFuIG9iamVjdC5FT0Ygd2hpbGUgcGFyc2luZyBhIGxpc3QuL3Vzci9sb2NhbC9jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NlcmRlLWpzb24td2FzbS0wLjEuMi9zcmMvZGUvbW9kLnJzAAAAYXR0ZW1wdCB0byBhZGQgd2l0aCBvdmVyZmxvdzAHEAAcAAAA0AYQAF0AAACSAAAACQAAAEJ1ZmZlciBpcyBmdWxsAABkBxAADgAAAAAAAAAvdXNyL2xvY2FsL2NhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvc2VyZGUtanNvbi13YXNtLTAuMS4yL3NyYy9zZXIvbW9kLnJzAABhdHRlbXB0IHRvIHN1YnRyYWN0IHdpdGggb3ZlcmZsb3cAAADgBxAAIQAAAIAHEABeAAAAUAAAABEAAABfX0V4dGVuc2libGVCdWZmZXJGdWxsAAAdAAAACAAAAAQAAAAeAAAAHwAAAB0AAAAIAAAABAAAACAAAAAhAAAAAAAA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" +} diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 9ce32263..06f5efad 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -25,7 +25,7 @@ export function isAminoStdTx(txValue: unknown): txValue is StdTx { export interface Msg { readonly type: string; // TODO: make better union type - readonly value: MsgSend | unknown; + readonly value: MsgSend | MsgStoreCode | unknown; } export interface MsgSend { @@ -36,6 +36,17 @@ export interface MsgSend { readonly amount: ReadonlyArray; } +export interface MsgStoreCode { + /** Bech32 account address */ + readonly sender: string; + /** Base64 encoded Wasm */ + readonly wasm_byte_code: string; + /** A valid URI reference to the contract's source code, optional */ + readonly source?: string; + /** A docker tag, optional */ + readonly builder?: string; +} + export interface StdFee { readonly amount: ReadonlyArray; readonly gas: string; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index a2c0abd1..a6a42cf5 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -14,7 +14,7 @@ export declare type AminoTx = Tx & { export declare function isAminoStdTx(txValue: unknown): txValue is StdTx; export interface Msg { readonly type: string; - readonly value: MsgSend | unknown; + readonly value: MsgSend | MsgStoreCode | unknown; } export interface MsgSend { /** Bech32 account address */ @@ -23,6 +23,16 @@ export interface MsgSend { readonly to_address: string; readonly amount: ReadonlyArray; } +export interface MsgStoreCode { + /** Bech32 account address */ + readonly sender: string; + /** Base64 encoded Wasm */ + readonly wasm_byte_code: string; + /** A valid URI reference to the contract's source code, optional */ + readonly source?: string; + /** A docker tag, optional */ + readonly builder?: string; +} export interface StdFee { readonly amount: ReadonlyArray; readonly gas: string; From 4e9c0098094d1cbaa3fb0d4b41b073058926d300 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 11:41:24 +0100 Subject: [PATCH 03/14] Use stronger types for Msg --- packages/sdk/src/restclient.spec.ts | 5 ++--- packages/sdk/src/types.ts | 17 ++++++++++++++--- packages/sdk/types/types.d.ts | 14 ++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 48fd024f..c8228eb4 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -3,13 +3,12 @@ import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; -import { types } from "src"; import { marshalTx, sortJson } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { StdSignature, StdTx } from "./types"; +import { MsgStoreCodeWrapped, StdSignature, StdTx } from "./types"; const { fromBase64, toBase64, toUtf8 } = Encoding; @@ -68,7 +67,7 @@ describe("RestClient", () => { const signer = await wallet.createIdentity("abc" as ChainId, faucetPath); const memo = "My first contract on chain"; - const theMsg: types.Msg = { + const theMsg: MsgStoreCodeWrapped = { type: "wasm/store-code", value: { sender: faucetAddress, diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 06f5efad..badfd978 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -22,10 +22,9 @@ export function isAminoStdTx(txValue: unknown): txValue is StdTx { ); } -export interface Msg { +interface MsgUnknownWrapped { readonly type: string; - // TODO: make better union type - readonly value: MsgSend | MsgStoreCode | unknown; + readonly value: object; } export interface MsgSend { @@ -36,6 +35,11 @@ export interface MsgSend { readonly amount: ReadonlyArray; } +export interface MsgSendWrapped extends MsgUnknownWrapped { + readonly type: "cosmos-sdk/StdTx"; + readonly value: MsgSend; +} + export interface MsgStoreCode { /** Bech32 account address */ readonly sender: string; @@ -47,6 +51,13 @@ export interface MsgStoreCode { readonly builder?: string; } +export interface MsgStoreCodeWrapped extends MsgUnknownWrapped { + readonly type: "wasm/store-code"; + readonly value: MsgStoreCode; +} + +export type Msg = MsgSendWrapped | MsgStoreCodeWrapped | MsgUnknownWrapped; + export interface StdFee { readonly amount: ReadonlyArray; readonly gas: string; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index a6a42cf5..7104e3a3 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -12,9 +12,9 @@ export declare type AminoTx = Tx & { readonly value: StdTx; }; export declare function isAminoStdTx(txValue: unknown): txValue is StdTx; -export interface Msg { +interface MsgUnknownWrapped { readonly type: string; - readonly value: MsgSend | MsgStoreCode | unknown; + readonly value: object; } export interface MsgSend { /** Bech32 account address */ @@ -23,6 +23,10 @@ export interface MsgSend { readonly to_address: string; readonly amount: ReadonlyArray; } +export interface MsgSendWrapped extends MsgUnknownWrapped { + readonly type: "cosmos-sdk/StdTx"; + readonly value: MsgSend; +} export interface MsgStoreCode { /** Bech32 account address */ readonly sender: string; @@ -33,6 +37,11 @@ export interface MsgStoreCode { /** A docker tag, optional */ readonly builder?: string; } +export interface MsgStoreCodeWrapped extends MsgUnknownWrapped { + readonly type: "wasm/store-code"; + readonly value: MsgStoreCode; +} +export declare type Msg = MsgSendWrapped | MsgStoreCodeWrapped | MsgUnknownWrapped; export interface StdFee { readonly amount: ReadonlyArray; readonly gas: string; @@ -58,3 +67,4 @@ export interface BaseAccount { readonly account_number: number; readonly sequence: number; } +export {}; From a9189262e525b87e1160ba3b0758c0b874424ed6 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 12:17:20 +0100 Subject: [PATCH 04/14] Increase gas limit in test --- packages/sdk/src/restclient.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index c8228eb4..ed843e87 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -88,7 +88,7 @@ describe("RestClient", () => { denom: "ucosm", }, ], - gas: "200000", + gas: "89000000", }, }; From cd66935dcedba056bccdc5da89d3ba158e0eb30f Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 12:43:25 +0100 Subject: [PATCH 05/14] Extract encodeSecp256k1Signature --- packages/bcp/src/encode.ts | 17 ++++----- packages/sdk/package.json | 1 + packages/sdk/src/encoding.spec.ts | 59 +++++++++++++++++++++++++++++ packages/sdk/src/encoding.ts | 17 ++++++++- packages/sdk/src/index.ts | 2 +- packages/sdk/src/restclient.spec.ts | 20 +++------- packages/sdk/types/encoding.d.ts | 3 +- packages/sdk/types/index.d.ts | 2 +- 8 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 packages/sdk/src/encoding.spec.ts diff --git a/packages/bcp/src/encode.ts b/packages/bcp/src/encode.ts index 94288c48..164fb867 100644 --- a/packages/bcp/src/encode.ts +++ b/packages/bcp/src/encode.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { types } from "@cosmwasm/sdk"; +import { encodeSecp256k1Signature, types } from "@cosmwasm/sdk"; import { Algorithm, Amount, @@ -10,7 +10,6 @@ import { SignedTransaction, UnsignedTransaction, } from "@iov/bcp"; -import { Secp256k1 } from "@iov/crypto"; import { Decimal, Encoding } from "@iov/encoding"; import { TokenInfos } from "./types"; @@ -72,14 +71,12 @@ export function encodeFee(fee: Fee, tokens: TokenInfos): types.StdFee { } export function encodeFullSignature(fullSignature: FullSignature): types.StdSignature { - return { - pub_key: { - type: "tendermint/PubKeySecp256k1", - value: toBase64(Secp256k1.compressPubkey(fullSignature.pubkey.data)), - }, - // Recovery seems to be unused - signature: toBase64(Secp256k1.trimRecoveryByte(fullSignature.signature)), - }; + switch (fullSignature.pubkey.algo) { + case Algorithm.Secp256k1: + return encodeSecp256k1Signature(fullSignature.pubkey.data, fullSignature.signature); + default: + throw new Error("Unsupported signing algorithm"); + } } export function buildUnsignedTx(tx: UnsignedTransaction, tokens: TokenInfos): types.AminoTx { diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 12243e6f..3c5016b9 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -38,6 +38,7 @@ "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" }, "dependencies": { + "@iov/crypto": "^2.0.0-alpha.7", "@iov/encoding": "^2.0.0-alpha.7", "axios": "^0.19.0" }, diff --git a/packages/sdk/src/encoding.spec.ts b/packages/sdk/src/encoding.spec.ts new file mode 100644 index 00000000..6aeb8f61 --- /dev/null +++ b/packages/sdk/src/encoding.spec.ts @@ -0,0 +1,59 @@ +import { Encoding } from "@iov/encoding"; + +import { encodeSecp256k1Signature } from "./encoding"; + +const { fromBase64 } = Encoding; + +describe("encoding", () => { + describe("encodeSecp256k1Signature", () => { + it("encodes a full signature", () => { + const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP"); + const signature = fromBase64( + "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + ); + expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({ + // eslint-disable-next-line @typescript-eslint/camelcase + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP", + }, + signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + }); + }); + + it("compresses uncompressed public keys", () => { + const pubkey = fromBase64( + "BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=", + ); + const signature = fromBase64( + "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + ); + expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({ + // eslint-disable-next-line @typescript-eslint/camelcase + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }, + signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + }); + }); + + it("removes recovery values from signature data", () => { + const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP"); + const signature = Uint8Array.from([ + ...fromBase64( + "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + ), + 99, + ]); + expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({ + // eslint-disable-next-line @typescript-eslint/camelcase + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP", + }, + signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==", + }); + }); + }); +}); diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index 3cee29af..8f10a78d 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -1,6 +1,9 @@ +import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; -import { StdTx } from "./types"; +import { StdSignature, StdTx } from "./types"; + +const { toBase64 } = Encoding; export function sortJson(json: any): any { if (typeof json !== "object" || json === null) { @@ -24,3 +27,15 @@ export function marshalTx(tx: StdTx): Uint8Array { const json = JSON.stringify(tx); return Encoding.toUtf8(json); } + +export function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature { + return { + // eslint-disable-next-line @typescript-eslint/camelcase + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: toBase64(Secp256k1.compressPubkey(pubkey)), + }, + // Recovery seems to be unused + signature: toBase64(Secp256k1.trimRecoveryByte(signature)), + }; +} diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 23e94da1..1a2e024c 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,6 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { marshalTx, sortJson } from "./encoding"; +export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index ed843e87..f6febb93 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -1,16 +1,15 @@ /* eslint-disable @typescript-eslint/camelcase */ import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; -import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; -import { marshalTx, sortJson } from "./encoding"; +import { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { MsgStoreCodeWrapped, StdSignature, StdTx } from "./types"; +import { MsgStoreCodeWrapped, StdTx } from "./types"; -const { fromBase64, toBase64, toUtf8 } = Encoding; +const { fromBase64, toUtf8 } = Encoding; const httpUrl = "http://localhost:1317"; const defaultNetworkId = "testing"; @@ -105,21 +104,14 @@ describe("RestClient", () => { }); const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes; - const signature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); - const fullSignature: StdSignature = { - pub_key: { - type: "tendermint/PubKeySecp256k1", - value: toBase64(Secp256k1.compressPubkey(signer.pubkey.data)), - }, - // Recovery seems to be unused - signature: toBase64(Secp256k1.trimRecoveryByte(signature)), - }; + const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); + const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); const tx: StdTx = { msg: unsigned.msg, fee: unsigned.fee, memo: memo, - signatures: [fullSignature], + signatures: [signature], }; const postableBytes = marshalTx(tx); diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index 591bdbb4..22972faf 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,3 +1,4 @@ -import { StdTx } from "./types"; +import { StdSignature, StdTx } from "./types"; export declare function sortJson(json: any): any; export declare function marshalTx(tx: StdTx): Uint8Array; +export declare function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 0c6dcc71..cddb9250 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,5 +1,5 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { marshalTx, sortJson } from "./encoding"; +export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; From 44182e96b7a426bd18b1b8126099d88c6f54c982 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 13:10:27 +0100 Subject: [PATCH 06/14] Improve and fix Msg types --- packages/bcp/src/decode.ts | 7 ++----- packages/sdk/src/restclient.spec.ts | 4 ++-- packages/sdk/src/types.ts | 26 +++++++++++++++++--------- packages/sdk/types/types.d.ts | 20 +++++++++++--------- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/bcp/src/decode.ts b/packages/bcp/src/decode.ts index 2835b0fa..af83599a 100644 --- a/packages/bcp/src/decode.ts +++ b/packages/bcp/src/decode.ts @@ -73,13 +73,10 @@ export function decodeAmount(tokens: TokenInfos, coin: types.Coin): Amount { } export function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): SendTransaction { - if (msg.type !== "cosmos-sdk/MsgSend") { + if (!types.isMsgSend(msg)) { throw new Error("Unknown message type in transaction"); } - if (!(msg.value as types.MsgSend).from_address) { - throw new Error("Only MsgSend is supported"); - } - const msgValue = msg.value as types.MsgSend; + const msgValue = msg.value; if (msgValue.amount.length !== 1) { throw new Error("Only MsgSend with one amount is supported"); } diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index f6febb93..e753904b 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -7,7 +7,7 @@ import { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { MsgStoreCodeWrapped, StdTx } from "./types"; +import { MsgStoreCode, StdTx } from "./types"; const { fromBase64, toUtf8 } = Encoding; @@ -66,7 +66,7 @@ describe("RestClient", () => { const signer = await wallet.createIdentity("abc" as ChainId, faucetPath); const memo = "My first contract on chain"; - const theMsg: MsgStoreCodeWrapped = { + const theMsg: MsgStoreCode = { type: "wasm/store-code", value: { sender: faucetAddress, diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index badfd978..07066b29 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -22,12 +22,12 @@ export function isAminoStdTx(txValue: unknown): txValue is StdTx { ); } -interface MsgUnknownWrapped { +interface MsgTemplate { readonly type: string; readonly value: object; } -export interface MsgSend { +export interface ValueSend { /** Bech32 account address */ readonly from_address: string; /** Bech32 account address */ @@ -35,12 +35,12 @@ export interface MsgSend { readonly amount: ReadonlyArray; } -export interface MsgSendWrapped extends MsgUnknownWrapped { - readonly type: "cosmos-sdk/StdTx"; - readonly value: MsgSend; +export interface MsgSend extends MsgTemplate { + readonly type: "cosmos-sdk/MsgSend"; + readonly value: ValueSend; } -export interface MsgStoreCode { +export interface ValueStoreCode { /** Bech32 account address */ readonly sender: string; /** Base64 encoded Wasm */ @@ -51,12 +51,20 @@ export interface MsgStoreCode { readonly builder?: string; } -export interface MsgStoreCodeWrapped extends MsgUnknownWrapped { +export interface MsgStoreCode extends MsgTemplate { readonly type: "wasm/store-code"; - readonly value: MsgStoreCode; + readonly value: ValueStoreCode; } -export type Msg = MsgSendWrapped | MsgStoreCodeWrapped | MsgUnknownWrapped; +export type Msg = MsgSend | MsgStoreCode | MsgTemplate; + +export function isMsgSend(msg: Msg): msg is MsgSend { + return (msg as MsgSend).type === "cosmos-sdk/MsgSend"; +} + +export function isMsgStoreCode(msg: Msg): msg is MsgStoreCode { + return (msg as MsgStoreCode).type === "wasm/store-code"; +} export interface StdFee { readonly amount: ReadonlyArray; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index 7104e3a3..b1b43a0d 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -12,22 +12,22 @@ export declare type AminoTx = Tx & { readonly value: StdTx; }; export declare function isAminoStdTx(txValue: unknown): txValue is StdTx; -interface MsgUnknownWrapped { +interface MsgTemplate { readonly type: string; readonly value: object; } -export interface MsgSend { +export interface ValueSend { /** Bech32 account address */ readonly from_address: string; /** Bech32 account address */ readonly to_address: string; readonly amount: ReadonlyArray; } -export interface MsgSendWrapped extends MsgUnknownWrapped { - readonly type: "cosmos-sdk/StdTx"; - readonly value: MsgSend; +export interface MsgSend extends MsgTemplate { + readonly type: "cosmos-sdk/MsgSend"; + readonly value: ValueSend; } -export interface MsgStoreCode { +export interface ValueStoreCode { /** Bech32 account address */ readonly sender: string; /** Base64 encoded Wasm */ @@ -37,11 +37,13 @@ export interface MsgStoreCode { /** A docker tag, optional */ readonly builder?: string; } -export interface MsgStoreCodeWrapped extends MsgUnknownWrapped { +export interface MsgStoreCode extends MsgTemplate { readonly type: "wasm/store-code"; - readonly value: MsgStoreCode; + readonly value: ValueStoreCode; } -export declare type Msg = MsgSendWrapped | MsgStoreCodeWrapped | MsgUnknownWrapped; +export declare type Msg = MsgSend | MsgStoreCode | MsgTemplate; +export declare function isMsgSend(msg: Msg): msg is MsgSend; +export declare function isMsgStoreCode(msg: Msg): msg is MsgStoreCode; export interface StdFee { readonly amount: ReadonlyArray; readonly gas: string; From 2d14efa4cd95edc2a97f8cdcdb3cda4590e3ba43 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 13:34:51 +0100 Subject: [PATCH 07/14] Deduplicate makeSignBytes --- packages/bcp/src/cosmwasmcodec.ts | 26 ++++++++--------- packages/bcp/src/types.ts | 6 +--- packages/bcp/types/types.d.ts | 3 +- packages/sdk/src/encoding.ts | 26 +++++++++++++++-- packages/sdk/src/index.ts | 2 +- packages/sdk/src/restclient.spec.ts | 44 +++++++++-------------------- packages/sdk/src/types.ts | 3 ++ packages/sdk/types/encoding.d.ts | 10 +++++-- packages/sdk/types/index.d.ts | 2 +- packages/sdk/types/types.d.ts | 2 ++ 10 files changed, 66 insertions(+), 58 deletions(-) diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index 7602830f..88285bff 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { marshalTx, sortJson, unmarshalTx } from "@cosmwasm/sdk"; +import { makeSignBytes, marshalTx, types, unmarshalTx } from "@cosmwasm/sdk"; import { Address, ChainId, @@ -14,7 +14,6 @@ import { TxCodec, UnsignedTransaction, } from "@iov/bcp"; -import { Encoding } from "@iov/encoding"; import { CosmosBech32Prefix, isValidAddress, pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; @@ -22,8 +21,6 @@ import { parseTx } from "./decode"; import { buildSignedTx, buildUnsignedTx } from "./encode"; import { nonceToAccountNumber, nonceToSequence, TokenInfos } from "./types"; -const { toUtf8 } = Encoding; - export class CosmWasmCodec implements TxCodec { private readonly prefix: CosmosBech32Prefix; private readonly tokens: TokenInfos; @@ -34,18 +31,19 @@ export class CosmWasmCodec implements TxCodec { } public bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob { - const memo = (unsigned as any).memo; const built = buildUnsignedTx(unsigned, this.tokens); - const signMsg = sortJson({ - account_number: nonceToAccountNumber(nonce).toString(), - chain_id: Caip5.decode(unsigned.chainId), - fee: (built.value as any).fee, - memo: memo, - msgs: (built.value as any).msg, - sequence: nonceToSequence(nonce).toString(), - }); - const signBytes = toUtf8(JSON.stringify(signMsg)); + const nonceInfo: types.NonceInfo = { + account_number: nonceToAccountNumber(nonce), + sequence: nonceToSequence(nonce), + }; + const signBytes = makeSignBytes( + built.value.msg[0], + built.value.fee, + Caip5.decode(unsigned.chainId), + built.value.memo || "", + nonceInfo, + ); return { bytes: signBytes as SignableBytes, diff --git a/packages/bcp/src/types.ts b/packages/bcp/src/types.ts index 2f1ee35a..71ec2be8 100644 --- a/packages/bcp/src/types.ts +++ b/packages/bcp/src/types.ts @@ -23,13 +23,9 @@ const maxAcct = 1 << 23; // tslint:disable-next-line:no-bitwise const maxSeq = 1 << 20; -// NonceInfo is the data we need from account to create a nonce -// Use this so no confusion about order of arguments -export type NonceInfo = Pick; - // this (lossily) encodes the two pieces of info (uint64) needed to sign into // one (53-bit) number. Cross your fingers. -export function accountToNonce({ account_number: account, sequence }: NonceInfo): Nonce { +export function accountToNonce({ account_number: account, sequence }: types.NonceInfo): Nonce { // we allow 23 bits (8 million) for accounts, and 20 bits (1 million) for tx/account // let's fix this soon if (account > maxAcct) { diff --git a/packages/bcp/types/types.d.ts b/packages/bcp/types/types.d.ts index d89725f4..e5a6e631 100644 --- a/packages/bcp/types/types.d.ts +++ b/packages/bcp/types/types.d.ts @@ -15,7 +15,6 @@ export interface TokenInfo { readonly fractionalDigits: number; } export declare type TokenInfos = ReadonlyArray; -export declare type NonceInfo = Pick; -export declare function accountToNonce({ account_number: account, sequence }: NonceInfo): Nonce; +export declare function accountToNonce({ account_number: account, sequence }: types.NonceInfo): Nonce; export declare function nonceToAccountNumber(nonce: Nonce): number; export declare function nonceToSequence(nonce: Nonce): number; diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index 8f10a78d..fe4d34a0 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -1,11 +1,11 @@ import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; -import { StdSignature, StdTx } from "./types"; +import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; -const { toBase64 } = Encoding; +const { toBase64, toUtf8 } = Encoding; -export function sortJson(json: any): any { +function sortJson(json: any): any { if (typeof json !== "object" || json === null) { return json; } @@ -28,6 +28,26 @@ export function marshalTx(tx: StdTx): Uint8Array { return Encoding.toUtf8(json); } +export function makeSignBytes( + msg: Msg, + fee: StdFee, + chainId: string, + memo: string, + account: NonceInfo, +): Uint8Array { + const signMsg = sortJson({ + // eslint-disable-next-line @typescript-eslint/camelcase + account_number: account.account_number.toString(), + // eslint-disable-next-line @typescript-eslint/camelcase + chain_id: chainId, + fee: fee, + memo: memo, + msgs: msg, + sequence: account.sequence.toString(), + }); + return toUtf8(JSON.stringify(signMsg)); +} + export function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature { return { // eslint-disable-next-line @typescript-eslint/camelcase diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 1a2e024c..9016d432 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,6 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; +export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index e753904b..4f5d3a58 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -3,13 +3,13 @@ import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; -import { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; +import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { MsgStoreCode, StdTx } from "./types"; +import { MsgStoreCode, StdFee, StdTx } from "./types"; -const { fromBase64, toUtf8 } = Encoding; +const { fromBase64 } = Encoding; const httpUrl = "http://localhost:1317"; const defaultNetworkId = "testing"; @@ -75,41 +75,25 @@ describe("RestClient", () => { builder: "v0.0.1", }, }; - - const unsigned: StdTx = { - msg: [theMsg], - memo: memo, - signatures: [], - fee: { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "89000000", - }, + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "89000000", }; const client = new RestClient(httpUrl); const account = (await client.authAccounts(faucetAddress)).result.value; - - const signMsg = sortJson({ - account_number: account.account_number.toString(), - chain_id: defaultNetworkId, - fee: unsigned.fee, - memo: memo, - msgs: unsigned.msg, - sequence: account.sequence.toString(), - }); - - const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes; + const signBytes = makeSignBytes(theMsg, fee, defaultNetworkId, memo, account) as SignableBytes; const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); const tx: StdTx = { - msg: unsigned.msg, - fee: unsigned.fee, + msg: [theMsg], + fee: fee, memo: memo, signatures: [signature], }; diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 07066b29..243088b4 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -97,3 +97,6 @@ export interface BaseAccount { readonly account_number: number; readonly sequence: number; } + +/** The data we need from BaseAccount to create a nonce */ +export type NonceInfo = Pick; diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index 22972faf..e7f23d60 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,4 +1,10 @@ -import { StdSignature, StdTx } from "./types"; -export declare function sortJson(json: any): any; +import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; export declare function marshalTx(tx: StdTx): Uint8Array; +export declare function makeSignBytes( + msg: Msg, + fee: StdFee, + chainId: string, + memo: string, + account: NonceInfo, +): Uint8Array; export declare function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index cddb9250..8c8e4b4b 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,5 +1,5 @@ import * as types from "./types"; export { unmarshalTx } from "./decoding"; -export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding"; +export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { types }; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index b1b43a0d..3eaa73c3 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -69,4 +69,6 @@ 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; export {}; From 220c0c69d61b37da6a24e9152e4981030468eb92 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 4 Feb 2020 13:38:06 +0100 Subject: [PATCH 08/14] Add test case for simple MsgSend --- packages/sdk/src/encoding.ts | 2 +- packages/sdk/src/restclient.spec.ts | 71 +++++++++++++++++++++++++++-- packages/sdk/types/encoding.d.ts | 1 + 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index fe4d34a0..584c3575 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -5,7 +5,7 @@ import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; const { toBase64, toUtf8 } = Encoding; -function sortJson(json: any): any { +export function sortJson(json: any): any { if (typeof json !== "object" || json === null) { return json; } diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 4f5d3a58..c5d528a6 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -3,13 +3,13 @@ import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; -import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; +import { encodeSecp256k1Signature, makeSignBytes, marshalTx, sortJson } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; -import { MsgStoreCode, StdFee, StdTx } from "./types"; +import { MsgSend, MsgStoreCode, StdFee, StdTx } from "./types"; -const { fromBase64 } = Encoding; +const { fromBase64, toUtf8 } = Encoding; const httpUrl = "http://localhost:1317"; const defaultNetworkId = "testing"; @@ -17,6 +17,7 @@ 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 faucetPath = HdPaths.cosmos(0); const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; +const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k"; function pendingWithoutCosmos(): void { if (!process.env.COSMOS_ENABLED) { @@ -60,6 +61,70 @@ describe("RestClient", () => { }); describe("post", () => { + it("can send tokens", async () => { + pendingWithoutCosmos(); + const wallet = Secp256k1HdWallet.fromMnemonic(faucetMnemonic); + const signer = await wallet.createIdentity("abc" as ChainId, faucetPath); + + const memo = "My first contract on chain"; + const theMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: faucetAddress, + to_address: emptyAddress, + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + + const unsigned: StdTx = { + msg: [theMsg], + memo: memo, + signatures: [], + fee: { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }, + }; + + const client = new RestClient(httpUrl); + const account = (await client.authAccounts(faucetAddress)).result.value; + + const signMsg = sortJson({ + account_number: account.account_number.toString(), + chain_id: defaultNetworkId, + fee: unsigned.fee, + memo: memo, + msgs: unsigned.msg, + sequence: account.sequence.toString(), + }); + + const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes; + const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); + const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); + + const tx: StdTx = { + msg: unsigned.msg, + fee: unsigned.fee, + memo: memo, + signatures: [signature], + }; + + const postableBytes = marshalTx(tx); + const result = await client.postTx(postableBytes); + // console.log("Raw log:", result.raw_log); + expect(result.code).toBeFalsy(); + }); + it("can upload wasm", async () => { pendingWithoutCosmos(); const wallet = Secp256k1HdWallet.fromMnemonic(faucetMnemonic); diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index e7f23d60..463b7516 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,4 +1,5 @@ import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; +export declare function sortJson(json: any): any; export declare function marshalTx(tx: StdTx): Uint8Array; export declare function makeSignBytes( msg: Msg, From 3fe792e058365fe20af11e6c4b05d1822a14919f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 4 Feb 2020 14:00:24 +0100 Subject: [PATCH 09/14] Disable faucet docker job --- .circleci/config.yml | 2 +- packages/sdk/src/restclient.spec.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 67d28966..3776c694 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ workflows: jobs: - build - lint - - faucet_docker + # - faucet_docker - test jobs: diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index c5d528a6..e4bee541 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -163,6 +163,12 @@ describe("RestClient", () => { signatures: [signature], }; + // make sure this is a valid encoding/decoding + const aminoBytes = await client.encodeTx(tx); + expect(aminoBytes).toBeTruthy(); + expect(aminoBytes.length).toEqual(63084); + + // now submit it const postableBytes = marshalTx(tx); const result = await client.postTx(postableBytes); // console.log("Raw log:", result.raw_log); From 555534ba1b6cdbfa81817572033cfd14610b639d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 4 Feb 2020 14:29:38 +0100 Subject: [PATCH 10/14] Add script to run local binaries, help debug --- scripts/cosm/manual_start.sh | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100755 scripts/cosm/manual_start.sh diff --git a/scripts/cosm/manual_start.sh b/scripts/cosm/manual_start.sh new file mode 100755 index 00000000..a203e7bc --- /dev/null +++ b/scripts/cosm/manual_start.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -o errexit -o nounset -o pipefail +command -v shellcheck > /dev/null && shellcheck "$0" + +## This is like start.sh but using local binaries, not docker images +SCRIPT_DIR="$(realpath "$(dirname "$0")")" + +TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gaia.XXXXXXXXX") +chmod 777 "$TMP_DIR" +echo "Using temporary dir $TMP_DIR" +WASMD_LOGFILE="$TMP_DIR/wasmd.log" +REST_SERVER_LOGFILE="$TMP_DIR/rest-server.log" + +# move the template into our temporary home +cp -r "$SCRIPT_DIR"/template/.wasm* "$TMP_DIR" + +wasmd start \ + --home "$TMP_DIR/.wasmd" \ + --trace \ + --rpc.laddr tcp://0.0.0.0:26657 \ + > "$WASMD_LOGFILE" & + +echo "wasmd running and logging into $WASMD_LOGFILE" + +sleep 10 +cat "$WASMD_LOGFILE" + +wasmcli rest-server \ + --home "$TMP_DIR/.wasmcli" \ + --node tcp://localhost:26657 \ + --trust-node \ + --laddr tcp://0.0.0.0:1317 \ + > "$REST_SERVER_LOGFILE" & + +echo "rest server running on http://localhost:1317 and logging into $REST_SERVER_LOGFILE" + +# Debug rest server start +sleep 3 +cat "$REST_SERVER_LOGFILE" + +tail -f "$WASMD_LOGFILE" From 63e3ab037cf3272fe8f88cf7aedc0d4e1fe88e91 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 15:09:33 +0100 Subject: [PATCH 11/14] Make messages in makeSignBytes a list this fixes a bug introduced in 2d14efa4cd95edc --- packages/bcp/src/cosmwasmcodec.ts | 2 +- packages/sdk/src/encoding.ts | 18 ++++++++++++++---- packages/sdk/src/restclient.spec.ts | 2 +- packages/sdk/types/encoding.d.ts | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index 88285bff..58644f2b 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -38,7 +38,7 @@ export class CosmWasmCodec implements TxCodec { sequence: nonceToSequence(nonce), }; const signBytes = makeSignBytes( - built.value.msg[0], + built.value.msg, built.value.fee, Caip5.decode(unsigned.chainId), built.value.memo || "", diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index 584c3575..62c17d32 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -28,23 +28,33 @@ export function marshalTx(tx: StdTx): Uint8Array { return Encoding.toUtf8(json); } +interface SignJson { + readonly account_number: string; + readonly chain_id: string; + readonly fee: StdFee; + readonly memo: string; + readonly msgs: readonly Msg[]; + readonly sequence: string; +} + export function makeSignBytes( - msg: Msg, + msgs: readonly Msg[], fee: StdFee, chainId: string, memo: string, account: NonceInfo, ): Uint8Array { - const signMsg = sortJson({ + const signJson: SignJson = { // eslint-disable-next-line @typescript-eslint/camelcase account_number: account.account_number.toString(), // eslint-disable-next-line @typescript-eslint/camelcase chain_id: chainId, fee: fee, memo: memo, - msgs: msg, + msgs: msgs, sequence: account.sequence.toString(), - }); + }; + const signMsg = sortJson(signJson); return toUtf8(JSON.stringify(signMsg)); } diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index e4bee541..6bcff98a 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -152,7 +152,7 @@ describe("RestClient", () => { const client = new RestClient(httpUrl); const account = (await client.authAccounts(faucetAddress)).result.value; - const signBytes = makeSignBytes(theMsg, fee, defaultNetworkId, memo, account) as SignableBytes; + const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account) as SignableBytes; const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index 463b7516..69a1f7a6 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -2,7 +2,7 @@ import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; export declare function sortJson(json: any): any; export declare function marshalTx(tx: StdTx): Uint8Array; export declare function makeSignBytes( - msg: Msg, + msgs: readonly Msg[], fee: StdFee, chainId: string, memo: string, From f3a413f62a6ea111c74a2de6e70c1e43e00dd6ce Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 15:28:14 +0100 Subject: [PATCH 12/14] Cleanup test code --- packages/sdk/src/encoding.ts | 2 +- packages/sdk/src/restclient.spec.ts | 60 ++++++++++------------------- packages/sdk/types/encoding.d.ts | 1 - 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index 62c17d32..88844d26 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -5,7 +5,7 @@ import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; const { toBase64, toUtf8 } = Encoding; -export function sortJson(json: any): any { +function sortJson(json: any): any { if (typeof json !== "object" || json === null) { return json; } diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 6bcff98a..ade652b4 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -3,13 +3,13 @@ import { ChainId, PrehashType, SignableBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; -import { encodeSecp256k1Signature, makeSignBytes, marshalTx, sortJson } from "./encoding"; +import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; import { MsgSend, MsgStoreCode, StdFee, StdTx } from "./types"; -const { fromBase64, toUtf8 } = Encoding; +const { fromBase64 } = Encoding; const httpUrl = "http://localhost:1317"; const defaultNetworkId = "testing"; @@ -81,45 +81,31 @@ describe("RestClient", () => { }, }; - const unsigned: StdTx = { - msg: [theMsg], - memo: memo, - signatures: [], - fee: { - amount: [ - { - amount: "5000", - denom: "ucosm", - }, - ], - gas: "890000", - }, + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", }; const client = new RestClient(httpUrl); const account = (await client.authAccounts(faucetAddress)).result.value; - const signMsg = sortJson({ - account_number: account.account_number.toString(), - chain_id: defaultNetworkId, - fee: unsigned.fee, - memo: memo, - msgs: unsigned.msg, - sequence: account.sequence.toString(), - }); - - const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes; + const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account) as SignableBytes; const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); - const tx: StdTx = { - msg: unsigned.msg, - fee: unsigned.fee, + const signedTx: StdTx = { + msg: [theMsg], + fee: fee, memo: memo, signatures: [signature], }; - const postableBytes = marshalTx(tx); + const postableBytes = marshalTx(signedTx); const result = await client.postTx(postableBytes); // console.log("Raw log:", result.raw_log); expect(result.code).toBeFalsy(); @@ -136,14 +122,14 @@ describe("RestClient", () => { value: { sender: faucetAddress, wasm_byte_code: contract.data, - source: "https://mycoderepo.example/134", - builder: "v0.0.1", + source: "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm", + builder: "cosmwasm-opt:0.6.2", }, }; const fee: StdFee = { amount: [ { - amount: "5000", + amount: "5000000", denom: "ucosm", }, ], @@ -156,20 +142,14 @@ describe("RestClient", () => { const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256); const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature); - const tx: StdTx = { + const signedTx: StdTx = { msg: [theMsg], fee: fee, memo: memo, signatures: [signature], }; - // make sure this is a valid encoding/decoding - const aminoBytes = await client.encodeTx(tx); - expect(aminoBytes).toBeTruthy(); - expect(aminoBytes.length).toEqual(63084); - - // now submit it - const postableBytes = marshalTx(tx); + const postableBytes = marshalTx(signedTx); const result = await client.postTx(postableBytes); // console.log("Raw log:", result.raw_log); expect(result.code).toBeFalsy(); diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index 69a1f7a6..2ed63061 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,5 +1,4 @@ import { Msg, NonceInfo, StdFee, StdSignature, StdTx } from "./types"; -export declare function sortJson(json: any): any; export declare function marshalTx(tx: StdTx): Uint8Array; export declare function makeSignBytes( msgs: readonly Msg[], From 8f0509e11ea703da5341f5b4426a17c0be05df6d Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 15:58:13 +0100 Subject: [PATCH 13/14] Add support for parsing MsgStoreCode in BCP --- packages/bcp/src/cosmwasmconnection.ts | 17 ++++++++++--- packages/bcp/src/decode.ts | 34 +++++++++++++++----------- packages/bcp/types/decode.d.ts | 3 +-- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index 21b65fe4..a1f1d56d 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { RestClient, TxsResponse, unmarshalTx } from "@cosmwasm/sdk"; +import { RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -305,8 +305,19 @@ export class CosmWasmConnection implements BlockchainConnection { response: TxsResponse, chainId: ChainId, ): Promise | FailedTransaction> { - const sender = (response.tx.value as any).msg[0].value.from_address; - const accountForHeight = await this.restClient.authAccounts(sender, response.height); + const firstMsg = response.tx.value.msg.find(() => true); + if (!firstMsg) throw new Error("Got transaction without a first message. What is going on here?"); + + let senderAddress: string; + if (types.isMsgSend(firstMsg)) { + senderAddress = firstMsg.value.from_address; + } else if (types.isMsgStoreCode(firstMsg)) { + senderAddress = firstMsg.value.sender; + } else { + throw new Error(`Got unsupported type of message: ${firstMsg.type}`); + } + + const accountForHeight = await this.restClient.authAccounts(senderAddress, response.height); // this is technically not the proper nonce. maybe this causes issues for sig validation? // leaving for now unless it causes issues const sequence = (accountForHeight.result.value.sequence - 1) as Nonce; diff --git a/packages/bcp/src/decode.ts b/packages/bcp/src/decode.ts index af83599a..77b3eb30 100644 --- a/packages/bcp/src/decode.ts +++ b/packages/bcp/src/decode.ts @@ -72,21 +72,27 @@ export function decodeAmount(tokens: TokenInfos, coin: types.Coin): Amount { }; } -export function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): SendTransaction { - if (!types.isMsgSend(msg)) { - throw new Error("Unknown message type in transaction"); +export function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): UnsignedTransaction { + if (types.isMsgSend(msg)) { + if (msg.value.amount.length !== 1) { + throw new Error("Only MsgSend with one amount is supported"); + } + const send: SendTransaction = { + kind: "bcp/send", + chainId: chainId, + sender: msg.value.from_address as Address, + recipient: msg.value.to_address as Address, + amount: decodeAmount(tokens, msg.value.amount[0]), + }; + return send; + } else { + // Unknown transaction type + const unknown = { + chainId: chainId, + kind: "bcp/unknown", + }; + return unknown; } - const msgValue = msg.value; - if (msgValue.amount.length !== 1) { - throw new Error("Only MsgSend with one amount is supported"); - } - return { - kind: "bcp/send", - chainId: chainId, - sender: msgValue.from_address as Address, - recipient: msgValue.to_address as Address, - amount: decodeAmount(tokens, msgValue.amount[0]), - }; } export function parseFee(fee: types.StdFee, tokens: TokenInfos): Fee { diff --git a/packages/bcp/types/decode.d.ts b/packages/bcp/types/decode.d.ts index 2fb8dcab..80de6596 100644 --- a/packages/bcp/types/decode.d.ts +++ b/packages/bcp/types/decode.d.ts @@ -7,7 +7,6 @@ import { FullSignature, Nonce, PubkeyBundle, - SendTransaction, SignatureBytes, SignedTransaction, UnsignedTransaction, @@ -19,7 +18,7 @@ export declare function decodeSignature(signature: string): SignatureBytes; export declare function decodeFullSignature(signature: types.StdSignature, nonce: number): FullSignature; export declare function coinToDecimal(tokens: TokenInfos, coin: types.Coin): readonly [Decimal, string]; export declare function decodeAmount(tokens: TokenInfos, coin: types.Coin): Amount; -export declare function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): SendTransaction; +export declare function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): UnsignedTransaction; export declare function parseFee(fee: types.StdFee, tokens: TokenInfos): Fee; export declare function parseTx( txValue: types.StdTx, From 7741e5711aa14655c13a9eeac26e44f24e84c2c5 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 4 Feb 2020 16:43:38 +0100 Subject: [PATCH 14/14] Parse and test logs --- packages/sdk/src/logs.spec.ts | 124 ++++++++++++++++++++++++++++ packages/sdk/src/logs.ts | 59 +++++++++++++ packages/sdk/src/restclient.spec.ts | 9 ++ packages/sdk/types/logs.d.ts | 17 ++++ 4 files changed, 209 insertions(+) create mode 100644 packages/sdk/src/logs.spec.ts create mode 100644 packages/sdk/src/logs.ts create mode 100644 packages/sdk/types/logs.d.ts diff --git a/packages/sdk/src/logs.spec.ts b/packages/sdk/src/logs.spec.ts new file mode 100644 index 00000000..a34efd66 --- /dev/null +++ b/packages/sdk/src/logs.spec.ts @@ -0,0 +1,124 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { parseAttribute, parseEvent, parseLog, parseLogs } from "./logs"; + +describe("logs", () => { + describe("parseAttribute", () => { + it("works", () => { + const attr = parseAttribute({ key: "a", value: "b" }); + expect(attr).toEqual({ key: "a", value: "b" }); + }); + }); + + describe("parseEvent", () => { + it("works", () => { + const original = { + type: "message", + attributes: [ + { + key: "action", + value: "store-code", + }, + { + key: "module", + value: "wasm", + }, + { + key: "action", + value: "store-code", + }, + { + key: "sender", + value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + { + key: "code_id", + value: "1", + }, + ], + } as const; + + const event = parseEvent(original); + expect(event).toEqual(original); + }); + }); + + describe("parseLog", () => { + it("works", () => { + const original = { + msg_index: 0, + log: "", + events: [ + { + type: "message", + attributes: [ + { + key: "action", + value: "store-code", + }, + { + key: "module", + value: "wasm", + }, + { + key: "action", + value: "store-code", + }, + { + key: "sender", + value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + { + key: "code_id", + value: "1", + }, + ], + }, + ], + } as const; + + const log = parseLog(original); + expect(log).toEqual(original); + }); + }); + + describe("parseLogs", () => { + it("works", () => { + const original = [ + { + msg_index: 0, + log: "", + events: [ + { + type: "message", + attributes: [ + { + key: "action", + value: "store-code", + }, + { + key: "module", + value: "wasm", + }, + { + key: "action", + value: "store-code", + }, + { + key: "sender", + value: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + }, + { + key: "code_id", + value: "1", + }, + ], + }, + ], + }, + ] as const; + + const logs = parseLogs(original); + expect(logs).toEqual(original); + }); + }); +}); diff --git a/packages/sdk/src/logs.ts b/packages/sdk/src/logs.ts new file mode 100644 index 00000000..4c822dc4 --- /dev/null +++ b/packages/sdk/src/logs.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { isNonNullObject } from "@iov/encoding"; + +export interface Attribute { + readonly key: string; + readonly value: string; +} + +export interface Event { + readonly type: "message"; + readonly attributes: readonly Attribute[]; +} + +export interface Log { + readonly msg_index: number; + readonly log: string; + readonly events: readonly Event[]; +} + +export function parseAttribute(input: unknown): Attribute { + if (!isNonNullObject(input)) throw new Error("Attribute must be a non-null object"); + const { key, value } = input as any; + if (typeof key !== "string" || typeof value !== "string") { + throw new Error("Attribute is not a key/value pair"); + } + return { + key: key, + value: value, + }; +} + +export function parseEvent(input: unknown): Event { + if (!isNonNullObject(input)) throw new Error("Event must be a non-null object"); + const { type, attributes } = input as any; + if (type !== "message") throw new Error("Event must be of type message"); + if (!Array.isArray(attributes)) throw new Error("Event's attributes must be an array"); + return { + type: type, + attributes: attributes.map(parseAttribute), + }; +} + +export function parseLog(input: unknown): Log { + if (!isNonNullObject(input)) throw new Error("Log must be a non-null object"); + const { msg_index, log, events } = input as any; + if (typeof msg_index !== "number") throw new Error("Log's msg_index must be a number"); + if (typeof log !== "string") throw new Error("Log's log must be a string"); + if (!Array.isArray(events)) throw new Error("Log's events must be an array"); + return { + msg_index: msg_index, + log: log, + events: events.map(parseEvent), + }; +} + +export function parseLogs(input: unknown): readonly Log[] { + if (!Array.isArray(input)) throw new Error("Logs must be an array"); + return input.map(parseLog); +} diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index ade652b4..5b516e7c 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -4,6 +4,7 @@ import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol"; import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; +import { Log, parseLogs } from "./logs"; import { RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import data from "./testdata/cosmoshub.json"; @@ -25,6 +26,11 @@ function pendingWithoutCosmos(): void { } } +function parseSuccess(rawLog?: string): readonly Log[] { + if (!rawLog) throw new Error("Log missing"); + return parseLogs(JSON.parse(rawLog)); +} + describe("RestClient", () => { it("can be constructed", () => { const client = new RestClient(httpUrl); @@ -153,6 +159,9 @@ describe("RestClient", () => { const result = await client.postTx(postableBytes); // console.log("Raw log:", result.raw_log); expect(result.code).toBeFalsy(); + const [firstLog] = parseSuccess(result.raw_log); + const codeIdAttr = firstLog.events[0].attributes.find(attr => attr.key === "code_id"); + expect(codeIdAttr).toEqual({ key: "code_id", value: "1" }); }); }); }); diff --git a/packages/sdk/types/logs.d.ts b/packages/sdk/types/logs.d.ts new file mode 100644 index 00000000..159ce322 --- /dev/null +++ b/packages/sdk/types/logs.d.ts @@ -0,0 +1,17 @@ +export interface Attribute { + readonly key: string; + readonly value: string; +} +export interface Event { + readonly type: "message"; + readonly attributes: readonly Attribute[]; +} +export interface Log { + readonly msg_index: number; + readonly log: string; + readonly events: readonly Event[]; +} +export declare function parseAttribute(input: unknown): Attribute; +export declare function parseEvent(input: unknown): Event; +export declare function parseLog(input: unknown): Log; +export declare function parseLogs(input: unknown): readonly Log[];