From c67ba2c1392b537798c74da843bb670b6e67235c Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 11:35:13 +0100 Subject: [PATCH 01/13] Use docker image from env in generate_template.sh --- scripts/cosm/generate_template.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/cosm/generate_template.sh b/scripts/cosm/generate_template.sh index b9550409..65009205 100755 --- a/scripts/cosm/generate_template.sh +++ b/scripts/cosm/generate_template.sh @@ -2,11 +2,10 @@ set -o errexit -o nounset -o pipefail command -v shellcheck > /dev/null && shellcheck "$0" -# Choose from https://hub.docker.com/r/cosmwasm/wasmd/tags -REPOSITORY="cosmwasm/wasmd" -VERSION="manual" - SCRIPT_DIR="$(realpath "$(dirname "$0")")" +# shellcheck source=./env +# shellcheck disable=SC1091 +source "$SCRIPT_DIR"/env rm -rf "$SCRIPT_DIR/template" mkdir "$SCRIPT_DIR/template" From 051e87dda61aa4f8eb7c748905e425ac9772de3e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 11:35:31 +0100 Subject: [PATCH 02/13] Only sudo chown if necessary --- scripts/cosm/generate_template.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/cosm/generate_template.sh b/scripts/cosm/generate_template.sh index 65009205..d6f79123 100755 --- a/scripts/cosm/generate_template.sh +++ b/scripts/cosm/generate_template.sh @@ -18,5 +18,8 @@ docker run --rm \ ./setup.sh \ cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 -# this is created as root, let's make it ours -sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template" +# The ./template folder is created by the docker daemon's user (root on Linux, current user +# when using Docker Desktop on macOS), let's make it ours if needed +if [ ! -x "$SCRIPT_DIR/template/.wasmd/config/gentx" ]; then + sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template" +fi From 21936da8261327291893cb359803dab6ec5c0443 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 11:38:56 +0100 Subject: [PATCH 03/13] Add unused account --- scripts/cosm/README.md | 9 +++++++++ scripts/cosm/deploy_erc20.js | 5 +++++ scripts/cosm/generate_template.sh | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/cosm/README.md b/scripts/cosm/README.md index 13c16ea5..07ea4583 100644 --- a/scripts/cosm/README.md +++ b/scripts/cosm/README.md @@ -78,3 +78,12 @@ You should get output matching the following: threshold: 0 pubkeys: [] ``` + +## Preset accounts + +1. Faucet
+ economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone
+ cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 +2. Unused: for testing account state; this account never changes balances or nonces
+ oyster design unusual machine spread century engine gravity focus cave carry slot
+ cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u diff --git a/scripts/cosm/deploy_erc20.js b/scripts/cosm/deploy_erc20.js index 9a6791d6..6199806f 100755 --- a/scripts/cosm/deploy_erc20.js +++ b/scripts/cosm/deploy_erc20.js @@ -26,6 +26,7 @@ const defaultFee = { const faucetMnemonic = "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone"; const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; +const unusedAccount = "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u"; async function uploadContract(client, pen, wasm) { const memo = "Upload ERC20 contract"; @@ -96,6 +97,10 @@ async function main() { address: faucetAddress, amount: "11", }, + { + address: unusedAccount, + amount: "12812345", + }, ], }; const instantiationResult = await instantiateContract(client, pen, codeId, initMsg); diff --git a/scripts/cosm/generate_template.sh b/scripts/cosm/generate_template.sh index d6f79123..9a448adc 100755 --- a/scripts/cosm/generate_template.sh +++ b/scripts/cosm/generate_template.sh @@ -10,13 +10,13 @@ source "$SCRIPT_DIR"/env rm -rf "$SCRIPT_DIR/template" mkdir "$SCRIPT_DIR/template" -# any any more addresses you want to fund in genesis below +# The usage of the accounts below is documented in README.md of this directory docker run --rm \ -e PASSWORD=my-secret-password \ --mount type=bind,source="$SCRIPT_DIR/template",target=/root \ "$REPOSITORY:$VERSION" \ ./setup.sh \ - cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 + cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u # The ./template folder is created by the docker daemon's user (root on Linux, current user # when using Docker Desktop on macOS), let's make it ours if needed From 94a198bd93f12d44749838121bb671026a527ac4 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 12:20:56 +0100 Subject: [PATCH 04/13] Regenerate template --- ...t5peka2zgd8ucnfsxeqkwkffhccwx4ch6w.address | 1 - ...v8h6a75z9zdde7cmxv4fdz75appy7h5wvg.address | 1 + scripts/cosm/template/.wasmcli/keyhash | 2 +- scripts/cosm/template/.wasmcli/validator.info | 2 +- .../cosm/template/.wasmd/config/genesis.json | 229 ++++++++++-------- ...89558533ad6df13f96bfb7c8ae44b457a919a.json | 1 + ...ec95e305b18861b32f69c11e2d0236d01c9e8.json | 1 - .../cosm/template/.wasmd/config/node_key.json | 2 +- .../.wasmd/config/priv_validator_key.json | 6 +- 9 files changed, 132 insertions(+), 113 deletions(-) delete mode 100644 scripts/cosm/template/.wasmcli/cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w.address create mode 100644 scripts/cosm/template/.wasmcli/cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg.address create mode 100644 scripts/cosm/template/.wasmd/config/gentx/gentx-67289558533ad6df13f96bfb7c8ae44b457a919a.json delete mode 100644 scripts/cosm/template/.wasmd/config/gentx/gentx-c40ec95e305b18861b32f69c11e2d0236d01c9e8.json diff --git a/scripts/cosm/template/.wasmcli/cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w.address b/scripts/cosm/template/.wasmcli/cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w.address deleted file mode 100644 index 48126ec8..00000000 --- a/scripts/cosm/template/.wasmcli/cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w.address +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNzA4NjQ4OSArMDAwMCBVVEMgbT0rMC4yMjM1NjMwMDAiLCJlbmMiOiJBMjU2R0NNIiwicDJjIjo4MTkyLCJwMnMiOiJmU2Q5OUVVUldWQW9EY0Z5In0.KuQ7PWpuxAAjkdWw6e9IUPi_o3Ud-L_MhTNQ5NNwI1MFxvc0Jg__Bg.y7kp74vcKuEgrxUa.pLhY4Qup_jmjSpWjJN0NSJ84IMdhpyOT-IOFfdjNvvihg3ohZWFROrLP1LzZ9FINwbnFMqrmIxgxbrNMOH45U1OahlaswRUP8eVcbF4E4ZF-ZfpYEpCClNG41T-cBV2SzMySkdYAv_u-FJ4_b66nfJ7wYkfOJrff5e8g-FDlIe90PBrGR6c6YLr0XOH6X9uZVF3mWFfYc_jxKT_uoJMcbkefOEPr0W3mVFc-RAvaQ54Az6n_o1tOC6iQBoZ2PHc.I5HjgFmEZwtYqYQfM7VnHg \ No newline at end of file diff --git a/scripts/cosm/template/.wasmcli/cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg.address b/scripts/cosm/template/.wasmcli/cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg.address new file mode 100644 index 00000000..60300308 --- /dev/null +++ b/scripts/cosm/template/.wasmcli/cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg.address @@ -0,0 +1 @@ +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNjg2NzQ1ICswMDAwIFVUQyBtPSswLjIyNTA4MDAwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6ImR3S2hTZDJfT1c4UDkyY00ifQ._x85VK6XkQ6XVU4zoSEEjAtMO7qCoSGWiVIo0OJtbksUCWsYhbRPTg.09Qg67smHfoMlScZ.YDYvL193V0G2u9fuJYF-1CSykfctJv8VFpQR3eYroPT233CQI9uXb2KUAK0lP_4AIrDREvkVv1CWQ3Wa0WTGSrOFepIB2X3AFGAf2gw8OsZybdsRiN2Y__7Ljmo7rNjMur9L53fiY7Y4eN83oP9034FovfByDeAL85Lwc0r1Jbf9u4wEB4QudtlFGjfbgfUw4MBDImpmI1dPfnw_1izqWgvlbDlpAzQUALo90gCHtwuCOsVgpCNeFOci5eV60LA.kNLZneL-i5Dzi8Xhi8bU_w \ No newline at end of file diff --git a/scripts/cosm/template/.wasmcli/keyhash b/scripts/cosm/template/.wasmcli/keyhash index df29f36c..9b1c2dc6 100755 --- a/scripts/cosm/template/.wasmcli/keyhash +++ b/scripts/cosm/template/.wasmcli/keyhash @@ -1 +1 @@ -$2a$10$vAg6eRcBB2poo3HKW0wpreHFth9sb9oYoFskLYc9H39ApJiPsGriG \ No newline at end of file +$2a$10$wE2S5ENI/eoNUjFTtNCisOmJWW0h0yIVHBr1CjlrDzcCDBRozAZqO \ No newline at end of file diff --git a/scripts/cosm/template/.wasmcli/validator.info b/scripts/cosm/template/.wasmcli/validator.info index 171aae17..dbfdf11a 100644 --- a/scripts/cosm/template/.wasmcli/validator.info +++ b/scripts/cosm/template/.wasmcli/validator.info @@ -1 +1 @@ -eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNjI2NzMwNDUgKzAwMDAgVVRDIG09KzAuMjE1MzcxMTY3IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiLUNHTldlMFg4bjEwZDl1VyJ9.Cxq-oR7LM1CmAaNO6O0nihb4f-4FFY6qnW-XGO3Trbq9694n4LFBlw.da-kCbllD1_XoMHF.oiuts-8U9mWmJs9xOnWC0NJabUM4FRgSnHKgBce3XzhdSnrhODbbaKkR9EhZFHNWw_h1o27ZxeEtHmPyqv-A5lz4zwwbapi1g7qcZhQW_dI0_4yJ16U5AMdvo7PH5lWXK9z6H0ReG8CIW5aw_CrQBd4egjyGMxQVAABOFAhQ747KGGu76L5vIpfi2b7wJx_z7gS1x6PNSHHR7KOvgQ9hqG6B5VkjPo85JdyRRz00jJec88JXutvdKVbpvVldB8BGsURHFVyYvR3Nj0a7daSroxxkk63T1pZTLIPncYn-XFruKTJE3xmzAu-ojjB1VevGp0dQ8drWcNE_D2nphXP3PLdd-zhfpNkIWfSB8Kh1geeK9xFi.XXG7ekj8VeF6RZaLbTsH0w \ No newline at end of file +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNDgzNjkzICswMDAwIFVUQyBtPSswLjIwNDc3NjcwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6IkRfU1A3Ni1zU3lCRkY0cUQifQ.CPLPgBUrK53I4uLXRR7ba78yQlfio1QI6xedzWjCnTlKEUIdso1c7g.SvJq7pwz3Z86LrNU.03eoFsTiIAfHa2XH14Rgh7bvUnzkH_q4ljLyweN93GVIQIgWjqhRXzaf3ZdZ34i5H0TIs9xr7LcvbttvsUpetw1GjujFboY6hDWhMD0hOE67NysQPIYIsIbC76y5O5_Q6HVZ14vxuEbxgF8qJjGUnpAwqoNwUDBQr8Nju8ZpcAt9Y9VGDw-wiYS3TuYLEED84XQuUwWAIbQNbqvRaY6ZuVtL30-j1cVpy6AyuHmKlFS5L7ddB64eQfni9LErc2VqTnBZypuuaJ1CuGwL1gM0cQrtpRXM-rmSFvu0nXciDqJ2bIUa3qBwULtnBaVqSSAkrj-DgTbHPWhX7RyJoVObEqtQ_XRrB252aKj5HudlYjUThE3O.JWWfqTMVbUQpqUTfepEixA \ No newline at end of file diff --git a/scripts/cosm/template/.wasmd/config/genesis.json b/scripts/cosm/template/.wasmd/config/genesis.json index 9adf048a..c217021d 100644 --- a/scripts/cosm/template/.wasmd/config/genesis.json +++ b/scripts/cosm/template/.wasmd/config/genesis.json @@ -1,5 +1,5 @@ { - "genesis_time": "2020-01-30T20:58:17.838935022Z", + "genesis_time": "2020-02-09T11:05:31.7520515Z", "chain_id": "testing", "consensus_params": { "block": { @@ -19,18 +19,25 @@ }, "app_hash": "", "app_state": { - "slashing": { + "distribution": { "params": { - "signed_blocks_window": "100", - "min_signed_per_window": "0.500000000000000000", - "downtime_jail_duration": "600000000000", - "slash_fraction_double_sign": "0.050000000000000000", - "slash_fraction_downtime": "0.010000000000000000" + "community_tax": "0.020000000000000000", + "base_proposer_reward": "0.010000000000000000", + "bonus_proposer_reward": "0.040000000000000000", + "withdraw_addr_enabled": true }, - "signing_infos": {}, - "missed_blocks": {} + "fee_pool": { + "community_pool": [] + }, + "delegator_withdraw_infos": [], + "previous_proposer": "", + "outstanding_rewards": [], + "validator_accumulated_commissions": [], + "validator_historical_rewards": [], + "validator_current_rewards": [], + "delegator_starting_infos": [], + "validator_slash_events": [] }, - "params": null, "gov": { "starting_proposal_id": "1", "deposits": null, @@ -54,12 +61,96 @@ "veto": "0.334000000000000000" } }, + "slashing": { + "params": { + "signed_blocks_window": "100", + "min_signed_per_window": "0.500000000000000000", + "downtime_jail_duration": "600000000000", + "slash_fraction_double_sign": "0.050000000000000000", + "slash_fraction_downtime": "0.010000000000000000" + }, + "signing_infos": {}, + "missed_blocks": {} + }, + "supply": { + "supply": [] + }, + "wasm": { + "codes": null, + "contracts": null + }, + "mint": { + "minter": { + "inflation": "0.130000000000000000", + "annual_provisions": "0.000000000000000000" + }, + "params": { + "mint_denom": "ustake", + "inflation_rate_change": "0.130000000000000000", + "inflation_max": "0.200000000000000000", + "inflation_min": "0.070000000000000000", + "goal_bonded": "0.670000000000000000", + "blocks_per_year": "6311520" + } + }, + "genutil": { + "gentxs": [ + { + "type": "cosmos-sdk/StdTx", + "value": { + "msg": [ + { + "type": "cosmos-sdk/MsgCreateValidator", + "value": { + "description": { + "moniker": "testing", + "identity": "", + "website": "", + "security_contact": "", + "details": "" + }, + "commission": { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.010000000000000000" + }, + "min_self_delegation": "1", + "delegator_address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg", + "validator_address": "cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm", + "pubkey": "cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88", + "value": { + "denom": "ustake", + "amount": "250000000" + } + } + } + ], + "fee": { + "amount": [], + "gas": "200000" + }, + "signatures": [ + { + "pub_key": { + "type": "tendermint/PubKeySecp256k1", + "value": "AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ" + }, + "signature": "+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A==" + } + ], + "memo": "67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656" + } + } + ] + }, "evidence": { "params": { "max_evidence_age": "120000000000" }, "evidence": [] }, + "params": null, + "upgrade": {}, "staking": { "params": { "unbonding_time": "1814400000000000", @@ -76,35 +167,6 @@ "redelegations": null, "exported": false }, - "distribution": { - "params": { - "community_tax": "0.020000000000000000", - "base_proposer_reward": "0.010000000000000000", - "bonus_proposer_reward": "0.040000000000000000", - "withdraw_addr_enabled": true - }, - "fee_pool": { - "community_pool": [] - }, - "delegator_withdraw_infos": [], - "previous_proposer": "", - "outstanding_rewards": [], - "validator_accumulated_commissions": [], - "validator_historical_rewards": [], - "validator_current_rewards": [], - "delegator_starting_infos": [], - "validator_slash_events": [] - }, - "bank": { - "send_enabled": true - }, - "crisis": { - "constant_fee": { - "denom": "ustake", - "amount": "1000" - } - }, - "upgrade": {}, "auth": { "params": { "max_memo_characters": "256", @@ -117,7 +179,7 @@ { "type": "cosmos-sdk/Account", "value": { - "address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w", + "address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg", "coins": [ { "denom": "ucosm", @@ -151,79 +213,36 @@ "account_number": 0, "sequence": 0 } - } - ] - }, - "mint": { - "minter": { - "inflation": "0.130000000000000000", - "annual_provisions": "0.000000000000000000" - }, - "params": { - "mint_denom": "ustake", - "inflation_rate_change": "0.130000000000000000", - "inflation_max": "0.200000000000000000", - "inflation_min": "0.070000000000000000", - "goal_bonded": "0.670000000000000000", - "blocks_per_year": "6311520" - } - }, - "wasm": { - "codes": null, - "contracts": null - }, - "supply": { - "supply": [] - }, - "genutil": { - "gentxs": [ + }, { - "type": "cosmos-sdk/StdTx", + "type": "cosmos-sdk/Account", "value": { - "msg": [ + "address": "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", + "coins": [ { - "type": "cosmos-sdk/MsgCreateValidator", - "value": { - "description": { - "moniker": "testing", - "identity": "", - "website": "", - "security_contact": "", - "details": "" - }, - "commission": { - "rate": "0.100000000000000000", - "max_rate": "0.200000000000000000", - "max_change_rate": "0.010000000000000000" - }, - "min_self_delegation": "1", - "delegator_address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w", - "validator_address": "cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka", - "pubkey": "cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9", - "value": { - "denom": "ustake", - "amount": "250000000" - } - } + "denom": "ucosm", + "amount": "1000000000" + }, + { + "denom": "ustake", + "amount": "1000000000" } ], - "fee": { - "amount": [], - "gas": "200000" - }, - "signatures": [ - { - "pub_key": { - "type": "tendermint/PubKeySecp256k1", - "value": "AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH" - }, - "signature": "zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA==" - } - ], - "memo": "c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656" + "public_key": "", + "account_number": 0, + "sequence": 0 } } ] + }, + "crisis": { + "constant_fee": { + "denom": "ustake", + "amount": "1000" + } + }, + "bank": { + "send_enabled": true } } } \ No newline at end of file diff --git a/scripts/cosm/template/.wasmd/config/gentx/gentx-67289558533ad6df13f96bfb7c8ae44b457a919a.json b/scripts/cosm/template/.wasmd/config/gentx/gentx-67289558533ad6df13f96bfb7c8ae44b457a919a.json new file mode 100644 index 00000000..5a90e9e6 --- /dev/null +++ b/scripts/cosm/template/.wasmd/config/gentx/gentx-67289558533ad6df13f96bfb7c8ae44b457a919a.json @@ -0,0 +1 @@ +{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg","validator_address":"cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm","pubkey":"cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ"},"signature":"+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A=="}],"memo":"67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656"}} diff --git a/scripts/cosm/template/.wasmd/config/gentx/gentx-c40ec95e305b18861b32f69c11e2d0236d01c9e8.json b/scripts/cosm/template/.wasmd/config/gentx/gentx-c40ec95e305b18861b32f69c11e2d0236d01c9e8.json deleted file mode 100644 index 37cd5a85..00000000 --- a/scripts/cosm/template/.wasmd/config/gentx/gentx-c40ec95e305b18861b32f69c11e2d0236d01c9e8.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w","validator_address":"cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka","pubkey":"cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH"},"signature":"zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA=="}],"memo":"c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656"}} diff --git a/scripts/cosm/template/.wasmd/config/node_key.json b/scripts/cosm/template/.wasmd/config/node_key.json index 36640502..d380c3bc 100644 --- a/scripts/cosm/template/.wasmd/config/node_key.json +++ b/scripts/cosm/template/.wasmd/config/node_key.json @@ -1 +1 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"G0VvywcXFSI5HASlbKRK/vAI2NNolDw1P/2fgWtfva/P8L9yiw2luZfu6cKbijEg/op2lOqV3CbfMo+B1P6G3w=="}} \ No newline at end of file +{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"i42pVrwetpGZFC78UUNhL6Bk41/N3sKDW9XKNz+IOm/JX5aN10vUrpA52DXOQNug55lTvTyuPR8izLSBcovIrg=="}} \ No newline at end of file diff --git a/scripts/cosm/template/.wasmd/config/priv_validator_key.json b/scripts/cosm/template/.wasmd/config/priv_validator_key.json index f268441e..1a4b6f20 100644 --- a/scripts/cosm/template/.wasmd/config/priv_validator_key.json +++ b/scripts/cosm/template/.wasmd/config/priv_validator_key.json @@ -1,11 +1,11 @@ { - "address": "9CBD80593D47022DFE9A0356F350A4D233E92AEB", + "address": "3FBF50B72FE062495F150AEB78D1981E7DAEBE60", "pub_key": { "type": "tendermint/PubKeyEd25519", - "value": "tfkKoKWpnpcNBhjAXUTA4i9oMs+EXOlujriy/2Jz29o=" + "value": "ff4Kip9dNfI/3PFdFkdlRQu4Ptb3yWnQDJ1OrXoHKW8=" }, "priv_key": { "type": "tendermint/PrivKeyEd25519", - "value": "NkIf2Dije6K8xOqZ7ni+f3+TDjuOrV5Q68g0coD8j6O1+Qqgpamelw0GGMBdRMDiL2gyz4Rc6W6OuLL/YnPb2g==" + "value": "yMKZJArmVw5zXDTHbYR0sNRqugzW3HNbO6yK5bOHYBp9/gqKn1018j/c8V0WR2VFC7g+1vfJadAMnU6tegcpbw==" } } \ No newline at end of file From a22f035c9492889dea940560b65ad8dde6b0057d Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:05:07 +0100 Subject: [PATCH 05/13] Test full authAccounts return value --- packages/sdk/src/restclient.spec.ts | 29 ++++++++++++++++++++++++----- packages/sdk/src/restclient.ts | 1 + packages/sdk/types/restclient.d.ts | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index a093c0f1..9a8b9a29 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -29,6 +29,9 @@ const faucetMnemonic = "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone"; const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k"; +const unusedAccount = { + address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", +}; function pendingWithoutCosmos(): void { if (!process.env.COSMOS_ENABLED) { @@ -188,13 +191,29 @@ describe("RestClient", () => { }); describe("authAccounts", () => { - it("works", async () => { + it("works for unused account without pubkey", async () => { pendingWithoutCosmos(); const client = new RestClient(httpUrl); - const { result } = await client.authAccounts(faucetAddress); - const account = result.value; - expect(account.account_number).toEqual(4); - expect(account.sequence).toBeGreaterThanOrEqual(0); + const { result } = await client.authAccounts(unusedAccount.address); + expect(result).toEqual({ + type: "cosmos-sdk/Account", + value: { + address: unusedAccount.address, + public_key: "", // not known to the chain + coins: [ + { + amount: "1000000000", + denom: "ucosm", + }, + { + amount: "1000000000", + denom: "ustake", + }, + ], + account_number: 5, + sequence: 0, + }, + }); }); }); diff --git a/packages/sdk/src/restclient.ts b/packages/sdk/src/restclient.ts index 29e17cc8..aa44cdd1 100644 --- a/packages/sdk/src/restclient.ts +++ b/packages/sdk/src/restclient.ts @@ -37,6 +37,7 @@ interface BlocksResponse { interface AuthAccountsResponse { readonly result: { + readonly type: "cosmos-sdk/Account"; readonly value: BaseAccount; }; } diff --git a/packages/sdk/types/restclient.d.ts b/packages/sdk/types/restclient.d.ts index d0c8f9d3..f6ab8a1c 100644 --- a/packages/sdk/types/restclient.d.ts +++ b/packages/sdk/types/restclient.d.ts @@ -26,6 +26,7 @@ interface BlocksResponse { } interface AuthAccountsResponse { readonly result: { + readonly type: "cosmos-sdk/Account"; readonly value: BaseAccount; }; } From 34c0f1e18f9a5c217e8a4ce3a504c9fb0f8999fa Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:08:28 +0100 Subject: [PATCH 06/13] Rename type to CosmosSdkAccount --- packages/sdk/src/restclient.ts | 4 ++-- packages/sdk/src/types.ts | 6 +++--- packages/sdk/types/restclient.d.ts | 4 ++-- packages/sdk/types/types.d.ts | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/sdk/src/restclient.ts b/packages/sdk/src/restclient.ts index aa44cdd1..632f0b5b 100644 --- a/packages/sdk/src/restclient.ts +++ b/packages/sdk/src/restclient.ts @@ -1,7 +1,7 @@ import { Encoding } from "@iov/encoding"; import axios, { AxiosInstance } from "axios"; -import { AminoTx, BaseAccount, CodeInfo, ContractInfo, isAminoStdTx, StdTx, WasmData } from "./types"; +import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, isAminoStdTx, StdTx, WasmData } from "./types"; const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding; @@ -38,7 +38,7 @@ interface BlocksResponse { interface AuthAccountsResponse { readonly result: { readonly type: "cosmos-sdk/Account"; - readonly value: BaseAccount; + readonly value: CosmosSdkAccount; }; } diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 5dfd60aa..d9ac9998 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -151,7 +151,7 @@ export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType. // bech32-encoded amino-binary encoded PubKey interface. oof. export type Bech32PubKey = string; -export interface BaseAccount { +export interface CosmosSdkAccount { /** Bech32 account address */ readonly address: string; readonly coins: ReadonlyArray; @@ -160,8 +160,8 @@ export interface BaseAccount { readonly sequence: number; } -/** The data we need from BaseAccount to create a nonce */ -export type NonceInfo = Pick; +/** The data we need from CosmosSdkAccount to create a nonce */ +export type NonceInfo = Pick; export interface CodeInfo { readonly id: number; diff --git a/packages/sdk/types/restclient.d.ts b/packages/sdk/types/restclient.d.ts index f6ab8a1c..a7fbd87f 100644 --- a/packages/sdk/types/restclient.d.ts +++ b/packages/sdk/types/restclient.d.ts @@ -1,4 +1,4 @@ -import { AminoTx, BaseAccount, CodeInfo, ContractInfo, StdTx, WasmData } from "./types"; +import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, StdTx, WasmData } from "./types"; interface NodeInfo { readonly network: string; } @@ -27,7 +27,7 @@ interface BlocksResponse { interface AuthAccountsResponse { readonly result: { readonly type: "cosmos-sdk/Account"; - readonly value: BaseAccount; + readonly value: CosmosSdkAccount; }; } declare type WasmResponse = WasmSuccess | WasmError; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index c2d760a3..20b65f4d 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -110,7 +110,7 @@ export declare const pubkeyType: { }; export declare const pubkeyTypes: readonly string[]; export declare type Bech32PubKey = string; -export interface BaseAccount { +export interface CosmosSdkAccount { /** Bech32 account address */ readonly address: string; readonly coins: ReadonlyArray; @@ -118,8 +118,8 @@ export interface BaseAccount { readonly account_number: number; readonly sequence: number; } -/** The data we need from BaseAccount to create a nonce */ -export declare type NonceInfo = Pick; +/** The data we need from CosmosSdkAccount to create a nonce */ +export declare type NonceInfo = Pick; export interface CodeInfo { readonly id: number; /** Bech32 account address */ From ff78c296d439001e059dd32020c45037a9b753da Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:10:35 +0100 Subject: [PATCH 07/13] Collect faucet data in object --- packages/sdk/src/restclient.spec.ts | 42 +++++++++++++++-------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 9a8b9a29..9c20c438 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -25,9 +25,11 @@ const { fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding; const httpUrl = "http://localhost:1317"; const defaultNetworkId = "testing"; -const faucetMnemonic = - "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone"; -const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6"; +const faucet = { + mnemonic: + "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone", + address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", +}; const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k"; const unusedAccount = { address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u", @@ -83,7 +85,7 @@ async function uploadContract(client: RestClient, pen: Pen): Promise { describe("post", () => { it("can send tokens", async () => { pendingWithoutCosmos(); - const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); const memo = "My first contract on chain"; const theMsg: MsgSend = { type: "cosmos-sdk/MsgSend", value: { - from_address: faucetAddress, + from_address: faucet.address, to_address: emptyAddress, amount: [ { @@ -257,7 +259,7 @@ describe("RestClient", () => { }; const client = new RestClient(httpUrl); - const account = (await client.authAccounts(faucetAddress)).result.value; + const account = (await client.authAccounts(faucet.address)).result.value; const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account); const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes)); @@ -269,7 +271,7 @@ describe("RestClient", () => { it("can upload, instantiate and execute wasm", async () => { pendingWithoutCosmos(); - const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); const client = new RestClient(httpUrl); const transferAmount: readonly Coin[] = [ @@ -335,7 +337,7 @@ describe("RestClient", () => { describe("query", () => { it("can list upload code", async () => { pendingWithoutCosmos(); - const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); const client = new RestClient(httpUrl); // check with contracts were here first to compare @@ -355,17 +357,17 @@ describe("RestClient", () => { expect(newInfos.length).toEqual(numExisting + 1); const lastInfo = newInfos[newInfos.length - 1]; expect(lastInfo.id).toEqual(codeId); - expect(lastInfo.creator).toEqual(faucetAddress); + expect(lastInfo.creator).toEqual(faucet.address); // TODO: check code hash matches expectation - // expect(lastInfo.code_hash).toEqual(faucetAddress); + // expect(lastInfo.code_hash).toEqual(faucet.address); // TODO: download code and check against auto-gen }); it("can list contracts and get info", async () => { pendingWithoutCosmos(); - const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); const client = new RestClient(httpUrl); const beneficiaryAddress = makeRandomAddress(); const transferAmount: readonly Coin[] = [ @@ -409,7 +411,7 @@ describe("RestClient", () => { // check out info const myInfo = await client.getContractInfo(myAddress); expect(myInfo.code_id).toEqual(codeId); - expect(myInfo.creator).toEqual(faucetAddress); + expect(myInfo.creator).toEqual(faucet.address); expect((myInfo.init_msg as any).beneficiary).toEqual(beneficiaryAddress); // make sure random addresses don't give useful info @@ -478,7 +480,7 @@ describe("RestClient", () => { // we can query the verifier properly const verifier = await client.queryContractSmart(contractAddress, { verifier: {} }); - expect(verifier).toEqual(faucetAddress); + expect(verifier).toEqual(faucet.address); // invalid query syntax throws an error await client.queryContractSmart(contractAddress, { nosuchkey: {} }).then( From b2fcb0b1051a61a1c40c65b2dd15947395761dd8 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:16:54 +0100 Subject: [PATCH 08/13] Move decodeBech32Pubkey to pubkey.ts --- packages/sdk/src/address.spec.ts | 13 +------- packages/sdk/src/address.ts | 54 ++----------------------------- packages/sdk/src/index.ts | 4 +-- packages/sdk/src/pubkey.spec.ts | 13 +++++++- packages/sdk/src/pubkey.ts | 55 ++++++++++++++++++++++++++++++-- packages/sdk/types/address.d.ts | 3 +- packages/sdk/types/index.d.ts | 4 +-- packages/sdk/types/pubkey.d.ts | 3 +- 8 files changed, 75 insertions(+), 74 deletions(-) diff --git a/packages/sdk/src/address.spec.ts b/packages/sdk/src/address.spec.ts index 7c73ebaa..80df0b7a 100644 --- a/packages/sdk/src/address.spec.ts +++ b/packages/sdk/src/address.spec.ts @@ -1,21 +1,10 @@ import { Encoding } from "@iov/encoding"; -import { decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address"; +import { encodeAddress, isValidAddress } from "./address"; const { toBase64, fromHex } = Encoding; describe("address", () => { - describe("decodeBech32Pubkey", () => { - it("works", () => { - expect( - decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"), - ).toEqual({ - type: "tendermint/PubKeySecp256k1", - value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", - }); - }); - }); - describe("isValidAddress", () => { it("accepts valid addresses", () => { expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true); diff --git a/packages/sdk/src/address.ts b/packages/sdk/src/address.ts index 9f553d5c..85df61c5 100644 --- a/packages/sdk/src/address.ts +++ b/packages/sdk/src/address.ts @@ -1,10 +1,9 @@ import { Ripemd160, Sha256 } from "@iov/crypto"; import { Bech32, Encoding } from "@iov/encoding"; -import equal from "fast-deep-equal"; -import { Bech32PubKey, PubKey, pubkeyType } from "./types"; +import { PubKey, pubkeyType } from "./types"; -const { fromBase64, toBase64 } = Encoding; +const { fromBase64 } = Encoding; // TODO: make this much more configurable export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; @@ -15,55 +14,6 @@ function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBec return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix); } -function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix { - return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix); -} - -// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163 -// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography -// Last bytes is varint-encoded length prefix -const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721"); -const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420"); -const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005"); -const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; - -export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { - const { prefix, data } = Bech32.decode(bech); - if (!isCosmosPubkeyBech32Prefix(prefix)) { - throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`); - } - - const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength); - const rest = data.slice(pubkeyAminoPrefixLength); - if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) { - if (rest.length !== 33) { - throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey)."); - } - return { - type: pubkeyType.secp256k1, - value: toBase64(rest), - }; - } else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) { - if (rest.length !== 32) { - throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey)."); - } - return { - type: pubkeyType.ed25519, - value: toBase64(rest), - }; - } else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) { - if (rest.length !== 32) { - throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey)."); - } - return { - type: pubkeyType.sr25519, - value: toBase64(rest), - }; - } else { - throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix)); - } -} - export function isValidAddress(address: string): boolean { try { const { prefix, data } = Bech32.decode(address); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 1908af35..cbe754e4 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -2,9 +2,9 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address"; +export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { encodeSecp256k1Pubkey } from "./pubkey"; +export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; diff --git a/packages/sdk/src/pubkey.spec.ts b/packages/sdk/src/pubkey.spec.ts index 0b700496..2f0c6209 100644 --- a/packages/sdk/src/pubkey.spec.ts +++ b/packages/sdk/src/pubkey.spec.ts @@ -1,6 +1,6 @@ import { Encoding } from "@iov/encoding"; -import { encodeSecp256k1Pubkey } from "./pubkey"; +import { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; const { fromBase64 } = Encoding; @@ -24,4 +24,15 @@ describe("pubkey", () => { }); }); }); + + describe("decodeBech32Pubkey", () => { + it("works", () => { + expect( + decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"), + ).toEqual({ + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }); + }); + }); }); diff --git a/packages/sdk/src/pubkey.ts b/packages/sdk/src/pubkey.ts index 73b10695..23552860 100644 --- a/packages/sdk/src/pubkey.ts +++ b/packages/sdk/src/pubkey.ts @@ -1,7 +1,9 @@ import { Secp256k1 } from "@iov/crypto"; -import { Encoding } from "@iov/encoding"; +import { Bech32, Encoding } from "@iov/encoding"; +import equal from "fast-deep-equal"; -import { PubKey, pubkeyType } from "./types"; +import { CosmosPubkeyBech32Prefix } from "./address"; +import { Bech32PubKey, PubKey, pubkeyType } from "./types"; export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { return { @@ -9,3 +11,52 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { value: Encoding.toBase64(Secp256k1.compressPubkey(pubkey)), }; } + +function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix { + return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix); +} + +// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163 +// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography +// Last bytes is varint-encoded length prefix +const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721"); +const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420"); +const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005"); +const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; + +export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { + const { prefix, data } = Bech32.decode(bech); + if (!isCosmosPubkeyBech32Prefix(prefix)) { + throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`); + } + + const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength); + const rest = data.slice(pubkeyAminoPrefixLength); + if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) { + if (rest.length !== 33) { + throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey)."); + } + return { + type: pubkeyType.secp256k1, + value: Encoding.toBase64(rest), + }; + } else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) { + if (rest.length !== 32) { + throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey)."); + } + return { + type: pubkeyType.ed25519, + value: Encoding.toBase64(rest), + }; + } else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) { + if (rest.length !== 32) { + throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey)."); + } + return { + type: pubkeyType.sr25519, + value: Encoding.toBase64(rest), + }; + } else { + throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix)); + } +} diff --git a/packages/sdk/types/address.d.ts b/packages/sdk/types/address.d.ts index 4fddadd5..3390fc29 100644 --- a/packages/sdk/types/address.d.ts +++ b/packages/sdk/types/address.d.ts @@ -1,7 +1,6 @@ -import { Bech32PubKey, PubKey } from "./types"; +import { PubKey } from "./types"; export declare type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; export declare type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix; -export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey; export declare function isValidAddress(address: string): boolean; export declare function encodeAddress(pubkey: PubKey, prefix: string): string; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index abe78f64..0aaeec16 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,9 +1,9 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address"; +export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { encodeSecp256k1Pubkey } from "./pubkey"; +export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; diff --git a/packages/sdk/types/pubkey.d.ts b/packages/sdk/types/pubkey.d.ts index 72188ff7..3d7075df 100644 --- a/packages/sdk/types/pubkey.d.ts +++ b/packages/sdk/types/pubkey.d.ts @@ -1,2 +1,3 @@ -import { PubKey } from "./types"; +import { Bech32PubKey, PubKey } from "./types"; export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; +export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey; From af5e5a76a94a8c7f017c2a165fd76d8cc176a5b0 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:27:53 +0100 Subject: [PATCH 09/13] Add encodeBech32Pubkey --- packages/sdk/src/index.ts | 2 +- packages/sdk/src/pubkey.spec.ts | 15 ++++++++++++++- packages/sdk/src/pubkey.ts | 15 +++++++++++++++ packages/sdk/types/index.d.ts | 2 +- packages/sdk/types/pubkey.d.ts | 2 ++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index cbe754e4..36d24cbf 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -7,4 +7,4 @@ export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; diff --git a/packages/sdk/src/pubkey.spec.ts b/packages/sdk/src/pubkey.spec.ts index 2f0c6209..e5b3962b 100644 --- a/packages/sdk/src/pubkey.spec.ts +++ b/packages/sdk/src/pubkey.spec.ts @@ -1,6 +1,7 @@ import { Encoding } from "@iov/encoding"; -import { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +import { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +import { PubKey } from "./types"; const { fromBase64 } = Encoding; @@ -35,4 +36,16 @@ describe("pubkey", () => { }); }); }); + + describe("encodeBech32Pubkey", () => { + it("works for secp256k1", () => { + const pubkey: PubKey = { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }; + expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual( + "cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5", + ); + }); + }); }); diff --git a/packages/sdk/src/pubkey.ts b/packages/sdk/src/pubkey.ts index 23552860..ca21d0eb 100644 --- a/packages/sdk/src/pubkey.ts +++ b/packages/sdk/src/pubkey.ts @@ -60,3 +60,18 @@ export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix)); } } + +export function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey { + let aminoPrefix: Uint8Array; + switch (pubkey.type) { + // Note: please don't add cases here without writing additional unit tests + case pubkeyType.secp256k1: + aminoPrefix = pubkeyAminoPrefixSecp256k1; + break; + default: + throw new Error("Unsupported pubkey type"); + } + + const data = new Uint8Array([...aminoPrefix, ...Encoding.fromBase64(pubkey.value)]); + return Bech32.encode(prefix, data); +} diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 0aaeec16..3c8bdaab 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -6,4 +6,4 @@ export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; diff --git a/packages/sdk/types/pubkey.d.ts b/packages/sdk/types/pubkey.d.ts index 3d7075df..375de704 100644 --- a/packages/sdk/types/pubkey.d.ts +++ b/packages/sdk/types/pubkey.d.ts @@ -1,3 +1,5 @@ +import { CosmosPubkeyBech32Prefix } from "./address"; import { Bech32PubKey, PubKey } from "./types"; export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey; +export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey; From 1ed25c1bc058e463e0c262b53123692d0d53d3ae Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:31:29 +0100 Subject: [PATCH 10/13] Test pubkey response in authAccounts --- packages/sdk/src/restclient.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/sdk/src/restclient.spec.ts b/packages/sdk/src/restclient.spec.ts index 9c20c438..af0e42a0 100644 --- a/packages/sdk/src/restclient.spec.ts +++ b/packages/sdk/src/restclient.spec.ts @@ -6,6 +6,7 @@ import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; import { leb128Encode } from "./leb128.spec"; import { findAttribute, parseLogs } from "./logs"; import { Pen, Secp256k1Pen } from "./pen"; +import { encodeBech32Pubkey } from "./pubkey"; import { PostTxsResponse, RestClient } from "./restclient"; import contract from "./testdata/contract.json"; import cosmoshub from "./testdata/cosmoshub.json"; @@ -28,6 +29,10 @@ const defaultNetworkId = "testing"; const faucet = { mnemonic: "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone", + pubkey: { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }, address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", }; const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k"; @@ -217,6 +222,17 @@ describe("RestClient", () => { }, }); }); + + it("has correct pubkey for faucet", async () => { + pendingWithoutCosmos(); + const client = new RestClient(httpUrl); + const { result } = await client.authAccounts(faucet.address); + expect(result.value).toEqual( + jasmine.objectContaining({ + public_key: encodeBech32Pubkey(faucet.pubkey, "cosmospub"), + }), + ); + }); }); describe("encodeTx", () => { From 00c033b6693034295c52983bc1fb4a84e42c2d51 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:41:16 +0100 Subject: [PATCH 11/13] Use CosmosAddressBech32Prefix explicitely for addresses --- packages/bcp/src/address.spec.ts | 19 +----------------- packages/bcp/src/address.ts | 6 ++---- packages/bcp/src/cosmwasmcodec.spec.ts | 21 ++++++++++++++++++++ packages/bcp/src/cosmwasmcodec.ts | 21 +++++++++++++------- packages/bcp/src/cosmwasmconnection.spec.ts | 4 ++-- packages/bcp/src/cosmwasmconnection.ts | 22 +++++++++------------ packages/bcp/src/cosmwasmconnector.ts | 8 ++++---- packages/bcp/types/address.d.ts | 5 ++--- packages/bcp/types/cosmwasmcodec.d.ts | 6 +++--- packages/bcp/types/cosmwasmconnection.d.ts | 7 +++---- packages/bcp/types/cosmwasmconnector.d.ts | 4 ++-- packages/sdk/src/address.ts | 1 - packages/sdk/src/index.ts | 2 +- packages/sdk/types/address.d.ts | 1 - packages/sdk/types/index.d.ts | 2 +- 15 files changed, 65 insertions(+), 64 deletions(-) diff --git a/packages/bcp/src/address.spec.ts b/packages/bcp/src/address.spec.ts index cdfd3e31..0b52e387 100644 --- a/packages/bcp/src/address.spec.ts +++ b/packages/bcp/src/address.spec.ts @@ -1,7 +1,7 @@ import { Algorithm, PubkeyBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; -import { decodeCosmosPubkey, isValidAddress, pubkeyToAddress } from "./address"; +import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; const { fromBase64, fromHex } = Encoding; @@ -17,23 +17,6 @@ describe("address", () => { }); }); - describe("isValidAddress", () => { - it("accepts valid addresses", () => { - expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true); - expect(isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual(true); - expect(isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual(true); - }); - - it("rejects invalid addresses", () => { - // Bad size - expect(isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false); - // Bad checksum - expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false); - // Bad prefix - expect(isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false); - }); - }); - describe("pubkeyToAddress", () => { it("works for Secp256k1 compressed", () => { const prefix = "cosmos"; diff --git a/packages/bcp/src/address.ts b/packages/bcp/src/address.ts index ce6aa25b..c702edea 100644 --- a/packages/bcp/src/address.ts +++ b/packages/bcp/src/address.ts @@ -1,10 +1,8 @@ -import { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress, types } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix, decodeBech32Pubkey, encodeAddress, types } from "@cosmwasm/sdk"; import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; -export { CosmosBech32Prefix, isValidAddress }; - const { fromBase64, toBase64 } = Encoding; export function decodeCosmosPubkey( @@ -22,7 +20,7 @@ export function decodeCosmosPubkey( } // See https://github.com/tendermint/tendermint/blob/f2ada0a604b4c0763bda2f64fac53d506d3beca7/docs/spec/blockchain/encoding.md#public-key-cryptography -export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address { +export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosAddressBech32Prefix): Address { let sdkKey: types.PubKey; if (pubkey.algo === Algorithm.Secp256k1) { sdkKey = { diff --git a/packages/bcp/src/cosmwasmcodec.spec.ts b/packages/bcp/src/cosmwasmcodec.spec.ts index 8f5604be..e82d3870 100644 --- a/packages/bcp/src/cosmwasmcodec.spec.ts +++ b/packages/bcp/src/cosmwasmcodec.spec.ts @@ -7,6 +7,27 @@ import { chainId, nonce, sendTxJson, signedTxBin, signedTxEncodedJson, signedTxJ const { toUtf8 } = Encoding; describe("cosmWasmCodec", () => { + describe("isValidAddress", () => { + it("accepts valid addresses", () => { + expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true); + expect(cosmWasmCodec.isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual( + true, + ); + expect(cosmWasmCodec.isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual( + true, + ); + }); + + it("rejects invalid addresses", () => { + // Bad size + expect(cosmWasmCodec.isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false); + // Bad checksum + expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false); + // Bad prefix + expect(cosmWasmCodec.isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false); + }); + }); + it("properly generates bytes to sign", () => { const expected = { bytes: toUtf8( diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index 58644f2b..ff3a9879 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -1,5 +1,12 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { makeSignBytes, marshalTx, types, unmarshalTx } from "@cosmwasm/sdk"; +import { + CosmosAddressBech32Prefix, + isValidAddress, + makeSignBytes, + marshalTx, + types, + unmarshalTx, +} from "@cosmwasm/sdk"; import { Address, ChainId, @@ -15,18 +22,18 @@ import { UnsignedTransaction, } from "@iov/bcp"; -import { CosmosBech32Prefix, isValidAddress, pubkeyToAddress } from "./address"; +import { pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { parseTx } from "./decode"; import { buildSignedTx, buildUnsignedTx } from "./encode"; import { nonceToAccountNumber, nonceToSequence, TokenInfos } from "./types"; export class CosmWasmCodec implements TxCodec { - private readonly prefix: CosmosBech32Prefix; + private readonly addressPrefix: CosmosAddressBech32Prefix; private readonly tokens: TokenInfos; - public constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos) { - this.prefix = prefix; + public constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos) { + this.addressPrefix = prefix; this.tokens = tokens; } @@ -76,7 +83,7 @@ export class CosmWasmCodec implements TxCodec { } public identityToAddress(identity: Identity): Address { - return pubkeyToAddress(identity.pubkey, this.prefix); + return pubkeyToAddress(identity.pubkey, this.addressPrefix); } public isValidAddress(address: string): boolean { @@ -84,7 +91,7 @@ export class CosmWasmCodec implements TxCodec { } } -const defaultPrefix = "cosmos" as CosmosBech32Prefix; +const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix; const defaultTokens: TokenInfos = [ { diff --git a/packages/bcp/src/cosmwasmconnection.spec.ts b/packages/bcp/src/cosmwasmconnection.spec.ts index c59759a7..36e29773 100644 --- a/packages/bcp/src/cosmwasmconnection.spec.ts +++ b/packages/bcp/src/cosmwasmconnection.spec.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, Algorithm, @@ -14,7 +15,6 @@ import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmCodec, cosmWasmCodec } from "./cosmwasmcodec"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; import { signedTxJson, txId } from "./testdata.spec"; @@ -43,7 +43,7 @@ describe("CosmWasmConnection", () => { const faucetPath = HdPaths.cosmos(0); const defaultRecipient = "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" as Address; - const defaultPrefix = "cosmos" as CosmosBech32Prefix; + const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix; // this is for wasmd blockchain const defaultTokens: TokenConfiguration = [ diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index fe4c9f2d..25790a6a 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, types, unmarshalTx } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix, RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -34,7 +34,7 @@ import equal from "fast-deep-equal"; import { ReadonlyDate } from "readonly-date"; import { Stream } from "xstream"; -import { CosmosBech32Prefix, decodeCosmosPubkey, pubkeyToAddress } from "./address"; +import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { decodeAmount, parseTxsResponse } from "./decode"; import { accountToNonce, TokenInfo } from "./types"; @@ -75,12 +75,12 @@ export class CosmWasmConnection implements BlockchainConnection { // we must know prefix and tokens a priori to understand the chain public static async establish( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ): Promise { const restClient = new RestClient(url); const chainData = await this.initialize(restClient); - return new CosmWasmConnection(restClient, chainData, prefix, tokens); + return new CosmWasmConnection(restClient, chainData, addressPrefix, tokens); } private static async initialize(restClient: RestClient): Promise { @@ -90,26 +90,22 @@ export class CosmWasmConnection implements BlockchainConnection { private readonly restClient: RestClient; private readonly chainData: ChainData; - private readonly _prefix: CosmosBech32Prefix; + private readonly addressPrefix: CosmosAddressBech32Prefix; private readonly tokenInfo: readonly TokenInfo[]; // these are derived from arguments (cached for use in multiple functions) private readonly primaryToken: Token; private readonly supportedTokens: readonly Token[]; - private get prefix(): CosmosBech32Prefix { - return this._prefix; - } - private constructor( restClient: RestClient, chainData: ChainData, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ) { this.restClient = restClient; this.chainData = chainData; - this._prefix = prefix; + this.addressPrefix = addressPrefix; this.tokenInfo = tokens; this.supportedTokens = tokens.map(info => ({ @@ -149,7 +145,7 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getAccount(query: AccountQuery): Promise { - const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address; + const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address; const { result } = await this.restClient.authAccounts(address); const account = result.value; if (!account.address) { @@ -172,7 +168,7 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getNonce(query: AddressQuery | PubkeyQuery): Promise { - const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address; + const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address; const { result } = await this.restClient.authAccounts(address); const account = result.value; return accountToNonce(account); diff --git a/packages/bcp/src/cosmwasmconnector.ts b/packages/bcp/src/cosmwasmconnector.ts index af0673a3..61aaf006 100644 --- a/packages/bcp/src/cosmwasmconnector.ts +++ b/packages/bcp/src/cosmwasmconnector.ts @@ -1,6 +1,6 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { ChainConnector, ChainId } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmCodec } from "./cosmwasmcodec"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; @@ -9,13 +9,13 @@ import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; */ export function createCosmWasmConnector( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, expectedChainId?: ChainId, ): ChainConnector { - const codec = new CosmWasmCodec(prefix, tokens); + const codec = new CosmWasmCodec(addressPrefix, tokens); return { - establishConnection: async () => CosmWasmConnection.establish(url, prefix, tokens), + establishConnection: async () => CosmWasmConnection.establish(url, addressPrefix, tokens), codec: codec, expectedChainId: expectedChainId, }; diff --git a/packages/bcp/types/address.d.ts b/packages/bcp/types/address.d.ts index 158addbc..7a2c395c 100644 --- a/packages/bcp/types/address.d.ts +++ b/packages/bcp/types/address.d.ts @@ -1,10 +1,9 @@ -import { CosmosBech32Prefix, isValidAddress } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; -export { CosmosBech32Prefix, isValidAddress }; export declare function decodeCosmosPubkey( encodedPubkey: string, ): { readonly algo: Algorithm; readonly data: PubkeyBytes; }; -export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address; +export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosAddressBech32Prefix): Address; diff --git a/packages/bcp/types/cosmwasmcodec.d.ts b/packages/bcp/types/cosmwasmcodec.d.ts index 9ce8a6f0..76121658 100644 --- a/packages/bcp/types/cosmwasmcodec.d.ts +++ b/packages/bcp/types/cosmwasmcodec.d.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, ChainId, @@ -10,12 +11,11 @@ import { TxCodec, UnsignedTransaction, } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { TokenInfos } from "./types"; export declare class CosmWasmCodec implements TxCodec { - private readonly prefix; + private readonly addressPrefix; private readonly tokens; - constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos); + constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos); bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob; bytesToPost(signed: SignedTransaction): PostableBytes; identifier(_signed: SignedTransaction): TransactionId; diff --git a/packages/bcp/types/cosmwasmconnection.d.ts b/packages/bcp/types/cosmwasmconnection.d.ts index e5d1a7c6..413795dc 100644 --- a/packages/bcp/types/cosmwasmconnection.d.ts +++ b/packages/bcp/types/cosmwasmconnection.d.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -20,7 +21,6 @@ import { UnsignedTransaction, } from "@iov/bcp"; import { Stream } from "xstream"; -import { CosmosBech32Prefix } from "./address"; import { TokenInfo } from "./types"; export declare type TokenConfiguration = ReadonlyArray< TokenInfo & { @@ -30,17 +30,16 @@ export declare type TokenConfiguration = ReadonlyArray< export declare class CosmWasmConnection implements BlockchainConnection { static establish( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ): Promise; private static initialize; private readonly restClient; private readonly chainData; - private readonly _prefix; + private readonly addressPrefix; private readonly tokenInfo; private readonly primaryToken; private readonly supportedTokens; - private get prefix(); private constructor(); disconnect(): void; chainId(): ChainId; diff --git a/packages/bcp/types/cosmwasmconnector.d.ts b/packages/bcp/types/cosmwasmconnector.d.ts index d9ed98cd..fbebceea 100644 --- a/packages/bcp/types/cosmwasmconnector.d.ts +++ b/packages/bcp/types/cosmwasmconnector.d.ts @@ -1,12 +1,12 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { ChainConnector, ChainId } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; /** * A helper to connect to a cosmos-based chain at a given url */ export declare function createCosmWasmConnector( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, expectedChainId?: ChainId, ): ChainConnector; diff --git a/packages/sdk/src/address.ts b/packages/sdk/src/address.ts index 85df61c5..cb6b5eb7 100644 --- a/packages/sdk/src/address.ts +++ b/packages/sdk/src/address.ts @@ -8,7 +8,6 @@ const { fromBase64 } = Encoding; // TODO: make this much more configurable export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; -export type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix; function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBech32Prefix { return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 36d24cbf..b678ce20 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -2,7 +2,7 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; +export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; diff --git a/packages/sdk/types/address.d.ts b/packages/sdk/types/address.d.ts index 3390fc29..2d282875 100644 --- a/packages/sdk/types/address.d.ts +++ b/packages/sdk/types/address.d.ts @@ -1,6 +1,5 @@ import { PubKey } from "./types"; export declare type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; -export declare type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix; export declare function isValidAddress(address: string): boolean; export declare function encodeAddress(pubkey: PubKey, prefix: string): string; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 3c8bdaab..e2733189 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,7 +1,7 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; +export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; From 4520953e5316fd8bdd949377e617117c24e60aea Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 13:47:47 +0100 Subject: [PATCH 12/13] Move pubkey prefixes to pubkey.ts --- packages/sdk/src/address.ts | 1 - packages/sdk/src/index.ts | 7 ++++++- packages/sdk/src/pubkey.ts | 8 +++++--- packages/sdk/types/address.d.ts | 1 - packages/sdk/types/index.d.ts | 7 ++++++- packages/sdk/types/pubkey.d.ts | 2 +- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/sdk/src/address.ts b/packages/sdk/src/address.ts index cb6b5eb7..c5d5fa1a 100644 --- a/packages/sdk/src/address.ts +++ b/packages/sdk/src/address.ts @@ -7,7 +7,6 @@ const { fromBase64 } = Encoding; // TODO: make this much more configurable export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; -export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBech32Prefix { return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index b678ce20..024cf055 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -7,4 +7,9 @@ export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + CosmosPubkeyBech32Prefix, + decodeBech32Pubkey, + encodeBech32Pubkey, + encodeSecp256k1Pubkey, +} from "./pubkey"; diff --git a/packages/sdk/src/pubkey.ts b/packages/sdk/src/pubkey.ts index ca21d0eb..49a3cfd2 100644 --- a/packages/sdk/src/pubkey.ts +++ b/packages/sdk/src/pubkey.ts @@ -2,7 +2,6 @@ import { Secp256k1 } from "@iov/crypto"; import { Bech32, Encoding } from "@iov/encoding"; import equal from "fast-deep-equal"; -import { CosmosPubkeyBech32Prefix } from "./address"; import { Bech32PubKey, PubKey, pubkeyType } from "./types"; export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { @@ -12,8 +11,11 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { }; } +export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; +const validPubkeyPrefixes = ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"]; + function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix { - return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix); + return validPubkeyPrefixes.includes(prefix); } // As discussed in https://github.com/binance-chain/javascript-sdk/issues/163 @@ -27,7 +29,7 @@ const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { const { prefix, data } = Bech32.decode(bech); if (!isCosmosPubkeyBech32Prefix(prefix)) { - throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`); + throw new Error(`Invalid bech32 prefix. Must be one of ${validPubkeyPrefixes.join(", ")}.`); } const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength); diff --git a/packages/sdk/types/address.d.ts b/packages/sdk/types/address.d.ts index 2d282875..50e7e04e 100644 --- a/packages/sdk/types/address.d.ts +++ b/packages/sdk/types/address.d.ts @@ -1,5 +1,4 @@ import { PubKey } from "./types"; export declare type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; -export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; export declare function isValidAddress(address: string): boolean; export declare function encodeAddress(pubkey: PubKey, prefix: string): string; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index e2733189..5e0f5db2 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -6,4 +6,9 @@ export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; -export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + CosmosPubkeyBech32Prefix, + decodeBech32Pubkey, + encodeBech32Pubkey, + encodeSecp256k1Pubkey, +} from "./pubkey"; diff --git a/packages/sdk/types/pubkey.d.ts b/packages/sdk/types/pubkey.d.ts index 375de704..a7dddae8 100644 --- a/packages/sdk/types/pubkey.d.ts +++ b/packages/sdk/types/pubkey.d.ts @@ -1,5 +1,5 @@ -import { CosmosPubkeyBech32Prefix } from "./address"; import { Bech32PubKey, PubKey } from "./types"; export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; +export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey; export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey; From 96fc3230edaeb7b9aec83c95d03a953dd8d218ab Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Feb 2020 14:30:42 +0100 Subject: [PATCH 13/13] Standardize argument name --- packages/bcp/src/cosmwasmcodec.ts | 4 ++-- packages/bcp/types/cosmwasmcodec.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index ff3a9879..b370bdd1 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -32,8 +32,8 @@ export class CosmWasmCodec implements TxCodec { private readonly addressPrefix: CosmosAddressBech32Prefix; private readonly tokens: TokenInfos; - public constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos) { - this.addressPrefix = prefix; + public constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos) { + this.addressPrefix = addressPrefix; this.tokens = tokens; } diff --git a/packages/bcp/types/cosmwasmcodec.d.ts b/packages/bcp/types/cosmwasmcodec.d.ts index 76121658..ba1353a8 100644 --- a/packages/bcp/types/cosmwasmcodec.d.ts +++ b/packages/bcp/types/cosmwasmcodec.d.ts @@ -15,7 +15,7 @@ import { TokenInfos } from "./types"; export declare class CosmWasmCodec implements TxCodec { private readonly addressPrefix; private readonly tokens; - constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos); + constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos); bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob; bytesToPost(signed: SignedTransaction): PostableBytes; identifier(_signed: SignedTransaction): TransactionId;