From 5624b1d7e54f9577a2cbcde97a8119cb6fb48ce6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 11:57:11 +0200 Subject: [PATCH 01/47] Update PRIORITIES.md --- docs/PRIORITIES.md | 84 ++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 55 deletions(-) diff --git a/docs/PRIORITIES.md b/docs/PRIORITIES.md index d628c136e0..435ba02d3d 100644 --- a/docs/PRIORITIES.md +++ b/docs/PRIORITIES.md @@ -1,78 +1,52 @@ +# High priority + ## Fees + - Collection - - Gas price based on parameter - - (which gets changed automatically) - - https://github.com/cosmos/cosmos-sdk/issues/1921 - - Per block gas usage as % - - Windowing function - - Block N, - - For Block N-x ~ N, get average of % - - Should take into account time. - - Standard for querying this price // needs to be used by UX. + - Simple flat fee set in-config by validators & full nodes - ref [#1921](https://github.com/cosmos/cosmos-sdk/issues/1921) - Distribution - - MVP: 1 week, 1 week for testing. + - "Piggy bank" fee distribution - ref [#1944](https://github.com/cosmos/cosmos-sdk/pull/1944) (spec) +- Reserve pool + - Collects in a special field for now, no spending ## Governance v2 -- V1 is just text proposals - - Software upgrade stuff - - https://github.com/cosmos/cosmos-sdk/issues/1734#issuecomment-407254938 - - https://github.com/cosmos/cosmos-sdk/issues/1079 -- We need to test auto-flipping w/ threshold voting power. -- Super simple: - - Only use text proposals - - On-chain mechanism for agreeing on when to "flip" to new functionality + +- Simple software upgrade proposals + - Implementation described in [#1079](https://github.com/cosmos/cosmos-sdk/issues/1079) + - Agree upon a block height to switch to new version ## Staking/Slashing/Stability + +- Miscellaneous minor staking issues + - [List here](https://github.com/cosmos/cosmos-sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Astaking+label%3Aprelaunch) - Unbonding state for validators https://github.com/cosmos/cosmos-sdk/issues/1676 -- current: downtime, double signing during unbonding -- who gets slashed when -- needs review about edge cases -- need to communicate to everyone that lite has this edge case - - Issues: - - https://github.com/cosmos/cosmos-sdk/issues/1378 - - https://github.com/cosmos/cosmos-sdk/issues/1348 - - https://github.com/cosmos/cosmos-sdk/issues/1440 - * Est Difficulty: Hard - * _*Note:*_ This feature needs to be fully fleshed out. Will require a meeting between @jaekwon, @cwgoes, @rigel, @zaki, @bucky to discuss the issues. @jackzampolin to facilitate. +- Slashing period - ref [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) (spec) + - Various other slashing issues needing resolution - ref [#1256](https://github.com/cosmos/cosmos-sdk/issues/1256) +- Update staking/slashing for NextValSet change ## Vesting -- 24 accounts with NLocktime -- “No funds can be transferred before timelock” -- New atoms and such can be withdrawn right way -- Requires being able to send fees and inflation to new account + +- Single `VestingAccount` allowing delegation/voting but no withdrawals +- Ref [#1875](https://github.com/cosmos/cosmos-sdk/pull/1875) (spec) ## Multisig -- Make it work with Cli -- ADR -## Reserve Pool -- No withdrawing from it at launch +- Already implemented on TM side, need simple CLI interface -## Other: -- Need to update for NextValidatorSet - need to upgrade SDK for it -- Need to update for new ABCI changes - error string, tags are list of lists, proposer in header -- Inflation ? +## Other + +- Need to update for new ABCI changes - error string, tags are list of lists, proposer in header (Tendermint 0.24?) ## Gas -- Calculate gas -## Reward proposer -- Requires tendermint changes +- Benchmark gas, choose better constants # Lower priority -## Circuit Breaker -- Kinda needed for enabling txs. +## Governance -## Governance proposal changes -- V2 is parameter changes +- Circuit breaker (parameter change proposals, roughly the same implementation) -## Slashing/Stability -- tendermint evidence: we don’t yet slash byzantine signatures (signing at all) when not bonded. +## Documentation -# Other priority - -## gaiad // gaiacli -- Documentation // language - -## gaialite -- Documentation // language +- gaiad / gaiacli / gaialite documentation! From 53242681fe0edd44c3a6e28083f485139619432e Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 12:50:07 +0200 Subject: [PATCH 02/47] Two bullet points --- docs/PRIORITIES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/PRIORITIES.md b/docs/PRIORITIES.md index 435ba02d3d..631d9b9ea5 100644 --- a/docs/PRIORITIES.md +++ b/docs/PRIORITIES.md @@ -45,7 +45,8 @@ ## Governance -- Circuit breaker (parameter change proposals, roughly the same implementation) +- Circuit breaker +- Parameter change proposals (roughly the same implementation as circuit breaker) ## Documentation From 1ffb2a1c03fbb3b469ff7faa198dc504b331dd6b Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Mon, 20 Aug 2018 11:46:27 -0400 Subject: [PATCH 03/47] DataDog update script --- networks/remote/ansible/install-datadog-agent.yml | 1 + .../roles/install-datadog-agent/tasks/main.yml | 8 -------- .../files/conf.d/http_check.d/conf.yaml | 13 +++++++++++++ .../files/conf.d/network.d/conf.yaml | 0 .../files/conf.d/process.d/conf.yaml | 0 .../files/conf.d/prometheus.d/conf.yaml | 7 +++++-- .../roles/update-datadog-agent/handlers/main.yml | 5 +++++ .../roles/update-datadog-agent/tasks/main.yml | 10 ++++++++++ .../templates/datadog.yaml.j2 | 0 networks/remote/ansible/update-datadog-agent.yml | 10 ++++++++++ 10 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/network.d/conf.yaml (100%) rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/process.d/conf.yaml (100%) rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/prometheus.d/conf.yaml (51%) create mode 100644 networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml create mode 100644 networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/templates/datadog.yaml.j2 (100%) create mode 100644 networks/remote/ansible/update-datadog-agent.yml diff --git a/networks/remote/ansible/install-datadog-agent.yml b/networks/remote/ansible/install-datadog-agent.yml index d324587033..54b77e1f82 100644 --- a/networks/remote/ansible/install-datadog-agent.yml +++ b/networks/remote/ansible/install-datadog-agent.yml @@ -7,4 +7,5 @@ gather_facts: no roles: - install-datadog-agent + - update-datadog-agent diff --git a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml index bba86a5ac3..0c0a49ecac 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml +++ b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml @@ -13,14 +13,6 @@ DD_API_KEY: "{{DD_API_KEY}}" DD_HOST_TAGS: "testnet:{{TESTNET_NAME}},cluster:{{CLUSTER_NAME}}" -- name: Set datadog.yaml config - template: src=datadog.yaml.j2 dest=/etc/datadog-agent/datadog.yaml - notify: restart datadog-agent - -- name: Set metrics config - copy: src=conf.d/ dest=/etc/datadog-agent/conf.d/ - notify: restart datadog-agent - - name: Disable journald rate-limiting lineinfile: "dest=/etc/systemd/journald.conf regexp={{item.regexp}} line='{{item.line}}'" with_items: diff --git a/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml new file mode 100644 index 0000000000..6932ed6f40 --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml @@ -0,0 +1,13 @@ +init_config: + +instances: + - name: gaiad + url: http://localhost:26657/status + timeout: 1 + content_match: '"latest_block_height": "0",' + reverse_content_match: true + + - name: gaiacli + url: http://localhost:1317/node_version + timeout: 1 + diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/network.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/network.d/conf.yaml similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/network.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/network.d/conf.yaml diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/process.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/process.d/conf.yaml similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/process.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/process.d/conf.yaml diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml similarity index 51% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml index b08908400c..20c04ceee3 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml +++ b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml @@ -2,6 +2,9 @@ init_config: instances: - prometheus_url: http://127.0.0.1:26660 - namespace: "gaiad" metrics: - - p2p: * + - go* + - mempool* + - p2p* + - process* + - promhttp* diff --git a/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml b/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml new file mode 100644 index 0000000000..90e05c17dd --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: restart datadog-agent + service: name=datadog-agent state=restarted + diff --git a/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml new file mode 100644 index 0000000000..c6174c6af2 --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml @@ -0,0 +1,10 @@ +--- + +- name: Set datadog.yaml config + template: src=datadog.yaml.j2 dest=/etc/datadog-agent/datadog.yaml + notify: restart datadog-agent + +- name: Set metrics config + copy: src=conf.d/ dest=/etc/datadog-agent/conf.d/ + notify: restart datadog-agent + diff --git a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.yaml.j2 b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/templates/datadog.yaml.j2 rename to networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 diff --git a/networks/remote/ansible/update-datadog-agent.yml b/networks/remote/ansible/update-datadog-agent.yml new file mode 100644 index 0000000000..3fe1e0006e --- /dev/null +++ b/networks/remote/ansible/update-datadog-agent.yml @@ -0,0 +1,10 @@ +--- + +#DD_API_KEY,TESTNET_NAME,CLUSTER_NAME required + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - update-datadog-agent + From 08318e3d25028b415371436c370261269e8fb237 Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Mon, 20 Aug 2018 15:34:06 -0400 Subject: [PATCH 04/47] ansible fixes for gaiad and gaiacli deployments --- networks/remote/ansible/roles/add-lcd/tasks/main.yml | 2 +- networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/networks/remote/ansible/roles/add-lcd/tasks/main.yml b/networks/remote/ansible/roles/add-lcd/tasks/main.yml index 11fa44c9f2..d0fbd81325 100644 --- a/networks/remote/ansible/roles/add-lcd/tasks/main.yml +++ b/networks/remote/ansible/roles/add-lcd/tasks/main.yml @@ -3,7 +3,7 @@ - name: Copy binary copy: src: "{{GAIACLI_BINARY}}" - dest: /usr/bin + dest: /usr/bin/gaiacli mode: 0755 notify: restart gaiacli diff --git a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml index 03bdf40e09..bd2ccdb2b4 100644 --- a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml +++ b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml @@ -3,7 +3,7 @@ - name: Copy binary copy: src: "{{BINARY}}" - dest: /usr/bin + dest: /usr/bin/gaiad mode: 0755 notify: restart gaiad From f908199855fc4bbaf5597397e4a824d65bbb1675 Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Thu, 23 Aug 2018 14:51:42 -0400 Subject: [PATCH 05/47] Ansible and Terraform script updates --- PENDING.md | 2 + networks/remote/ansible/ansible.cfg | 4 - .../remote/ansible/increase-openfiles.yml | 8 ++ .../remote/ansible/install-datadog-agent.yml | 1 + .../ansible/roles/add-lcd/defaults/main.yml | 2 +- .../add-lcd/templates/gaiacli.service.j2 | 2 +- .../roles/increase-openfiles/files/50-fs.conf | 1 + .../increase-openfiles/files/91-nofiles.conf | 3 + .../increase-openfiles/files/limits.conf | 3 + .../increase-openfiles/handlers/main.yml | 5 ++ .../roles/increase-openfiles/tasks/main.yml | 22 ++++++ .../files/intake.logs.datadoghq.com.crt | 78 ------------------- .../files/logrotate.conf | 35 --------- .../roles/install-datadog-agent/files/syslog | 13 ---- .../install-datadog-agent/tasks/main.yml | 35 --------- .../templates/datadog.conf.j2 | 14 ---- .../roles/set-debug/files/sysconfig/gaiacli | 1 + .../roles/set-debug/files/sysconfig/gaiad | 1 + .../set-debug/files/sysctl.d/10-procdump | 3 + .../roles/set-debug/handlers/main.yaml | 4 + .../ansible/roles/set-debug/tasks/main.yml | 9 +++ .../setup-fullnodes}/files/gaiad.service | 0 .../roles/setup-fullnodes/handlers/main.yml | 5 ++ .../roles/setup-fullnodes/tasks/main.yml | 9 ++- .../roles/setup-journald/tasks/main.yml | 9 +++ .../setup-validators}/files/gaiad.service | 0 .../roles/setup-validators/handlers/main.yml | 5 ++ .../roles/setup-validators/tasks/main.yml | 9 ++- .../templates/datadog.yaml.j2 | 6 +- networks/remote/ansible/set-corefilesize.yml | 13 ---- networks/remote/ansible/set-debug.yml | 8 ++ networks/remote/ansible/setup-fullnodes.yml | 2 + networks/remote/ansible/setup-validators.yml | 1 + networks/remote/ansible/status.yml | 2 +- .../remote/terraform-app/files/terraform.sh | 10 +-- .../remote/terraform-app/infra/attachment.tf | 10 ++- .../remote/terraform-app/infra/instance.tf | 10 +-- networks/remote/terraform-app/infra/lb.tf | 29 +++---- networks/remote/terraform-app/infra/lcd.tf | 39 ++++++++++ .../remote/terraform-app/infra/outputs.tf | 6 +- .../remote/terraform-app/infra/variables.tf | 10 +++ networks/remote/terraform-app/infra/vpc.tf | 15 +++- networks/remote/terraform-app/main.tf | 16 +++- .../remote/terraform-aws/files/terraform.sh | 10 +-- networks/remote/terraform-aws/main.tf | 2 +- networks/remote/terraform-aws/nodes/main.tf | 8 +- networks/remote/terraform-do/cluster/main.tf | 5 -- .../remote/terraform-do/files/gaiad.service | 17 ---- .../remote/terraform-do/files/terraform.sh | 13 +--- 49 files changed, 217 insertions(+), 298 deletions(-) delete mode 100644 networks/remote/ansible/ansible.cfg create mode 100644 networks/remote/ansible/increase-openfiles.yml create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/limits.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/handlers/main.yml create mode 100644 networks/remote/ansible/roles/increase-openfiles/tasks/main.yml delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/syslog delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 create mode 100644 networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli create mode 100644 networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad create mode 100644 networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump create mode 100644 networks/remote/ansible/roles/set-debug/handlers/main.yaml create mode 100644 networks/remote/ansible/roles/set-debug/tasks/main.yml rename networks/remote/{terraform-app => ansible/roles/setup-fullnodes}/files/gaiad.service (100%) create mode 100644 networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml rename networks/remote/{terraform-aws => ansible/roles/setup-validators}/files/gaiad.service (100%) create mode 100644 networks/remote/ansible/roles/setup-validators/handlers/main.yml delete mode 100644 networks/remote/ansible/set-corefilesize.yml create mode 100644 networks/remote/ansible/set-debug.yml create mode 100644 networks/remote/terraform-app/infra/lcd.tf delete mode 100644 networks/remote/terraform-do/files/gaiad.service diff --git a/PENDING.md b/PENDING.md index 4ca3e6df54..70277f24b0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -72,6 +72,8 @@ IMPROVEMENTS * [x/gov] Initial governance parameters can now be set in the genesis file * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [server] \#1930 Transactions indexer indexes all tags by default. +* [tools] Improved terraform and ansible scripts for infrastructure deployment +* [tools] Added ansible script to enable process core dumps BUG FIXES * \#1666 Add intra-tx counter to the genesis validators diff --git a/networks/remote/ansible/ansible.cfg b/networks/remote/ansible/ansible.cfg deleted file mode 100644 index 045c1ea606..0000000000 --- a/networks/remote/ansible/ansible.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[defaults] -retry_files_enabled = False -host_key_checking = False - diff --git a/networks/remote/ansible/increase-openfiles.yml b/networks/remote/ansible/increase-openfiles.yml new file mode 100644 index 0000000000..1adcb821c1 --- /dev/null +++ b/networks/remote/ansible/increase-openfiles.yml @@ -0,0 +1,8 @@ +--- + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - increase-openfiles + diff --git a/networks/remote/ansible/install-datadog-agent.yml b/networks/remote/ansible/install-datadog-agent.yml index 54b77e1f82..b88600eae9 100644 --- a/networks/remote/ansible/install-datadog-agent.yml +++ b/networks/remote/ansible/install-datadog-agent.yml @@ -6,6 +6,7 @@ any_errors_fatal: true gather_facts: no roles: + - setup-journald - install-datadog-agent - update-datadog-agent diff --git a/networks/remote/ansible/roles/add-lcd/defaults/main.yml b/networks/remote/ansible/roles/add-lcd/defaults/main.yml index 952d016f7d..16a85e0dd3 100644 --- a/networks/remote/ansible/roles/add-lcd/defaults/main.yml +++ b/networks/remote/ansible/roles/add-lcd/defaults/main.yml @@ -1,4 +1,4 @@ --- -GAIAD_ADDRESS: tcp://0.0.0.0:1317 +GAIACLI_ADDRESS: tcp://0.0.0.0:1317 diff --git a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 index 4f189f8f5b..a0c20a5b98 100644 --- a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 +++ b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 @@ -8,7 +8,7 @@ Restart=on-failure User=gaiad Group=gaiad PermissionsStartOnly=true -ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIAD_ADDRESS}} +ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIACLI_ADDRESS}} ExecReload=/bin/kill -HUP $MAINPID KillSignal=SIGTERM diff --git a/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf b/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf new file mode 100644 index 0000000000..5193edd22e --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf @@ -0,0 +1 @@ +fs.file-max=262144 diff --git a/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf b/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf new file mode 100644 index 0000000000..929081c6c9 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf @@ -0,0 +1,3 @@ +* soft nofile 262144 +* hard nofile 262144 + diff --git a/networks/remote/ansible/roles/increase-openfiles/files/limits.conf b/networks/remote/ansible/roles/increase-openfiles/files/limits.conf new file mode 100644 index 0000000000..d3fcd2e867 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/limits.conf @@ -0,0 +1,3 @@ +[Service] +LimitNOFILE=infinity +LimitMEMLOCK=infinity diff --git a/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml b/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml new file mode 100644 index 0000000000..d496023003 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemctl + systemd: name=systemd daemon_reload=yes + diff --git a/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml b/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml new file mode 100644 index 0000000000..78432f5b5a --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Based on: https://stackoverflow.com/questions/38155108/how-to-increase-limit-for-open-processes-and-files-using-ansible + +- name: Set sysctl File Limits + copy: + src: 50-fs.conf + dest: /etc/sysctl.d + +- name: Set Shell File Limits + copy: + src: 91-nofiles.conf + dest: /etc/security/limits.d + +- name: Set gaia filehandle Limits + copy: + src: limits.conf + dest: "/lib/systemd/system/{{item}}.service.d" + notify: reload systemctl + with_items: + - gaiad + - gaiacli + diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt b/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt deleted file mode 100644 index ef6d9b2c2a..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt +++ /dev/null @@ -1,78 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIESTCCAzGgAwIBAgITBn+UV4WH6Kx33rJTMlu8mYtWDTANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB -IDFCMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDCThZn3c68asg3Wuw6MLAd5tES6BIoSMzoKcG5blPVo+sDORrMd4f2AbnZ -cMzPa43j4wNxhplty6aUKk4T1qe9BOwKFjwK6zmxxLVYo7bHViXsPlJ6qOMpFge5 -blDP+18x+B26A0piiQOuPkfyDyeR4xQghfj66Yo19V+emU3nazfvpFA+ROz6WoVm -B5x+F2pV8xeKNR7u6azDdU5YVX1TawprmxRC1+WsAYmz6qP+z8ArDITC2FMVy2fw -0IjKOtEXc/VfmtTFch5+AfGYMGMqqvJ6LcXiAhqG5TI+Dr0RtM88k+8XUBCeQ8IG -KuANaL7TiItKZYxK1MMuTJtV9IblAgMBAAGjggE7MIIBNzASBgNVHRMBAf8ECDAG -AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUWaRmBlKge5WSPKOUByeW -dFv5PdAwHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH -AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy -dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy -dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js -LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBMGA1UdIAQMMAow -CAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IBAQCFkr41u3nPo4FCHOTjY3NTOVI1 -59Gt/a6ZiqyJEi+752+a1U5y6iAwYfmXss2lJwJFqMp2PphKg5625kXg8kP2CN5t -6G7bMQcT8C8xDZNtYTd7WPD8UZiRKAJPBXa30/AbwuZe0GaFEQ8ugcYQgSn+IGBI -8/LwhBNTZTUVEWuCUUBVV18YtbAiPq3yXqMB48Oz+ctBWuZSkbvkNodPLamkB2g1 -upRyzQ7qDn1X8nn8N8V7YJ6y68AtkHcNSRAnpTitxBKjtKPISLMVCx7i4hncxHZS -yLyKQXhw2W2Xs0qLeC1etA+jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF -ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj -b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x -OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1 -dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW -gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH -MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy -MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0 -LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF -AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW -MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma -eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK -bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN -0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U -akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEdTCCA12gAwIBAgIJAKcOSkw0grd/MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV -BAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIw -MAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTAeFw0wOTA5MDIwMDAwMDBaFw0zNDA2MjgxNzM5MTZaMIGYMQswCQYDVQQGEwJV -UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjE7MDkGA1UEAxMyU3RhcmZp -ZWxkIFNlcnZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVDDrEKvlO4vW+GZdfjohTsR8/ -y8+fIBNtKTrID30892t2OGPZNmCom15cAICyL1l/9of5JUOG52kbUpqQ4XHj2C0N -Tm/2yEnZtvMaVq4rtnQU68/7JuMauh2WLmo7WJSJR1b/JaCTcFOD2oR0FMNnngRo -Ot+OQFodSk7PQ5E751bWAHDLUu57fa4657wx+UX2wmDPE1kCK4DMNEffud6QZW0C -zyyRpqbn3oUYSXxmTqM6bam17jQuug0DuDPfR+uxa40l2ZvOgdFFRjKWcIfeAg5J -Q4W2bHO7ZOphQazJ1FTfhy/HIrImzJ9ZVGif/L4qL8RVHHVAYBeFAlU5i38FAgMB -AAGjgfAwge0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O -BBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMB8GA1UdIwQYMBaAFL9ft9HO3R+G9FtV -rNzXEMIOqYjnME8GCCsGAQUFBwEBBEMwQTAcBggrBgEFBQcwAYYQaHR0cDovL28u -c3MyLnVzLzAhBggrBgEFBQcwAoYVaHR0cDovL3guc3MyLnVzL3guY2VyMCYGA1Ud -HwQfMB0wG6AZoBeGFWh0dHA6Ly9zLnNzMi51cy9yLmNybDARBgNVHSAECjAIMAYG -BFUdIAAwDQYJKoZIhvcNAQELBQADggEBACMd44pXyn3pF3lM8R5V/cxTbj5HD9/G -VfKyBDbtgB9TxF00KGu+x1X8Z+rLP3+QsjPNG1gQggL4+C/1E2DUBc7xgQjB3ad1 -l08YuW3e95ORCLp+QCztweq7dp4zBncdDQh/U90bZKuCJ/Fp1U1ervShw3WnWEQt -8jxwmKy6abaVd38PMV4s/KCHOkdp8Hlf9BRUpJVeEXgSYCfOn8J3/yNTd126/+pZ -59vPr5KW7ySaNRB6nJHGDn2Z9j8Z3/VyVOEVqQdZe4O/Ui5GjLIAZHYcSNPYeehu -VsyuLAOQ1xk4meTKCRlb/weWsKh/NEnfVqn3sF/tM+2MR7cwA130A4w= ------END CERTIFICATE----- diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf b/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf deleted file mode 100644 index e90a5ffb2c..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf +++ /dev/null @@ -1,35 +0,0 @@ -# see "man logrotate" for details -# rotate log files weekly -daily - -# keep 4 days worth of backlogs -rotate 4 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we'll rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -} - -# system-specific logs may be also be configured here. diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/syslog b/networks/remote/ansible/roles/install-datadog-agent/files/syslog deleted file mode 100644 index 8052df477c..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/syslog +++ /dev/null @@ -1,13 +0,0 @@ -/var/log/cron -/var/log/maillog -/var/log/messages -/var/log/secure -/var/log/spooler -{ - missingok - sharedscripts - postrotate - /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true - service datadog-agent restart 2> /dev/null || true - endscript -} diff --git a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml index 0c0a49ecac..4d5aa1877c 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml +++ b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml @@ -13,38 +13,3 @@ DD_API_KEY: "{{DD_API_KEY}}" DD_HOST_TAGS: "testnet:{{TESTNET_NAME}},cluster:{{CLUSTER_NAME}}" -- name: Disable journald rate-limiting - lineinfile: "dest=/etc/systemd/journald.conf regexp={{item.regexp}} line='{{item.line}}'" - with_items: - - { regexp: "^#RateLimitInterval", line: "RateLimitInterval=0s" } - - { regexp: "^#RateLimitBurst", line: "RateLimitBurst=0" } - - { regexp: "^#SystemMaxFileSize", line: "SystemMaxFileSize=500M" } - notify: restart journald - -- name: As long as Datadog does not support journald on RPM-based linux, we enable rsyslog - yum: "name={{item}} state=installed" - with_items: - - rsyslog - - rsyslog-gnutls - -#- name: Get DataDog certificate for rsyslog -# get_url: url=https://docs.datadoghq.com/crt/intake.logs.datadoghq.com.crt dest=/etc/ssl/certs/intake.logs.datadoghq.com.crt - -- name: Get DataDog certificate for rsyslog - copy: src=intake.logs.datadoghq.com.crt dest=/etc/ssl/certs/intake.logs.datadoghq.com.crt - -- name: Add datadog config to rsyslog - template: src=datadog.conf.j2 dest=/etc/rsyslog.d/datadog.conf mode=0600 - notify: restart rsyslog - -- name: Set logrotate to rotate daily so syslog does not use up all space - copy: src=logrotate.conf dest=/etc/logrotate.conf - -- name: Set syslog to restart datadog-agent after logrotate - copy: src=syslog dest=/etc/logrotate.d/syslog - -#semanage port -a -t syslog_tls_port_t -p tcp 10516 -- name: Enable rsyslog to report to port 10516 in SELinux - seport: ports=10516 proto=tcp reload=yes setype=syslog_tls_port_t state=present - notify: restart rsyslog - diff --git a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 b/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 deleted file mode 100644 index 1ab7d1b079..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 +++ /dev/null @@ -1,14 +0,0 @@ -$template DatadogFormat,"{{DD_API_KEY}} <%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% - - - %msg%\n" - -$imjournalRatelimitInterval 0 -$imjournalRatelimitBurst 0 - -$DefaultNetstreamDriver gtls -$DefaultNetstreamDriverCAFile /etc/ssl/certs/intake.logs.datadoghq.com.crt -$ActionSendStreamDriver gtls -$ActionSendStreamDriverMode 1 -$ActionSendStreamDriverAuthMode x509/name -$ActionSendStreamDriverPermittedPeer *.logs.datadoghq.com -*.* @@intake.logs.datadoghq.com:10516;DatadogFormat - - diff --git a/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli new file mode 100644 index 0000000000..8ef3a7e0c7 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli @@ -0,0 +1 @@ +DAEMON_COREFILE_LIMIT='unlimited' diff --git a/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad new file mode 100644 index 0000000000..8ef3a7e0c7 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad @@ -0,0 +1 @@ +DAEMON_COREFILE_LIMIT='unlimited' diff --git a/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump b/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump new file mode 100644 index 0000000000..fbbbe05121 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump @@ -0,0 +1,3 @@ +kernel.core_uses_pid = 1 +kernel.core_pattern = /tmp/core-%e-%s-%u-%g-%p-%t +fs.suid_dumpable = 2 diff --git a/networks/remote/ansible/roles/set-debug/handlers/main.yaml b/networks/remote/ansible/roles/set-debug/handlers/main.yaml new file mode 100644 index 0000000000..743ce09bcf --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/handlers/main.yaml @@ -0,0 +1,4 @@ +--- + +- name: reload sysctl + command: "/sbin/sysctl -p" diff --git a/networks/remote/ansible/roles/set-debug/tasks/main.yml b/networks/remote/ansible/roles/set-debug/tasks/main.yml new file mode 100644 index 0000000000..7497dabd8c --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/tasks/main.yml @@ -0,0 +1,9 @@ +--- +# Based on https://www.cyberciti.biz/tips/linux-core-dumps.html + +- name: Copy sysctl and sysconfig files to enable app and daemon core dumps + file: src=. dest=/etc/ + notify: reload sysctl + +- name: Enable debugging for all apps + lineinfile: create=yes line="DAEMON_COREFILE_LIMIT='unlimited'" path=/etc/sysconfig/init regexp=^DAEMON_COREFILE_LIMIT= diff --git a/networks/remote/terraform-app/files/gaiad.service b/networks/remote/ansible/roles/setup-fullnodes/files/gaiad.service similarity index 100% rename from networks/remote/terraform-app/files/gaiad.service rename to networks/remote/ansible/roles/setup-fullnodes/files/gaiad.service diff --git a/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml b/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml new file mode 100644 index 0000000000..987e2947bf --- /dev/null +++ b/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemd + systemd: name=gaiad enabled=yes daemon_reload=yes + diff --git a/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml b/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml index 26bcc4ccd8..ba9b22942c 100644 --- a/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml @@ -6,14 +6,21 @@ run_once: true become: no +- name: Create gaiad user + user: name=gaiad home=/home/gaiad shell=/bin/bash + - name: Copy binary copy: src: "{{BINARY}}" dest: /usr/bin mode: 0755 +- name: Copy service file + copy: src=gaiad.service dest=/etc/systemd/system/gaiad.service mode=0755 + notify: reload systemd + - name: Get node ID - command: "cat /etc/gaiad-nodeid" + command: "cat /etc/nodeid" changed_when: false register: nodeid diff --git a/networks/remote/ansible/roles/setup-journald/tasks/main.yml b/networks/remote/ansible/roles/setup-journald/tasks/main.yml index a7a105bf3f..130da52001 100644 --- a/networks/remote/ansible/roles/setup-journald/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-journald/tasks/main.yml @@ -5,8 +5,17 @@ with_items: - { regexp: "^#RateLimitInterval", line: "RateLimitInterval=0s" } - { regexp: "^#RateLimitBurst", line: "RateLimitBurst=0" } + - { regexp: "^#SystemMaxFileSize", line: "SystemMaxFileSize=100M" } + - { regexp: "^#SystemMaxUse", line: "SystemMaxUse=500M" } + - { regexp: "^#SystemMaxFiles", line: "SystemMaxFiles=10" } notify: restart journald +- name: Change logrotate to daily + lineinfile: "dest=/etc/logrotate.conf regexp={{item.regexp}} line='{{item.line}}'" + with_items: + - { regexp: "^weekly", line: "daily" } + - { regexp: "^#compress", line: "compress" } + - name: Create journal directory for permanent logs file: path=/var/log/journal state=directory notify: restart journald diff --git a/networks/remote/terraform-aws/files/gaiad.service b/networks/remote/ansible/roles/setup-validators/files/gaiad.service similarity index 100% rename from networks/remote/terraform-aws/files/gaiad.service rename to networks/remote/ansible/roles/setup-validators/files/gaiad.service diff --git a/networks/remote/ansible/roles/setup-validators/handlers/main.yml b/networks/remote/ansible/roles/setup-validators/handlers/main.yml new file mode 100644 index 0000000000..987e2947bf --- /dev/null +++ b/networks/remote/ansible/roles/setup-validators/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemd + systemd: name=gaiad enabled=yes daemon_reload=yes + diff --git a/networks/remote/ansible/roles/setup-validators/tasks/main.yml b/networks/remote/ansible/roles/setup-validators/tasks/main.yml index 46e9117d56..8832db4aa2 100644 --- a/networks/remote/ansible/roles/setup-validators/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-validators/tasks/main.yml @@ -6,14 +6,21 @@ run_once: true become: no +- name: Create gaiad user + user: name=gaiad home=/home/gaiad shell=/bin/bash + - name: Copy binary copy: src: "{{BINARY}}" dest: /usr/bin mode: 0755 +- name: Copy service file + copy: src=gaiad.service dest=/etc/systemd/system/gaiad.service mode=0755 + notify: reload systemd + - name: Get node ID - command: "cat /etc/gaiad-nodeid" + command: "cat /etc/nodeid" changed_when: false register: nodeid diff --git a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 index 2f3eb286e0..7e35a5255e 100644 --- a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 +++ b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 @@ -28,10 +28,10 @@ api_key: {{DD_API_KEY}} # Setting this option to "yes" will force the agent to only use TLS 1.2 when # pushing data to the url specified in "dd_url". -# force_tls_12: no +force_tls_12: yes # Force the hostname to whatever you want. (default: auto-detected) -# hostname: mymachine.mydomain +hostname: {{inventory_hostname}} # Make the agent use "hostname -f" on unix-based systems as a last resort # way of determining the hostname instead of Golang "os.Hostname()" @@ -220,7 +220,7 @@ collect_ec2_tags: true # Logs agent # # Logs agent is disabled by default -logs_enabled: true +#logs_enabled: true # # Enable logs collection for all containers, disabled by default # logs_config: diff --git a/networks/remote/ansible/set-corefilesize.yml b/networks/remote/ansible/set-corefilesize.yml deleted file mode 100644 index ae0f852913..0000000000 --- a/networks/remote/ansible/set-corefilesize.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- - -# Set the core file size to unlimited to allow the system to generate core dumps - -- hosts: all - any_errors_fatal: true - gather_facts: no - - tasks: - - - name: Set core file size to unlimited to be able to get the core dump on SIGABRT - shell: "ulimit -c unlimited" - diff --git a/networks/remote/ansible/set-debug.yml b/networks/remote/ansible/set-debug.yml new file mode 100644 index 0000000000..76ee1b3574 --- /dev/null +++ b/networks/remote/ansible/set-debug.yml @@ -0,0 +1,8 @@ +--- + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - set-debug + diff --git a/networks/remote/ansible/setup-fullnodes.yml b/networks/remote/ansible/setup-fullnodes.yml index 7175e4d36d..da1810d1d0 100644 --- a/networks/remote/ansible/setup-fullnodes.yml +++ b/networks/remote/ansible/setup-fullnodes.yml @@ -2,10 +2,12 @@ #GENESISFILE required #CONFIGFILE required +#BINARY required - hosts: all any_errors_fatal: true gather_facts: no roles: + - increase-openfiles - setup-fullnodes diff --git a/networks/remote/ansible/setup-validators.yml b/networks/remote/ansible/setup-validators.yml index b8cec93861..0e6f2959a0 100644 --- a/networks/remote/ansible/setup-validators.yml +++ b/networks/remote/ansible/setup-validators.yml @@ -4,5 +4,6 @@ any_errors_fatal: true gather_facts: no roles: + - increase-openfiles - setup-validators diff --git a/networks/remote/ansible/status.yml b/networks/remote/ansible/status.yml index d0b89d13f6..ebd7f72eed 100644 --- a/networks/remote/ansible/status.yml +++ b/networks/remote/ansible/status.yml @@ -9,7 +9,7 @@ - name: Gather status uri: body_format: json - url: "http://{{inventory_hostname}}:26657/status" + url: "http://{{ansible_host}}:26657/status" register: status - name: Print status diff --git a/networks/remote/terraform-app/files/terraform.sh b/networks/remote/terraform-app/files/terraform.sh index 754c5757fb..60b4dd8e72 100644 --- a/networks/remote/terraform-app/files/terraform.sh +++ b/networks/remote/terraform-app/files/terraform.sh @@ -4,13 +4,5 @@ #Usage: terraform.sh #Add gaiad node number for remote identification -echo "$2" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$2" > /etc/nodeid diff --git a/networks/remote/terraform-app/infra/attachment.tf b/networks/remote/terraform-app/infra/attachment.tf index daf9e6faab..1ba5f4fe58 100644 --- a/networks/remote/terraform-app/infra/attachment.tf +++ b/networks/remote/terraform-app/infra/attachment.tf @@ -6,10 +6,16 @@ #Instance Attachment (autoscaling is the future) resource "aws_lb_target_group_attachment" "lb_attach" { - count = "${var.SERVERS*length(data.aws_availability_zones.zones.names)}" + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" target_id = "${element(aws_instance.node.*.id,count.index)}" - port = 80 + port = 26657 } +resource "aws_lb_target_group_attachment" "lb_attach_lcd" { + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.arn}" + target_id = "${element(aws_instance.node.*.id,count.index)}" + port = 1317 +} diff --git a/networks/remote/terraform-app/infra/instance.tf b/networks/remote/terraform-app/infra/instance.tf index c2ccd5d449..53b21e62d5 100644 --- a/networks/remote/terraform-app/infra/instance.tf +++ b/networks/remote/terraform-app/infra/instance.tf @@ -13,7 +13,7 @@ data "aws_ami" "linux" { resource "aws_instance" "node" { # depends_on = ["${element(aws_route_table_association.route_table_association.*,count.index)}"] - count = "${var.SERVERS*length(data.aws_availability_zones.zones.names)}" + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" ami = "${data.aws_ami.linux.image_id}" instance_type = "${var.instance_type}" key_name = "${aws_key_pair.key.key_name}" @@ -33,7 +33,7 @@ resource "aws_instance" "node" { } root_block_device { - volume_size = 20 + volume_size = 40 } connection { @@ -47,14 +47,8 @@ resource "aws_instance" "node" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/tmp/gaiad.service" - } - provisioner "remote-exec" { inline = [ - "sudo cp /tmp/gaiad.service /etc/systemd/system/gaiad.service", "chmod +x /tmp/terraform.sh", "sudo /tmp/terraform.sh ${var.name} ${count.index}", ] diff --git a/networks/remote/terraform-app/infra/lb.tf b/networks/remote/terraform-app/infra/lb.tf index b4f6f120cb..201a53ffd8 100644 --- a/networks/remote/terraform-app/infra/lb.tf +++ b/networks/remote/terraform-app/infra/lb.tf @@ -1,20 +1,22 @@ resource "aws_lb" "lb" { name = "${var.name}" subnets = ["${aws_subnet.subnet.*.id}"] -# security_groups = ["${split(",", var.lb_security_groups)}"] + security_groups = ["${aws_security_group.secgroup.id}"] tags { Name = "${var.name}" } # access_logs { # bucket = "${var.s3_bucket}" -# prefix = "ELB-logs" +# prefix = "lblogs" # } } resource "aws_lb_listener" "lb_listener" { load_balancer_arn = "${aws_lb.lb.arn}" - port = "80" - protocol = "HTTP" + port = "443" + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06" + certificate_arn = "${var.certificate_arn}" default_action { target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" @@ -23,7 +25,6 @@ resource "aws_lb_listener" "lb_listener" { } resource "aws_lb_listener_rule" "listener_rule" { -# depends_on = ["aws_lb_target_group.lb_target_group"] listener_arn = "${aws_lb_listener.lb_listener.arn}" priority = "100" action { @@ -38,24 +39,14 @@ resource "aws_lb_listener_rule" "listener_rule" { resource "aws_lb_target_group" "lb_target_group" { name = "${var.name}" - port = "80" + port = "26657" protocol = "HTTP" vpc_id = "${aws_vpc.vpc.id}" tags { name = "${var.name}" } -# stickiness { -# type = "lb_cookie" -# cookie_duration = 1800 -# enabled = "true" -# } -# health_check { -# healthy_threshold = 3 -# unhealthy_threshold = 10 -# timeout = 5 -# interval = 10 -# path = "${var.target_group_path}" -# port = "${var.target_group_port}" -# } + health_check { + path = "/health" + } } diff --git a/networks/remote/terraform-app/infra/lcd.tf b/networks/remote/terraform-app/infra/lcd.tf new file mode 100644 index 0000000000..5d09903d0f --- /dev/null +++ b/networks/remote/terraform-app/infra/lcd.tf @@ -0,0 +1,39 @@ +resource "aws_lb_listener" "lb_listener_lcd" { + load_balancer_arn = "${aws_lb.lb.arn}" + port = "1317" + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06" + certificate_arn = "${var.certificate_arn}" + + default_action { + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.arn}" + type = "forward" + } +} + +resource "aws_lb_listener_rule" "listener_rule_lcd" { + listener_arn = "${aws_lb_listener.lb_listener_lcd.arn}" + priority = "100" + action { + type = "forward" + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.id}" + } + condition { + field = "path-pattern" + values = ["/"] + } +} + +resource "aws_lb_target_group" "lb_target_group_lcd" { + name = "${var.name}lcd" + port = "1317" + protocol = "HTTP" + vpc_id = "${aws_vpc.vpc.id}" + tags { + name = "${var.name}" + } + health_check { + path = "/node_version" + } +} + diff --git a/networks/remote/terraform-app/infra/outputs.tf b/networks/remote/terraform-app/infra/outputs.tf index 525cb0d311..fdb32611c3 100644 --- a/networks/remote/terraform-app/infra/outputs.tf +++ b/networks/remote/terraform-app/infra/outputs.tf @@ -8,9 +8,9 @@ output "instances" { value = ["${aws_instance.node.*.id}"] } -output "instances_count" { - value = "${length(aws_instance.node.*)}" -} +#output "instances_count" { +# value = "${length(aws_instance.node.*)}" +#} // The list of cluster instance public IPs output "public_ips" { diff --git a/networks/remote/terraform-app/infra/variables.tf b/networks/remote/terraform-app/infra/variables.tf index 8459e78f06..0a96f14432 100644 --- a/networks/remote/terraform-app/infra/variables.tf +++ b/networks/remote/terraform-app/infra/variables.tf @@ -17,6 +17,11 @@ variable "SERVERS" { default = "1" } +variable "max_zones" { + description = "Maximum number of availability zones to use" + default = "1" +} + variable "ssh_private_file" { description = "SSH private key file to be used to connect to the nodes" type = "string" @@ -27,3 +32,8 @@ variable "ssh_public_file" { type = "string" } +variable "certificate_arn" { + description = "Load-balancer SSL certificate AWS ARN" + type = "string" +} + diff --git a/networks/remote/terraform-app/infra/vpc.tf b/networks/remote/terraform-app/infra/vpc.tf index b38d845ca4..638ccfe0b3 100644 --- a/networks/remote/terraform-app/infra/vpc.tf +++ b/networks/remote/terraform-app/infra/vpc.tf @@ -33,7 +33,7 @@ data "aws_availability_zones" "zones" { } resource "aws_subnet" "subnet" { - count = "${length(data.aws_availability_zones.zones.names)}" + count = "${min(length(data.aws_availability_zones.zones.names),var.max_zones)}" vpc_id = "${aws_vpc.vpc.id}" availability_zone = "${element(data.aws_availability_zones.zones.names,count.index)}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, count.index)}" @@ -45,7 +45,7 @@ resource "aws_subnet" "subnet" { } resource "aws_route_table_association" "route_table_association" { - count = "${length(data.aws_availability_zones.zones.names)}" + count = "${min(length(data.aws_availability_zones.zones.names),var.max_zones)}" subnet_id = "${element(aws_subnet.subnet.*.id,count.index)}" route_table_id = "${aws_route_table.route_table.id}" } @@ -66,8 +66,15 @@ resource "aws_security_group" "secgroup" { } ingress { - from_port = 80 - to_port = 80 + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 1317 + to_port = 1317 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } diff --git a/networks/remote/terraform-app/main.tf b/networks/remote/terraform-app/main.tf index de828daf0b..687e3b5b7c 100644 --- a/networks/remote/terraform-app/main.tf +++ b/networks/remote/terraform-app/main.tf @@ -9,11 +9,16 @@ variable "SERVERS" { default = "1" } +variable "MAX_ZONES" { + description = "Maximum number of availability zones to use" + default = "4" +} + #See https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region #eu-west-3 does not contain CentOS images variable "REGION" { description = "AWS Regions" - default = "us-east-2" + default = "us-east-1" } variable "SSH_PRIVATE_FILE" { @@ -26,6 +31,11 @@ variable "SSH_PUBLIC_FILE" { type = "string" } +variable "CERTIFICATE_ARN" { + description = "Load-balancer certificate AWS ARN" + type = "string" +} + # ap-southeast-1 and ap-southeast-2 does not contain the newer CentOS 1704 image variable "image" { description = "AWS image name" @@ -34,7 +44,7 @@ variable "image" { variable "instance_type" { description = "AWS instance type" - default = "t2.medium" + default = "t2.large" } provider "aws" { @@ -48,7 +58,9 @@ module "nodes" { instance_type = "${var.instance_type}" ssh_public_file = "${var.SSH_PUBLIC_FILE}" ssh_private_file = "${var.SSH_PRIVATE_FILE}" + certificate_arn = "${var.CERTIFICATE_ARN}" SERVERS = "${var.SERVERS}" + max_zones = "${var.MAX_ZONES}" } output "public_ips" { diff --git a/networks/remote/terraform-aws/files/terraform.sh b/networks/remote/terraform-aws/files/terraform.sh index ef80199728..47363b37dd 100644 --- a/networks/remote/terraform-aws/files/terraform.sh +++ b/networks/remote/terraform-aws/files/terraform.sh @@ -7,13 +7,5 @@ REGION="$(($2 + 1))" RNODE="$(($3 + 1))" ID="$((${REGION} * 100 + ${RNODE}))" -echo "$ID" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$ID" > /etc/nodeid diff --git a/networks/remote/terraform-aws/main.tf b/networks/remote/terraform-aws/main.tf index 448695389b..41e05995e5 100644 --- a/networks/remote/terraform-aws/main.tf +++ b/networks/remote/terraform-aws/main.tf @@ -43,7 +43,7 @@ variable "image" { variable "instance_type" { description = "AWS instance type" - default = "t2.medium" + default = "t2.large" } module "nodes-0" { diff --git a/networks/remote/terraform-aws/nodes/main.tf b/networks/remote/terraform-aws/nodes/main.tf index 854f7ac2ac..825be4af62 100644 --- a/networks/remote/terraform-aws/nodes/main.tf +++ b/networks/remote/terraform-aws/nodes/main.tf @@ -79,7 +79,7 @@ resource "aws_instance" "node" { } root_block_device { - volume_size = 20 + volume_size = 40 } connection { @@ -93,14 +93,8 @@ resource "aws_instance" "node" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/tmp/gaiad.service" - } - provisioner "remote-exec" { inline = [ - "sudo cp /tmp/gaiad.service /etc/systemd/system/gaiad.service", "chmod +x /tmp/terraform.sh", "sudo /tmp/terraform.sh ${var.name} ${var.multiplier} ${count.index}", ] diff --git a/networks/remote/terraform-do/cluster/main.tf b/networks/remote/terraform-do/cluster/main.tf index 9bada59155..07331ff3d6 100644 --- a/networks/remote/terraform-do/cluster/main.tf +++ b/networks/remote/terraform-do/cluster/main.tf @@ -29,11 +29,6 @@ resource "digitalocean_droplet" "cluster" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/etc/systemd/system/gaiad.service" - } - provisioner "remote-exec" { inline = [ "chmod +x /tmp/terraform.sh", diff --git a/networks/remote/terraform-do/files/gaiad.service b/networks/remote/terraform-do/files/gaiad.service deleted file mode 100644 index 6971665670..0000000000 --- a/networks/remote/terraform-do/files/gaiad.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=gaiad -Requires=network-online.target -After=network-online.target - -[Service] -Restart=on-failure -User=gaiad -Group=gaiad -PermissionsStartOnly=true -ExecStart=/usr/bin/gaiad start -ExecReload=/bin/kill -HUP $MAINPID -KillSignal=SIGTERM - -[Install] -WantedBy=multi-user.target - diff --git a/networks/remote/terraform-do/files/terraform.sh b/networks/remote/terraform-do/files/terraform.sh index 39d89ea827..60b4dd8e72 100644 --- a/networks/remote/terraform-do/files/terraform.sh +++ b/networks/remote/terraform-do/files/terraform.sh @@ -4,16 +4,5 @@ #Usage: terraform.sh #Add gaiad node number for remote identification -echo "$2" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad -#cp -r /root/.ssh /home/gaiad/.ssh -#chown -R gaiad.gaiad /home/gaiad/.ssh -#chmod -R 700 /home/gaiad/.ssh - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$2" > /etc/nodeid From eba269632d770ade4471477db611bb5539fe6b4d Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Mon, 20 Aug 2018 11:46:27 -0400 Subject: [PATCH 06/47] DataDog update script --- networks/remote/ansible/install-datadog-agent.yml | 1 + .../roles/install-datadog-agent/tasks/main.yml | 8 -------- .../files/conf.d/http_check.d/conf.yaml | 13 +++++++++++++ .../files/conf.d/network.d/conf.yaml | 0 .../files/conf.d/process.d/conf.yaml | 0 .../files/conf.d/prometheus.d/conf.yaml | 7 +++++-- .../roles/update-datadog-agent/handlers/main.yml | 5 +++++ .../roles/update-datadog-agent/tasks/main.yml | 10 ++++++++++ .../templates/datadog.yaml.j2 | 0 networks/remote/ansible/update-datadog-agent.yml | 10 ++++++++++ 10 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/network.d/conf.yaml (100%) rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/process.d/conf.yaml (100%) rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/files/conf.d/prometheus.d/conf.yaml (51%) create mode 100644 networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml create mode 100644 networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml rename networks/remote/ansible/roles/{install-datadog-agent => update-datadog-agent}/templates/datadog.yaml.j2 (100%) create mode 100644 networks/remote/ansible/update-datadog-agent.yml diff --git a/networks/remote/ansible/install-datadog-agent.yml b/networks/remote/ansible/install-datadog-agent.yml index d324587033..54b77e1f82 100644 --- a/networks/remote/ansible/install-datadog-agent.yml +++ b/networks/remote/ansible/install-datadog-agent.yml @@ -7,4 +7,5 @@ gather_facts: no roles: - install-datadog-agent + - update-datadog-agent diff --git a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml index bba86a5ac3..0c0a49ecac 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml +++ b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml @@ -13,14 +13,6 @@ DD_API_KEY: "{{DD_API_KEY}}" DD_HOST_TAGS: "testnet:{{TESTNET_NAME}},cluster:{{CLUSTER_NAME}}" -- name: Set datadog.yaml config - template: src=datadog.yaml.j2 dest=/etc/datadog-agent/datadog.yaml - notify: restart datadog-agent - -- name: Set metrics config - copy: src=conf.d/ dest=/etc/datadog-agent/conf.d/ - notify: restart datadog-agent - - name: Disable journald rate-limiting lineinfile: "dest=/etc/systemd/journald.conf regexp={{item.regexp}} line='{{item.line}}'" with_items: diff --git a/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml new file mode 100644 index 0000000000..6932ed6f40 --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/http_check.d/conf.yaml @@ -0,0 +1,13 @@ +init_config: + +instances: + - name: gaiad + url: http://localhost:26657/status + timeout: 1 + content_match: '"latest_block_height": "0",' + reverse_content_match: true + + - name: gaiacli + url: http://localhost:1317/node_version + timeout: 1 + diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/network.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/network.d/conf.yaml similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/network.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/network.d/conf.yaml diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/process.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/process.d/conf.yaml similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/process.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/process.d/conf.yaml diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml similarity index 51% rename from networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml rename to networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml index b08908400c..20c04ceee3 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/files/conf.d/prometheus.d/conf.yaml +++ b/networks/remote/ansible/roles/update-datadog-agent/files/conf.d/prometheus.d/conf.yaml @@ -2,6 +2,9 @@ init_config: instances: - prometheus_url: http://127.0.0.1:26660 - namespace: "gaiad" metrics: - - p2p: * + - go* + - mempool* + - p2p* + - process* + - promhttp* diff --git a/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml b/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml new file mode 100644 index 0000000000..90e05c17dd --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: restart datadog-agent + service: name=datadog-agent state=restarted + diff --git a/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml new file mode 100644 index 0000000000..c6174c6af2 --- /dev/null +++ b/networks/remote/ansible/roles/update-datadog-agent/tasks/main.yml @@ -0,0 +1,10 @@ +--- + +- name: Set datadog.yaml config + template: src=datadog.yaml.j2 dest=/etc/datadog-agent/datadog.yaml + notify: restart datadog-agent + +- name: Set metrics config + copy: src=conf.d/ dest=/etc/datadog-agent/conf.d/ + notify: restart datadog-agent + diff --git a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.yaml.j2 b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 similarity index 100% rename from networks/remote/ansible/roles/install-datadog-agent/templates/datadog.yaml.j2 rename to networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 diff --git a/networks/remote/ansible/update-datadog-agent.yml b/networks/remote/ansible/update-datadog-agent.yml new file mode 100644 index 0000000000..3fe1e0006e --- /dev/null +++ b/networks/remote/ansible/update-datadog-agent.yml @@ -0,0 +1,10 @@ +--- + +#DD_API_KEY,TESTNET_NAME,CLUSTER_NAME required + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - update-datadog-agent + From 623d9fe9ff33659c51da9ad010c9fed6216348c1 Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Mon, 20 Aug 2018 15:34:06 -0400 Subject: [PATCH 07/47] ansible fixes for gaiad and gaiacli deployments --- networks/remote/ansible/roles/add-lcd/tasks/main.yml | 2 +- networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/networks/remote/ansible/roles/add-lcd/tasks/main.yml b/networks/remote/ansible/roles/add-lcd/tasks/main.yml index 11fa44c9f2..d0fbd81325 100644 --- a/networks/remote/ansible/roles/add-lcd/tasks/main.yml +++ b/networks/remote/ansible/roles/add-lcd/tasks/main.yml @@ -3,7 +3,7 @@ - name: Copy binary copy: src: "{{GAIACLI_BINARY}}" - dest: /usr/bin + dest: /usr/bin/gaiacli mode: 0755 notify: restart gaiacli diff --git a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml index ad705ada5d..0022199350 100644 --- a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml +++ b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml @@ -3,7 +3,7 @@ - name: Copy binary copy: src: "{{BINARY}}" - dest: /usr/bin + dest: /usr/bin/gaiad mode: 0755 notify: restart gaiad From 0e3883f8bff4dc187c177e643d066425affd58c1 Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Thu, 23 Aug 2018 14:51:42 -0400 Subject: [PATCH 08/47] Ansible and Terraform script updates --- PENDING.md | 2 + networks/remote/ansible/ansible.cfg | 4 - .../remote/ansible/increase-openfiles.yml | 8 ++ .../remote/ansible/install-datadog-agent.yml | 1 + .../ansible/roles/add-lcd/defaults/main.yml | 2 +- .../add-lcd/templates/gaiacli.service.j2 | 2 +- .../roles/increase-openfiles/files/50-fs.conf | 1 + .../increase-openfiles/files/91-nofiles.conf | 3 + .../increase-openfiles/files/limits.conf | 3 + .../increase-openfiles/handlers/main.yml | 5 ++ .../roles/increase-openfiles/tasks/main.yml | 22 ++++++ .../files/intake.logs.datadoghq.com.crt | 78 ------------------- .../files/logrotate.conf | 35 --------- .../roles/install-datadog-agent/files/syslog | 13 ---- .../install-datadog-agent/tasks/main.yml | 35 --------- .../templates/datadog.conf.j2 | 14 ---- .../roles/set-debug/files/sysconfig/gaiacli | 1 + .../roles/set-debug/files/sysconfig/gaiad | 1 + .../set-debug/files/sysctl.d/10-procdump | 3 + .../roles/set-debug/handlers/main.yaml | 4 + .../ansible/roles/set-debug/tasks/main.yml | 9 +++ .../setup-fullnodes}/files/gaiad.service | 0 .../roles/setup-fullnodes/handlers/main.yml | 5 ++ .../roles/setup-fullnodes/tasks/main.yml | 9 ++- .../roles/setup-journald/tasks/main.yml | 9 +++ .../setup-validators}/files/gaiad.service | 0 .../roles/setup-validators/handlers/main.yml | 5 ++ .../roles/setup-validators/tasks/main.yml | 9 ++- .../templates/datadog.yaml.j2 | 6 +- networks/remote/ansible/set-corefilesize.yml | 13 ---- networks/remote/ansible/set-debug.yml | 8 ++ networks/remote/ansible/setup-fullnodes.yml | 2 + networks/remote/ansible/setup-validators.yml | 1 + networks/remote/ansible/status.yml | 2 +- .../remote/terraform-app/files/terraform.sh | 10 +-- .../remote/terraform-app/infra/attachment.tf | 10 ++- .../remote/terraform-app/infra/instance.tf | 10 +-- networks/remote/terraform-app/infra/lb.tf | 29 +++---- networks/remote/terraform-app/infra/lcd.tf | 39 ++++++++++ .../remote/terraform-app/infra/outputs.tf | 6 +- .../remote/terraform-app/infra/variables.tf | 10 +++ networks/remote/terraform-app/infra/vpc.tf | 15 +++- networks/remote/terraform-app/main.tf | 16 +++- .../remote/terraform-aws/files/terraform.sh | 10 +-- networks/remote/terraform-aws/main.tf | 2 +- networks/remote/terraform-aws/nodes/main.tf | 8 +- networks/remote/terraform-do/cluster/main.tf | 5 -- .../remote/terraform-do/files/gaiad.service | 17 ---- .../remote/terraform-do/files/terraform.sh | 13 +--- 49 files changed, 217 insertions(+), 298 deletions(-) delete mode 100644 networks/remote/ansible/ansible.cfg create mode 100644 networks/remote/ansible/increase-openfiles.yml create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/files/limits.conf create mode 100644 networks/remote/ansible/roles/increase-openfiles/handlers/main.yml create mode 100644 networks/remote/ansible/roles/increase-openfiles/tasks/main.yml delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/files/syslog delete mode 100644 networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 create mode 100644 networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli create mode 100644 networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad create mode 100644 networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump create mode 100644 networks/remote/ansible/roles/set-debug/handlers/main.yaml create mode 100644 networks/remote/ansible/roles/set-debug/tasks/main.yml rename networks/remote/{terraform-app => ansible/roles/setup-fullnodes}/files/gaiad.service (100%) create mode 100644 networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml rename networks/remote/{terraform-aws => ansible/roles/setup-validators}/files/gaiad.service (100%) create mode 100644 networks/remote/ansible/roles/setup-validators/handlers/main.yml delete mode 100644 networks/remote/ansible/set-corefilesize.yml create mode 100644 networks/remote/ansible/set-debug.yml create mode 100644 networks/remote/terraform-app/infra/lcd.tf delete mode 100644 networks/remote/terraform-do/files/gaiad.service diff --git a/PENDING.md b/PENDING.md index dafd653fe4..b4a0c03161 100644 --- a/PENDING.md +++ b/PENDING.md @@ -80,6 +80,8 @@ IMPROVEMENTS * [x/stake] \#2000 Added tests for new staking endpoints * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. +* [tools] Improved terraform and ansible scripts for infrastructure deployment +* [tools] Added ansible script to enable process core dumps BUG FIXES * \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) diff --git a/networks/remote/ansible/ansible.cfg b/networks/remote/ansible/ansible.cfg deleted file mode 100644 index 045c1ea606..0000000000 --- a/networks/remote/ansible/ansible.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[defaults] -retry_files_enabled = False -host_key_checking = False - diff --git a/networks/remote/ansible/increase-openfiles.yml b/networks/remote/ansible/increase-openfiles.yml new file mode 100644 index 0000000000..1adcb821c1 --- /dev/null +++ b/networks/remote/ansible/increase-openfiles.yml @@ -0,0 +1,8 @@ +--- + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - increase-openfiles + diff --git a/networks/remote/ansible/install-datadog-agent.yml b/networks/remote/ansible/install-datadog-agent.yml index 54b77e1f82..b88600eae9 100644 --- a/networks/remote/ansible/install-datadog-agent.yml +++ b/networks/remote/ansible/install-datadog-agent.yml @@ -6,6 +6,7 @@ any_errors_fatal: true gather_facts: no roles: + - setup-journald - install-datadog-agent - update-datadog-agent diff --git a/networks/remote/ansible/roles/add-lcd/defaults/main.yml b/networks/remote/ansible/roles/add-lcd/defaults/main.yml index 952d016f7d..16a85e0dd3 100644 --- a/networks/remote/ansible/roles/add-lcd/defaults/main.yml +++ b/networks/remote/ansible/roles/add-lcd/defaults/main.yml @@ -1,4 +1,4 @@ --- -GAIAD_ADDRESS: tcp://0.0.0.0:1317 +GAIACLI_ADDRESS: tcp://0.0.0.0:1317 diff --git a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 index 4f189f8f5b..a0c20a5b98 100644 --- a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 +++ b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 @@ -8,7 +8,7 @@ Restart=on-failure User=gaiad Group=gaiad PermissionsStartOnly=true -ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIAD_ADDRESS}} +ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIACLI_ADDRESS}} ExecReload=/bin/kill -HUP $MAINPID KillSignal=SIGTERM diff --git a/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf b/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf new file mode 100644 index 0000000000..5193edd22e --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/50-fs.conf @@ -0,0 +1 @@ +fs.file-max=262144 diff --git a/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf b/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf new file mode 100644 index 0000000000..929081c6c9 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/91-nofiles.conf @@ -0,0 +1,3 @@ +* soft nofile 262144 +* hard nofile 262144 + diff --git a/networks/remote/ansible/roles/increase-openfiles/files/limits.conf b/networks/remote/ansible/roles/increase-openfiles/files/limits.conf new file mode 100644 index 0000000000..d3fcd2e867 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/files/limits.conf @@ -0,0 +1,3 @@ +[Service] +LimitNOFILE=infinity +LimitMEMLOCK=infinity diff --git a/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml b/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml new file mode 100644 index 0000000000..d496023003 --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemctl + systemd: name=systemd daemon_reload=yes + diff --git a/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml b/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml new file mode 100644 index 0000000000..78432f5b5a --- /dev/null +++ b/networks/remote/ansible/roles/increase-openfiles/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Based on: https://stackoverflow.com/questions/38155108/how-to-increase-limit-for-open-processes-and-files-using-ansible + +- name: Set sysctl File Limits + copy: + src: 50-fs.conf + dest: /etc/sysctl.d + +- name: Set Shell File Limits + copy: + src: 91-nofiles.conf + dest: /etc/security/limits.d + +- name: Set gaia filehandle Limits + copy: + src: limits.conf + dest: "/lib/systemd/system/{{item}}.service.d" + notify: reload systemctl + with_items: + - gaiad + - gaiacli + diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt b/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt deleted file mode 100644 index ef6d9b2c2a..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/intake.logs.datadoghq.com.crt +++ /dev/null @@ -1,78 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIESTCCAzGgAwIBAgITBn+UV4WH6Kx33rJTMlu8mYtWDTANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB -IDFCMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDCThZn3c68asg3Wuw6MLAd5tES6BIoSMzoKcG5blPVo+sDORrMd4f2AbnZ -cMzPa43j4wNxhplty6aUKk4T1qe9BOwKFjwK6zmxxLVYo7bHViXsPlJ6qOMpFge5 -blDP+18x+B26A0piiQOuPkfyDyeR4xQghfj66Yo19V+emU3nazfvpFA+ROz6WoVm -B5x+F2pV8xeKNR7u6azDdU5YVX1TawprmxRC1+WsAYmz6qP+z8ArDITC2FMVy2fw -0IjKOtEXc/VfmtTFch5+AfGYMGMqqvJ6LcXiAhqG5TI+Dr0RtM88k+8XUBCeQ8IG -KuANaL7TiItKZYxK1MMuTJtV9IblAgMBAAGjggE7MIIBNzASBgNVHRMBAf8ECDAG -AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUWaRmBlKge5WSPKOUByeW -dFv5PdAwHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH -AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy -dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy -dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js -LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBMGA1UdIAQMMAow -CAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IBAQCFkr41u3nPo4FCHOTjY3NTOVI1 -59Gt/a6ZiqyJEi+752+a1U5y6iAwYfmXss2lJwJFqMp2PphKg5625kXg8kP2CN5t -6G7bMQcT8C8xDZNtYTd7WPD8UZiRKAJPBXa30/AbwuZe0GaFEQ8ugcYQgSn+IGBI -8/LwhBNTZTUVEWuCUUBVV18YtbAiPq3yXqMB48Oz+ctBWuZSkbvkNodPLamkB2g1 -upRyzQ7qDn1X8nn8N8V7YJ6y68AtkHcNSRAnpTitxBKjtKPISLMVCx7i4hncxHZS -yLyKQXhw2W2Xs0qLeC1etA+jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF -ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj -b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x -OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1 -dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW -gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH -MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH -MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy -MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0 -LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF -AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW -MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma -eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK -bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN -0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U -akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEdTCCA12gAwIBAgIJAKcOSkw0grd/MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV -BAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTIw -MAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTAeFw0wOTA5MDIwMDAwMDBaFw0zNDA2MjgxNzM5MTZaMIGYMQswCQYDVQQGEwJV -UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjE7MDkGA1UEAxMyU3RhcmZp -ZWxkIFNlcnZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVDDrEKvlO4vW+GZdfjohTsR8/ -y8+fIBNtKTrID30892t2OGPZNmCom15cAICyL1l/9of5JUOG52kbUpqQ4XHj2C0N -Tm/2yEnZtvMaVq4rtnQU68/7JuMauh2WLmo7WJSJR1b/JaCTcFOD2oR0FMNnngRo -Ot+OQFodSk7PQ5E751bWAHDLUu57fa4657wx+UX2wmDPE1kCK4DMNEffud6QZW0C -zyyRpqbn3oUYSXxmTqM6bam17jQuug0DuDPfR+uxa40l2ZvOgdFFRjKWcIfeAg5J -Q4W2bHO7ZOphQazJ1FTfhy/HIrImzJ9ZVGif/L4qL8RVHHVAYBeFAlU5i38FAgMB -AAGjgfAwge0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O -BBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMB8GA1UdIwQYMBaAFL9ft9HO3R+G9FtV -rNzXEMIOqYjnME8GCCsGAQUFBwEBBEMwQTAcBggrBgEFBQcwAYYQaHR0cDovL28u -c3MyLnVzLzAhBggrBgEFBQcwAoYVaHR0cDovL3guc3MyLnVzL3guY2VyMCYGA1Ud -HwQfMB0wG6AZoBeGFWh0dHA6Ly9zLnNzMi51cy9yLmNybDARBgNVHSAECjAIMAYG -BFUdIAAwDQYJKoZIhvcNAQELBQADggEBACMd44pXyn3pF3lM8R5V/cxTbj5HD9/G -VfKyBDbtgB9TxF00KGu+x1X8Z+rLP3+QsjPNG1gQggL4+C/1E2DUBc7xgQjB3ad1 -l08YuW3e95ORCLp+QCztweq7dp4zBncdDQh/U90bZKuCJ/Fp1U1ervShw3WnWEQt -8jxwmKy6abaVd38PMV4s/KCHOkdp8Hlf9BRUpJVeEXgSYCfOn8J3/yNTd126/+pZ -59vPr5KW7ySaNRB6nJHGDn2Z9j8Z3/VyVOEVqQdZe4O/Ui5GjLIAZHYcSNPYeehu -VsyuLAOQ1xk4meTKCRlb/weWsKh/NEnfVqn3sF/tM+2MR7cwA130A4w= ------END CERTIFICATE----- diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf b/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf deleted file mode 100644 index e90a5ffb2c..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/logrotate.conf +++ /dev/null @@ -1,35 +0,0 @@ -# see "man logrotate" for details -# rotate log files weekly -daily - -# keep 4 days worth of backlogs -rotate 4 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we'll rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -} - -# system-specific logs may be also be configured here. diff --git a/networks/remote/ansible/roles/install-datadog-agent/files/syslog b/networks/remote/ansible/roles/install-datadog-agent/files/syslog deleted file mode 100644 index 8052df477c..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/files/syslog +++ /dev/null @@ -1,13 +0,0 @@ -/var/log/cron -/var/log/maillog -/var/log/messages -/var/log/secure -/var/log/spooler -{ - missingok - sharedscripts - postrotate - /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true - service datadog-agent restart 2> /dev/null || true - endscript -} diff --git a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml index 0c0a49ecac..4d5aa1877c 100644 --- a/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml +++ b/networks/remote/ansible/roles/install-datadog-agent/tasks/main.yml @@ -13,38 +13,3 @@ DD_API_KEY: "{{DD_API_KEY}}" DD_HOST_TAGS: "testnet:{{TESTNET_NAME}},cluster:{{CLUSTER_NAME}}" -- name: Disable journald rate-limiting - lineinfile: "dest=/etc/systemd/journald.conf regexp={{item.regexp}} line='{{item.line}}'" - with_items: - - { regexp: "^#RateLimitInterval", line: "RateLimitInterval=0s" } - - { regexp: "^#RateLimitBurst", line: "RateLimitBurst=0" } - - { regexp: "^#SystemMaxFileSize", line: "SystemMaxFileSize=500M" } - notify: restart journald - -- name: As long as Datadog does not support journald on RPM-based linux, we enable rsyslog - yum: "name={{item}} state=installed" - with_items: - - rsyslog - - rsyslog-gnutls - -#- name: Get DataDog certificate for rsyslog -# get_url: url=https://docs.datadoghq.com/crt/intake.logs.datadoghq.com.crt dest=/etc/ssl/certs/intake.logs.datadoghq.com.crt - -- name: Get DataDog certificate for rsyslog - copy: src=intake.logs.datadoghq.com.crt dest=/etc/ssl/certs/intake.logs.datadoghq.com.crt - -- name: Add datadog config to rsyslog - template: src=datadog.conf.j2 dest=/etc/rsyslog.d/datadog.conf mode=0600 - notify: restart rsyslog - -- name: Set logrotate to rotate daily so syslog does not use up all space - copy: src=logrotate.conf dest=/etc/logrotate.conf - -- name: Set syslog to restart datadog-agent after logrotate - copy: src=syslog dest=/etc/logrotate.d/syslog - -#semanage port -a -t syslog_tls_port_t -p tcp 10516 -- name: Enable rsyslog to report to port 10516 in SELinux - seport: ports=10516 proto=tcp reload=yes setype=syslog_tls_port_t state=present - notify: restart rsyslog - diff --git a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 b/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 deleted file mode 100644 index 1ab7d1b079..0000000000 --- a/networks/remote/ansible/roles/install-datadog-agent/templates/datadog.conf.j2 +++ /dev/null @@ -1,14 +0,0 @@ -$template DatadogFormat,"{{DD_API_KEY}} <%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% - - - %msg%\n" - -$imjournalRatelimitInterval 0 -$imjournalRatelimitBurst 0 - -$DefaultNetstreamDriver gtls -$DefaultNetstreamDriverCAFile /etc/ssl/certs/intake.logs.datadoghq.com.crt -$ActionSendStreamDriver gtls -$ActionSendStreamDriverMode 1 -$ActionSendStreamDriverAuthMode x509/name -$ActionSendStreamDriverPermittedPeer *.logs.datadoghq.com -*.* @@intake.logs.datadoghq.com:10516;DatadogFormat - - diff --git a/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli new file mode 100644 index 0000000000..8ef3a7e0c7 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiacli @@ -0,0 +1 @@ +DAEMON_COREFILE_LIMIT='unlimited' diff --git a/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad new file mode 100644 index 0000000000..8ef3a7e0c7 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysconfig/gaiad @@ -0,0 +1 @@ +DAEMON_COREFILE_LIMIT='unlimited' diff --git a/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump b/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump new file mode 100644 index 0000000000..fbbbe05121 --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/files/sysctl.d/10-procdump @@ -0,0 +1,3 @@ +kernel.core_uses_pid = 1 +kernel.core_pattern = /tmp/core-%e-%s-%u-%g-%p-%t +fs.suid_dumpable = 2 diff --git a/networks/remote/ansible/roles/set-debug/handlers/main.yaml b/networks/remote/ansible/roles/set-debug/handlers/main.yaml new file mode 100644 index 0000000000..743ce09bcf --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/handlers/main.yaml @@ -0,0 +1,4 @@ +--- + +- name: reload sysctl + command: "/sbin/sysctl -p" diff --git a/networks/remote/ansible/roles/set-debug/tasks/main.yml b/networks/remote/ansible/roles/set-debug/tasks/main.yml new file mode 100644 index 0000000000..7497dabd8c --- /dev/null +++ b/networks/remote/ansible/roles/set-debug/tasks/main.yml @@ -0,0 +1,9 @@ +--- +# Based on https://www.cyberciti.biz/tips/linux-core-dumps.html + +- name: Copy sysctl and sysconfig files to enable app and daemon core dumps + file: src=. dest=/etc/ + notify: reload sysctl + +- name: Enable debugging for all apps + lineinfile: create=yes line="DAEMON_COREFILE_LIMIT='unlimited'" path=/etc/sysconfig/init regexp=^DAEMON_COREFILE_LIMIT= diff --git a/networks/remote/terraform-app/files/gaiad.service b/networks/remote/ansible/roles/setup-fullnodes/files/gaiad.service similarity index 100% rename from networks/remote/terraform-app/files/gaiad.service rename to networks/remote/ansible/roles/setup-fullnodes/files/gaiad.service diff --git a/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml b/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml new file mode 100644 index 0000000000..987e2947bf --- /dev/null +++ b/networks/remote/ansible/roles/setup-fullnodes/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemd + systemd: name=gaiad enabled=yes daemon_reload=yes + diff --git a/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml b/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml index 26bcc4ccd8..ba9b22942c 100644 --- a/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-fullnodes/tasks/main.yml @@ -6,14 +6,21 @@ run_once: true become: no +- name: Create gaiad user + user: name=gaiad home=/home/gaiad shell=/bin/bash + - name: Copy binary copy: src: "{{BINARY}}" dest: /usr/bin mode: 0755 +- name: Copy service file + copy: src=gaiad.service dest=/etc/systemd/system/gaiad.service mode=0755 + notify: reload systemd + - name: Get node ID - command: "cat /etc/gaiad-nodeid" + command: "cat /etc/nodeid" changed_when: false register: nodeid diff --git a/networks/remote/ansible/roles/setup-journald/tasks/main.yml b/networks/remote/ansible/roles/setup-journald/tasks/main.yml index a7a105bf3f..130da52001 100644 --- a/networks/remote/ansible/roles/setup-journald/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-journald/tasks/main.yml @@ -5,8 +5,17 @@ with_items: - { regexp: "^#RateLimitInterval", line: "RateLimitInterval=0s" } - { regexp: "^#RateLimitBurst", line: "RateLimitBurst=0" } + - { regexp: "^#SystemMaxFileSize", line: "SystemMaxFileSize=100M" } + - { regexp: "^#SystemMaxUse", line: "SystemMaxUse=500M" } + - { regexp: "^#SystemMaxFiles", line: "SystemMaxFiles=10" } notify: restart journald +- name: Change logrotate to daily + lineinfile: "dest=/etc/logrotate.conf regexp={{item.regexp}} line='{{item.line}}'" + with_items: + - { regexp: "^weekly", line: "daily" } + - { regexp: "^#compress", line: "compress" } + - name: Create journal directory for permanent logs file: path=/var/log/journal state=directory notify: restart journald diff --git a/networks/remote/terraform-aws/files/gaiad.service b/networks/remote/ansible/roles/setup-validators/files/gaiad.service similarity index 100% rename from networks/remote/terraform-aws/files/gaiad.service rename to networks/remote/ansible/roles/setup-validators/files/gaiad.service diff --git a/networks/remote/ansible/roles/setup-validators/handlers/main.yml b/networks/remote/ansible/roles/setup-validators/handlers/main.yml new file mode 100644 index 0000000000..987e2947bf --- /dev/null +++ b/networks/remote/ansible/roles/setup-validators/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: reload systemd + systemd: name=gaiad enabled=yes daemon_reload=yes + diff --git a/networks/remote/ansible/roles/setup-validators/tasks/main.yml b/networks/remote/ansible/roles/setup-validators/tasks/main.yml index 46e9117d56..8832db4aa2 100644 --- a/networks/remote/ansible/roles/setup-validators/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-validators/tasks/main.yml @@ -6,14 +6,21 @@ run_once: true become: no +- name: Create gaiad user + user: name=gaiad home=/home/gaiad shell=/bin/bash + - name: Copy binary copy: src: "{{BINARY}}" dest: /usr/bin mode: 0755 +- name: Copy service file + copy: src=gaiad.service dest=/etc/systemd/system/gaiad.service mode=0755 + notify: reload systemd + - name: Get node ID - command: "cat /etc/gaiad-nodeid" + command: "cat /etc/nodeid" changed_when: false register: nodeid diff --git a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 index 2f3eb286e0..7e35a5255e 100644 --- a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 +++ b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 @@ -28,10 +28,10 @@ api_key: {{DD_API_KEY}} # Setting this option to "yes" will force the agent to only use TLS 1.2 when # pushing data to the url specified in "dd_url". -# force_tls_12: no +force_tls_12: yes # Force the hostname to whatever you want. (default: auto-detected) -# hostname: mymachine.mydomain +hostname: {{inventory_hostname}} # Make the agent use "hostname -f" on unix-based systems as a last resort # way of determining the hostname instead of Golang "os.Hostname()" @@ -220,7 +220,7 @@ collect_ec2_tags: true # Logs agent # # Logs agent is disabled by default -logs_enabled: true +#logs_enabled: true # # Enable logs collection for all containers, disabled by default # logs_config: diff --git a/networks/remote/ansible/set-corefilesize.yml b/networks/remote/ansible/set-corefilesize.yml deleted file mode 100644 index ae0f852913..0000000000 --- a/networks/remote/ansible/set-corefilesize.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- - -# Set the core file size to unlimited to allow the system to generate core dumps - -- hosts: all - any_errors_fatal: true - gather_facts: no - - tasks: - - - name: Set core file size to unlimited to be able to get the core dump on SIGABRT - shell: "ulimit -c unlimited" - diff --git a/networks/remote/ansible/set-debug.yml b/networks/remote/ansible/set-debug.yml new file mode 100644 index 0000000000..76ee1b3574 --- /dev/null +++ b/networks/remote/ansible/set-debug.yml @@ -0,0 +1,8 @@ +--- + +- hosts: all + any_errors_fatal: true + gather_facts: no + roles: + - set-debug + diff --git a/networks/remote/ansible/setup-fullnodes.yml b/networks/remote/ansible/setup-fullnodes.yml index 7175e4d36d..da1810d1d0 100644 --- a/networks/remote/ansible/setup-fullnodes.yml +++ b/networks/remote/ansible/setup-fullnodes.yml @@ -2,10 +2,12 @@ #GENESISFILE required #CONFIGFILE required +#BINARY required - hosts: all any_errors_fatal: true gather_facts: no roles: + - increase-openfiles - setup-fullnodes diff --git a/networks/remote/ansible/setup-validators.yml b/networks/remote/ansible/setup-validators.yml index b8cec93861..0e6f2959a0 100644 --- a/networks/remote/ansible/setup-validators.yml +++ b/networks/remote/ansible/setup-validators.yml @@ -4,5 +4,6 @@ any_errors_fatal: true gather_facts: no roles: + - increase-openfiles - setup-validators diff --git a/networks/remote/ansible/status.yml b/networks/remote/ansible/status.yml index d0b89d13f6..ebd7f72eed 100644 --- a/networks/remote/ansible/status.yml +++ b/networks/remote/ansible/status.yml @@ -9,7 +9,7 @@ - name: Gather status uri: body_format: json - url: "http://{{inventory_hostname}}:26657/status" + url: "http://{{ansible_host}}:26657/status" register: status - name: Print status diff --git a/networks/remote/terraform-app/files/terraform.sh b/networks/remote/terraform-app/files/terraform.sh index 754c5757fb..60b4dd8e72 100644 --- a/networks/remote/terraform-app/files/terraform.sh +++ b/networks/remote/terraform-app/files/terraform.sh @@ -4,13 +4,5 @@ #Usage: terraform.sh #Add gaiad node number for remote identification -echo "$2" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$2" > /etc/nodeid diff --git a/networks/remote/terraform-app/infra/attachment.tf b/networks/remote/terraform-app/infra/attachment.tf index daf9e6faab..1ba5f4fe58 100644 --- a/networks/remote/terraform-app/infra/attachment.tf +++ b/networks/remote/terraform-app/infra/attachment.tf @@ -6,10 +6,16 @@ #Instance Attachment (autoscaling is the future) resource "aws_lb_target_group_attachment" "lb_attach" { - count = "${var.SERVERS*length(data.aws_availability_zones.zones.names)}" + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" target_id = "${element(aws_instance.node.*.id,count.index)}" - port = 80 + port = 26657 } +resource "aws_lb_target_group_attachment" "lb_attach_lcd" { + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.arn}" + target_id = "${element(aws_instance.node.*.id,count.index)}" + port = 1317 +} diff --git a/networks/remote/terraform-app/infra/instance.tf b/networks/remote/terraform-app/infra/instance.tf index c2ccd5d449..53b21e62d5 100644 --- a/networks/remote/terraform-app/infra/instance.tf +++ b/networks/remote/terraform-app/infra/instance.tf @@ -13,7 +13,7 @@ data "aws_ami" "linux" { resource "aws_instance" "node" { # depends_on = ["${element(aws_route_table_association.route_table_association.*,count.index)}"] - count = "${var.SERVERS*length(data.aws_availability_zones.zones.names)}" + count = "${var.SERVERS*min(length(data.aws_availability_zones.zones.names),var.max_zones)}" ami = "${data.aws_ami.linux.image_id}" instance_type = "${var.instance_type}" key_name = "${aws_key_pair.key.key_name}" @@ -33,7 +33,7 @@ resource "aws_instance" "node" { } root_block_device { - volume_size = 20 + volume_size = 40 } connection { @@ -47,14 +47,8 @@ resource "aws_instance" "node" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/tmp/gaiad.service" - } - provisioner "remote-exec" { inline = [ - "sudo cp /tmp/gaiad.service /etc/systemd/system/gaiad.service", "chmod +x /tmp/terraform.sh", "sudo /tmp/terraform.sh ${var.name} ${count.index}", ] diff --git a/networks/remote/terraform-app/infra/lb.tf b/networks/remote/terraform-app/infra/lb.tf index b4f6f120cb..201a53ffd8 100644 --- a/networks/remote/terraform-app/infra/lb.tf +++ b/networks/remote/terraform-app/infra/lb.tf @@ -1,20 +1,22 @@ resource "aws_lb" "lb" { name = "${var.name}" subnets = ["${aws_subnet.subnet.*.id}"] -# security_groups = ["${split(",", var.lb_security_groups)}"] + security_groups = ["${aws_security_group.secgroup.id}"] tags { Name = "${var.name}" } # access_logs { # bucket = "${var.s3_bucket}" -# prefix = "ELB-logs" +# prefix = "lblogs" # } } resource "aws_lb_listener" "lb_listener" { load_balancer_arn = "${aws_lb.lb.arn}" - port = "80" - protocol = "HTTP" + port = "443" + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06" + certificate_arn = "${var.certificate_arn}" default_action { target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" @@ -23,7 +25,6 @@ resource "aws_lb_listener" "lb_listener" { } resource "aws_lb_listener_rule" "listener_rule" { -# depends_on = ["aws_lb_target_group.lb_target_group"] listener_arn = "${aws_lb_listener.lb_listener.arn}" priority = "100" action { @@ -38,24 +39,14 @@ resource "aws_lb_listener_rule" "listener_rule" { resource "aws_lb_target_group" "lb_target_group" { name = "${var.name}" - port = "80" + port = "26657" protocol = "HTTP" vpc_id = "${aws_vpc.vpc.id}" tags { name = "${var.name}" } -# stickiness { -# type = "lb_cookie" -# cookie_duration = 1800 -# enabled = "true" -# } -# health_check { -# healthy_threshold = 3 -# unhealthy_threshold = 10 -# timeout = 5 -# interval = 10 -# path = "${var.target_group_path}" -# port = "${var.target_group_port}" -# } + health_check { + path = "/health" + } } diff --git a/networks/remote/terraform-app/infra/lcd.tf b/networks/remote/terraform-app/infra/lcd.tf new file mode 100644 index 0000000000..5d09903d0f --- /dev/null +++ b/networks/remote/terraform-app/infra/lcd.tf @@ -0,0 +1,39 @@ +resource "aws_lb_listener" "lb_listener_lcd" { + load_balancer_arn = "${aws_lb.lb.arn}" + port = "1317" + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06" + certificate_arn = "${var.certificate_arn}" + + default_action { + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.arn}" + type = "forward" + } +} + +resource "aws_lb_listener_rule" "listener_rule_lcd" { + listener_arn = "${aws_lb_listener.lb_listener_lcd.arn}" + priority = "100" + action { + type = "forward" + target_group_arn = "${aws_lb_target_group.lb_target_group_lcd.id}" + } + condition { + field = "path-pattern" + values = ["/"] + } +} + +resource "aws_lb_target_group" "lb_target_group_lcd" { + name = "${var.name}lcd" + port = "1317" + protocol = "HTTP" + vpc_id = "${aws_vpc.vpc.id}" + tags { + name = "${var.name}" + } + health_check { + path = "/node_version" + } +} + diff --git a/networks/remote/terraform-app/infra/outputs.tf b/networks/remote/terraform-app/infra/outputs.tf index 525cb0d311..fdb32611c3 100644 --- a/networks/remote/terraform-app/infra/outputs.tf +++ b/networks/remote/terraform-app/infra/outputs.tf @@ -8,9 +8,9 @@ output "instances" { value = ["${aws_instance.node.*.id}"] } -output "instances_count" { - value = "${length(aws_instance.node.*)}" -} +#output "instances_count" { +# value = "${length(aws_instance.node.*)}" +#} // The list of cluster instance public IPs output "public_ips" { diff --git a/networks/remote/terraform-app/infra/variables.tf b/networks/remote/terraform-app/infra/variables.tf index 8459e78f06..0a96f14432 100644 --- a/networks/remote/terraform-app/infra/variables.tf +++ b/networks/remote/terraform-app/infra/variables.tf @@ -17,6 +17,11 @@ variable "SERVERS" { default = "1" } +variable "max_zones" { + description = "Maximum number of availability zones to use" + default = "1" +} + variable "ssh_private_file" { description = "SSH private key file to be used to connect to the nodes" type = "string" @@ -27,3 +32,8 @@ variable "ssh_public_file" { type = "string" } +variable "certificate_arn" { + description = "Load-balancer SSL certificate AWS ARN" + type = "string" +} + diff --git a/networks/remote/terraform-app/infra/vpc.tf b/networks/remote/terraform-app/infra/vpc.tf index b38d845ca4..638ccfe0b3 100644 --- a/networks/remote/terraform-app/infra/vpc.tf +++ b/networks/remote/terraform-app/infra/vpc.tf @@ -33,7 +33,7 @@ data "aws_availability_zones" "zones" { } resource "aws_subnet" "subnet" { - count = "${length(data.aws_availability_zones.zones.names)}" + count = "${min(length(data.aws_availability_zones.zones.names),var.max_zones)}" vpc_id = "${aws_vpc.vpc.id}" availability_zone = "${element(data.aws_availability_zones.zones.names,count.index)}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, count.index)}" @@ -45,7 +45,7 @@ resource "aws_subnet" "subnet" { } resource "aws_route_table_association" "route_table_association" { - count = "${length(data.aws_availability_zones.zones.names)}" + count = "${min(length(data.aws_availability_zones.zones.names),var.max_zones)}" subnet_id = "${element(aws_subnet.subnet.*.id,count.index)}" route_table_id = "${aws_route_table.route_table.id}" } @@ -66,8 +66,15 @@ resource "aws_security_group" "secgroup" { } ingress { - from_port = 80 - to_port = 80 + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 1317 + to_port = 1317 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } diff --git a/networks/remote/terraform-app/main.tf b/networks/remote/terraform-app/main.tf index de828daf0b..687e3b5b7c 100644 --- a/networks/remote/terraform-app/main.tf +++ b/networks/remote/terraform-app/main.tf @@ -9,11 +9,16 @@ variable "SERVERS" { default = "1" } +variable "MAX_ZONES" { + description = "Maximum number of availability zones to use" + default = "4" +} + #See https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region #eu-west-3 does not contain CentOS images variable "REGION" { description = "AWS Regions" - default = "us-east-2" + default = "us-east-1" } variable "SSH_PRIVATE_FILE" { @@ -26,6 +31,11 @@ variable "SSH_PUBLIC_FILE" { type = "string" } +variable "CERTIFICATE_ARN" { + description = "Load-balancer certificate AWS ARN" + type = "string" +} + # ap-southeast-1 and ap-southeast-2 does not contain the newer CentOS 1704 image variable "image" { description = "AWS image name" @@ -34,7 +44,7 @@ variable "image" { variable "instance_type" { description = "AWS instance type" - default = "t2.medium" + default = "t2.large" } provider "aws" { @@ -48,7 +58,9 @@ module "nodes" { instance_type = "${var.instance_type}" ssh_public_file = "${var.SSH_PUBLIC_FILE}" ssh_private_file = "${var.SSH_PRIVATE_FILE}" + certificate_arn = "${var.CERTIFICATE_ARN}" SERVERS = "${var.SERVERS}" + max_zones = "${var.MAX_ZONES}" } output "public_ips" { diff --git a/networks/remote/terraform-aws/files/terraform.sh b/networks/remote/terraform-aws/files/terraform.sh index ef80199728..47363b37dd 100644 --- a/networks/remote/terraform-aws/files/terraform.sh +++ b/networks/remote/terraform-aws/files/terraform.sh @@ -7,13 +7,5 @@ REGION="$(($2 + 1))" RNODE="$(($3 + 1))" ID="$((${REGION} * 100 + ${RNODE}))" -echo "$ID" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$ID" > /etc/nodeid diff --git a/networks/remote/terraform-aws/main.tf b/networks/remote/terraform-aws/main.tf index 448695389b..41e05995e5 100644 --- a/networks/remote/terraform-aws/main.tf +++ b/networks/remote/terraform-aws/main.tf @@ -43,7 +43,7 @@ variable "image" { variable "instance_type" { description = "AWS instance type" - default = "t2.medium" + default = "t2.large" } module "nodes-0" { diff --git a/networks/remote/terraform-aws/nodes/main.tf b/networks/remote/terraform-aws/nodes/main.tf index 854f7ac2ac..825be4af62 100644 --- a/networks/remote/terraform-aws/nodes/main.tf +++ b/networks/remote/terraform-aws/nodes/main.tf @@ -79,7 +79,7 @@ resource "aws_instance" "node" { } root_block_device { - volume_size = 20 + volume_size = 40 } connection { @@ -93,14 +93,8 @@ resource "aws_instance" "node" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/tmp/gaiad.service" - } - provisioner "remote-exec" { inline = [ - "sudo cp /tmp/gaiad.service /etc/systemd/system/gaiad.service", "chmod +x /tmp/terraform.sh", "sudo /tmp/terraform.sh ${var.name} ${var.multiplier} ${count.index}", ] diff --git a/networks/remote/terraform-do/cluster/main.tf b/networks/remote/terraform-do/cluster/main.tf index 9bada59155..07331ff3d6 100644 --- a/networks/remote/terraform-do/cluster/main.tf +++ b/networks/remote/terraform-do/cluster/main.tf @@ -29,11 +29,6 @@ resource "digitalocean_droplet" "cluster" { destination = "/tmp/terraform.sh" } - provisioner "file" { - source = "files/gaiad.service" - destination = "/etc/systemd/system/gaiad.service" - } - provisioner "remote-exec" { inline = [ "chmod +x /tmp/terraform.sh", diff --git a/networks/remote/terraform-do/files/gaiad.service b/networks/remote/terraform-do/files/gaiad.service deleted file mode 100644 index 6971665670..0000000000 --- a/networks/remote/terraform-do/files/gaiad.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=gaiad -Requires=network-online.target -After=network-online.target - -[Service] -Restart=on-failure -User=gaiad -Group=gaiad -PermissionsStartOnly=true -ExecStart=/usr/bin/gaiad start -ExecReload=/bin/kill -HUP $MAINPID -KillSignal=SIGTERM - -[Install] -WantedBy=multi-user.target - diff --git a/networks/remote/terraform-do/files/terraform.sh b/networks/remote/terraform-do/files/terraform.sh index 39d89ea827..60b4dd8e72 100644 --- a/networks/remote/terraform-do/files/terraform.sh +++ b/networks/remote/terraform-do/files/terraform.sh @@ -4,16 +4,5 @@ #Usage: terraform.sh #Add gaiad node number for remote identification -echo "$2" > /etc/gaiad-nodeid - -#Create gaiad user -useradd -m -s /bin/bash gaiad -#cp -r /root/.ssh /home/gaiad/.ssh -#chown -R gaiad.gaiad /home/gaiad/.ssh -#chmod -R 700 /home/gaiad/.ssh - -#Reload services to enable the gaiad service (note that the gaiad binary is not available yet) -systemctl daemon-reload -systemctl enable gaiad - +echo "$2" > /etc/nodeid From b331c4d6106740e41fdb9cc93a9c4eefbf6122f2 Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Thu, 23 Aug 2018 15:09:32 -0400 Subject: [PATCH 09/47] Fix for gaiacli service - removed 'advanced' --- .../remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 index a0c20a5b98..67cbeaee55 100644 --- a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 +++ b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 @@ -8,7 +8,7 @@ Restart=on-failure User=gaiad Group=gaiad PermissionsStartOnly=true -ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIACLI_ADDRESS}} +ExecStart=/usr/bin/gaiacli rest-server --laddr {{GAIACLI_ADDRESS}} ExecReload=/bin/kill -HUP $MAINPID KillSignal=SIGTERM From f432c0c383af189360302c72d78c25bfa5e91784 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 22 Aug 2018 12:38:55 +0100 Subject: [PATCH 10/47] Simulate transactions before actual execution * Change --gas=0 semantic in order to enable gas auto estimate. * REST clients have been modified to simulate the execution of the tx first to then populate the context with the estimated gas amount returned by the simulation. * The simulation returns both an unadjusted gas estimate and an adjusted one. The adjustment is required to ensure that the ensuing execution doesn't fail due to state changes that might have occurred. Gas adjustment can be controlled via the CLI's --gas-adjustment flag. * Tiny refactorig of REST endpoints error handling. Closes: #1246 --- baseapp/baseapp.go | 35 +++++++---- client/context/context.go | 4 ++ client/context/query.go | 7 +-- client/flags.go | 6 +- client/lcd/lcd_test.go | 58 ++++++++++------- client/lcd/version.go | 2 +- client/utils/rest.go | 12 ++++ client/utils/utils.go | 61 +++++++++++++++++- client/utils/utils_test.go | 20 ++++++ cmd/gaia/cli_test/cli_test.go | 90 ++++++++++++++++---------- x/auth/ante.go | 6 +- x/auth/ante_test.go | 2 +- x/auth/client/context/context.go | 4 +- x/auth/client/rest/query.go | 13 ++-- x/bank/client/rest/sendtx.go | 33 +++++----- x/gov/client/rest/rest.go | 105 ++++++++++--------------------- x/gov/client/rest/util.go | 37 +++++------ x/ibc/client/rest/transfer.go | 31 ++++----- x/slashing/client/rest/tx.go | 33 +++++----- x/stake/client/rest/tx.go | 75 +++++++++------------- 20 files changed, 367 insertions(+), 267 deletions(-) create mode 100644 client/utils/rest.go create mode 100644 client/utils/utils_test.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 365d7b31f2..2669aa9f30 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -495,13 +495,11 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) { // Get the context - if mode == runTxModeCheck || mode == runTxModeSimulate { - ctx = app.checkState.ctx.WithTxBytes(txBytes) - } else { - ctx = app.deliverState.ctx.WithTxBytes(txBytes) - ctx = ctx.WithSigningValidators(app.signedValidators) + ctx = getState(app, mode).ctx.WithTxBytes(txBytes) + if mode != runTxModeDeliver { + return } - + ctx = ctx.WithSigningValidators(app.signedValidators) return } @@ -567,6 +565,13 @@ func getState(app *BaseApp, mode runTxMode) *state { return app.deliverState } +func (app *BaseApp) applyTxMode(ctx sdk.Context, mode runTxMode) sdk.Context { + if mode != runTxModeSimulate { + return ctx + } + return ctx.WithMultiStore(getState(app, runTxModeSimulate).CacheMultiStore()) +} + // runTx processes a transaction. The transactions is proccessed via an // anteHandler. txBytes may be nil in some cases, eg. in tests. Also, in the // future we may support "internal" transactions. @@ -575,7 +580,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // determined by the GasMeter. We need access to the context to get the gas // meter so we initialize upfront. var gasWanted int64 + var msCache sdk.CacheMultiStore ctx := app.getContextForAnte(mode, txBytes) + ctx = app.applyTxMode(ctx, mode) defer func() { if r := recover(); r != nil { @@ -594,9 +601,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk }() var msgs = tx.GetMsgs() - - err := validateBasicTxMsgs(msgs) - if err != nil { + if err := validateBasicTxMsgs(msgs); err != nil { return err.Result() } @@ -613,9 +618,15 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk gasWanted = result.GasWanted } + if mode == runTxModeSimulate { + result = app.runMsgs(ctx, msgs, mode) + result.GasWanted = gasWanted + return + } + // Keep the state in a transient CacheWrap in case processing the messages // fails. - msCache := getState(app, mode).CacheMultiStore() + msCache = getState(app, mode).CacheMultiStore() if msCache.TracingEnabled() { msCache = msCache.WithTracingContext(sdk.TraceContext( map[string]interface{}{"txHash": cmn.HexBytes(tmhash.Sum(txBytes)).String()}, @@ -626,8 +637,8 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk result = app.runMsgs(ctx, msgs, mode) result.GasWanted = gasWanted - // only update state if all messages pass and we're not in a simulation - if result.IsOK() && mode != runTxModeSimulate { + // only update state if all messages pass + if result.IsOK() { msCache.Write() } diff --git a/client/context/context.go b/client/context/context.go index 1b0443b0c7..743c923552 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -22,6 +22,8 @@ type CLIContext struct { Client rpcclient.Client Logger io.Writer Height int64 + Gas int64 + GasAdjustment float64 NodeURI string FromAddressName string AccountStore string @@ -48,6 +50,8 @@ func NewCLIContext() CLIContext { AccountStore: ctxAccStoreName, FromAddressName: viper.GetString(client.FlagFrom), Height: viper.GetInt64(client.FlagHeight), + Gas: viper.GetInt64(client.FlagGas), + GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), TrustNode: viper.GetBool(client.FlagTrustNode), UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), diff --git a/client/context/query.go b/client/context/query.go index 68676f7415..e526c0abbc 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -27,8 +26,8 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { } // Query performs a query for information about the connected node. -func (ctx CLIContext) Query(path string) (res []byte, err error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string, data cmn.HexBytes) (res []byte, err error) { + return ctx.query(path, data) } // Query information about the connected node with a data payload @@ -284,7 +283,7 @@ func (ctx CLIContext) ensureBroadcastTx(txBytes []byte) error { // query performs a query from a Tendermint node with the provided store name // and path. -func (ctx CLIContext) query(path string, key common.HexBytes) (res []byte, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err error) { node, err := ctx.GetNode() if err != nil { return res, err diff --git a/client/flags.go b/client/flags.go index b020789057..d128d32f66 100644 --- a/client/flags.go +++ b/client/flags.go @@ -4,11 +4,14 @@ import "github.com/spf13/cobra" // nolint const ( + DefaultGasAdjustment = 0 + FlagUseLedger = "ledger" FlagChainID = "chain-id" FlagNode = "node" FlagHeight = "height" FlagGas = "gas" + FlagGasAdjustment = "gas-adjustment" FlagTrustNode = "trust-node" FlagFrom = "from" FlagName = "name" @@ -49,7 +52,8 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") - c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") + c.Flags().Int64(FlagGas, 0, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") + c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "gas adjustment to be applied on the estimate returned by the tx simulation") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 2e7ab0af7c..2db2f6d618 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -263,6 +263,10 @@ func TestCoinSend(t *testing.T) { require.Equal(t, "steak", mycoins.Denom) require.Equal(t, int64(1), mycoins.Amount.Int64()) + + // test failure with too little gas + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 100) + require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) } func TestIBCTransfer(t *testing.T) { @@ -712,7 +716,7 @@ func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account { return acc } -func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { +func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas int64) (res *http.Response, body string, receiveAddr sdk.AccAddress) { // create receive address kb := client.MockKeyBase() @@ -730,19 +734,36 @@ func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress panic(err) } - jsonStr := []byte(fmt.Sprintf(`{ - "name":"%s", - "password":"%s", - "account_number":"%d", - "sequence":"%d", - "gas": "10000", - "amount":[%s], - "chain_id":"%s" - }`, name, password, accnum, sequence, coinbz, chainID)) - res, body := Request(t, port, "POST", fmt.Sprintf("/accounts/%s/send", receiveAddr), jsonStr) + jsonStr := func() []byte { + if gas > 0 { + return []byte(fmt.Sprintf(`{ + "name":"%s", + "password":"%s", + "account_number":"%d", + "sequence":"%d", + "amount":[%s], + "chain_id":"%s", + "gas":"%v" + }`, name, password, accnum, sequence, coinbz, chainID, gas)) + } + return []byte(fmt.Sprintf(`{ + "name":"%s", + "password":"%s", + "account_number":"%d", + "sequence":"%d", + "amount":[%s], + "chain_id":"%s" + }`, name, password, accnum, sequence, coinbz, chainID)) + }() + res, body = Request(t, port, "POST", fmt.Sprintf("/accounts/%s/send", receiveAddr), jsonStr) + return +} + +func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { + res, body, receiveAddr := doSendWithGas(t, port, seed, name, password, addr, 0) require.Equal(t, http.StatusOK, res.StatusCode, body) - err = cdc.UnmarshalJSON([]byte(body), &resultTx) + err := cdc.UnmarshalJSON([]byte(body), &resultTx) require.Nil(t, err) return receiveAddr, resultTx @@ -768,7 +789,6 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc "password": "%s", "account_number":"%d", "sequence": "%d", - "gas": "100000", "src_chain_id": "%s", "amount":[ { @@ -887,7 +907,6 @@ func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, "password": "%s", "account_number": "%d", "sequence": "%d", - "gas": "10000", "chain_id": "%s", "delegations": [ { @@ -925,7 +944,6 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string, "password": "%s", "account_number": "%d", "sequence": "%d", - "gas": "20000", "chain_id": "%s", "delegations": [], "begin_unbondings": [ @@ -964,7 +982,6 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, "password": "%s", "account_number": "%d", "sequence": "%d", - "gas": "10000", "chain_id": "%s", "delegations": [], "begin_unbondings": [], @@ -1116,8 +1133,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA "password": "%s", "chain_id": "%s", "account_number":"%d", - "sequence":"%d", - "gas":"100000" + "sequence":"%d" } }`, proposerAddr, name, password, chainID, accnum, sequence)) res, body := Request(t, port, "POST", "/gov/proposals", jsonStr) @@ -1147,8 +1163,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk "password": "%s", "chain_id": "%s", "account_number":"%d", - "sequence": "%d", - "gas":"100000" + "sequence": "%d" } }`, proposerAddr, name, password, chainID, accnum, sequence)) res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr) @@ -1178,8 +1193,7 @@ func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.Ac "password": "%s", "chain_id": "%s", "account_number": "%d", - "sequence": "%d", - "gas":"100000" + "sequence": "%d" } }`, proposerAddr, name, password, chainID, accnum, sequence)) res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), jsonStr) diff --git a/client/lcd/version.go b/client/lcd/version.go index 377d7ca268..a124388e6d 100644 --- a/client/lcd/version.go +++ b/client/lcd/version.go @@ -17,7 +17,7 @@ func CLIVersionRequestHandler(w http.ResponseWriter, r *http.Request) { // connected node version REST handler endpoint func NodeVersionRequestHandler(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - version, err := cliCtx.Query("/app/version") + version, err := cliCtx.Query("/app/version", nil) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Could't query version. Error: %s", err.Error()))) diff --git a/client/utils/rest.go b/client/utils/rest.go new file mode 100644 index 0000000000..0e26403124 --- /dev/null +++ b/client/utils/rest.go @@ -0,0 +1,12 @@ +package utils + +import ( + "net/http" +) + +// WriteErrorResponse prepares and writes a HTTP error +// given a status code and an error message. +func WriteErrorResponse(w *http.ResponseWriter, status int, msg string) { + (*w).WriteHeader(status) + (*w).Write([]byte(msg)) +} diff --git a/client/utils/utils.go b/client/utils/utils.go index 8a058b56fd..9f06dda1d7 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -1,12 +1,21 @@ package utils import ( + "fmt" + "os" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/keys" sdk "github.com/cosmos/cosmos-sdk/types" authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" + amino "github.com/tendermint/go-amino" ) +// DefaultGasAdjustment is applied to gas estimates to avoid tx +// execution failures due to state changes that might +// occur between the tx simulation and the actual run. +const DefaultGasAdjustment = 1.2 + // SendTx implements a auxiliary handler that facilitates sending a series of // messages in a signed transaction given a TxContext and a QueryContext. It // ensures that the account exists, has a proper number and sequence set. In @@ -49,12 +58,62 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) return err } + txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, cliCtx.FromAddressName, passphrase, msgs) + if err != nil { + return err + } + // build and sign the transaction txBytes, err := txCtx.BuildAndSign(cliCtx.FromAddressName, passphrase, msgs) if err != nil { return err } - // broadcast to a Tendermint node return cliCtx.EnsureBroadcastTx(txBytes) } + +func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { + if cliCtx.Gas == 0 { + return EnrichTxContextWithGas(txCtx, cliCtx, name, passphrase, msgs) + } + return txCtx, nil +} + +// EnrichTxContextWithGas simulates the execution of a transaction to +// then populate the relevant TxContext.Gas field with the estimate +// obtained by the query. +func EnrichTxContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { + txCtxSimulation := txCtx.WithGas(0) + txBytes, err := txCtxSimulation.BuildAndSign(name, passphrase, msgs) + if err != nil { + return txCtx, err + } + // run a simulation (via /app/simulate query) to + // estimate gas and update TxContext accordingly + rawRes, err := cliCtx.Query("/app/simulate", txBytes) + if err != nil { + return txCtx, err + } + estimate, err := parseQueryResponse(cliCtx.Codec, rawRes) + if err != nil { + return txCtx, err + } + adjusted := adjustGasEstimate(estimate, cliCtx.GasAdjustment) + fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) + return txCtx.WithGas(adjusted), nil +} + +func adjustGasEstimate(estimate int64, adjustment float64) int64 { + if adjustment == 0 { + return int64(DefaultGasAdjustment * float64(estimate)) + } + return int64(adjustment * float64(estimate)) +} + +func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) { + var simulationResult sdk.Result + if err := cdc.UnmarshalBinary(rawRes, &simulationResult); err != nil { + return 0, err + } + return simulationResult.GasUsed, nil +} diff --git a/client/utils/utils_test.go b/client/utils/utils_test.go new file mode 100644 index 0000000000..d9ea444881 --- /dev/null +++ b/client/utils/utils_test.go @@ -0,0 +1,20 @@ +package utils + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" +) + +func TestParseQueryResponse(t *testing.T) { + cdc := app.MakeCodec() + sdkResBytes := cdc.MustMarshalBinary(sdk.Result{GasUsed: 10}) + gas, err := parseQueryResponse(cdc, sdkResBytes) + assert.Equal(t, gas, int64(10)) + assert.Nil(t, err) + gas, err = parseQueryResponse(cdc, []byte("fuzzy")) + assert.Equal(t, gas, int64(0)) + assert.NotNil(t, err) +} diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 47a1949dd2..f794e5140d 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -34,16 +34,7 @@ func init() { } func TestGaiaCLISend(t *testing.T) { - tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) - - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) + chainID, servAddr, port := initializeFixtures(t) flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) // start gaiad server @@ -86,16 +77,42 @@ func TestGaiaCLISend(t *testing.T) { require.Equal(t, int64(20), fooAcc.GetCoins().AmountOf("steak").Int64()) } -func TestGaiaCLICreateValidator(t *testing.T) { - tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) +func TestGaiaCLIGasAuto(t *testing.T) { + chainID, servAddr, port := initializeFixtures(t) + flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) + // start gaiad server + proc := tests.GoExecuteTWithStdout(t, fmt.Sprintf("gaiad start --home=%s --rpc.laddr=%v", gaiadHome, servAddr)) + + defer proc.Stop(false) + tests.WaitForTMStart(port) + tests.WaitForNextNBlocksTM(2, port) + + fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) + barAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) + + fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) + require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) + + // Test failure with auto gas disabled and very little gas set by hand + success := executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=10 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + require.False(t, success) + tests.WaitForNextNBlocksTM(2, port) + // Check state didn't change + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) + require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64()) + + // Enable auto gas + success = executeWrite(t, fmt.Sprintf("gaiacli send %v --gas=0 --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + require.True(t, success) + tests.WaitForNextNBlocksTM(2, port) + // Check state has changed accordingly + fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) + require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64()) +} + +func TestGaiaCLICreateValidator(t *testing.T) { + chainID, servAddr, port := initializeFixtures(t) flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) // start gaiad server @@ -168,15 +185,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { } func TestGaiaCLISubmitProposal(t *testing.T) { - tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) - chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) - - // get a free port, also setup some common flags - servAddr, port, err := server.FreeTCPAddr() - require.NoError(t, err) + chainID, servAddr, port := initializeFixtures(t) flags := fmt.Sprintf("--home=%s --node=%v --chain-id=%v", gaiacliHome, servAddr, chainID) // start gaiad server @@ -277,10 +286,29 @@ func getTestingHomeDirs() (string, string) { return gaiadHome, gaiacliHome } +func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { + tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) + + chainID = executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) + + // get a free port, also setup some common flags + servAddr, port, err := server.FreeTCPAddr() + require.NoError(t, err) + return +} + //___________________________________________________________________________________ // executors -func executeWrite(t *testing.T, cmdStr string, writes ...string) bool { +func executeWrite(t *testing.T, cmdStr string, writes ...string) (exitSuccess bool) { + exitSuccess, _, _ = executeWriteRetStdStreams(t, cmdStr, writes...) + return +} + +func executeWriteRetStdStreams(t *testing.T, cmdStr string, writes ...string) (bool, string, string) { proc := tests.GoExecuteT(t, cmdStr) for _, write := range writes { @@ -300,9 +328,7 @@ func executeWrite(t *testing.T, cmdStr string, writes ...string) bool { } proc.Wait() - return proc.ExitState.Success() - // bz := proc.StdoutBuffer.Bytes() - // fmt.Println("EXEC WRITE", string(bz)) + return proc.ExitState.Success(), string(stdout), string(stderr) } func executeInit(t *testing.T, cmdStr string) (chainID string) { diff --git a/x/auth/ante.go b/x/auth/ante.go index 078f376e22..dd291a4a65 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -35,7 +35,11 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler { } // set the gas meter - newCtx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas)) + if stdTx.Fee.Gas == 0 { + newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) + } else { + newCtx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas)) + } // AnteHandlers must have their own defer/recover in order // for the BaseApp to know how much gas was used! diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index 5fa04d848d..25d31b067e 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -360,7 +360,7 @@ func TestAnteHandlerMemoGas(t *testing.T) { var tx sdk.Tx msg := newTestMsg(addr1) privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} - fee := NewStdFee(0, sdk.NewInt64Coin("atom", 0)) + fee := NewStdFee(1, sdk.NewInt64Coin("atom", 0)) // tx does not have enough gas tx = newTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee) diff --git a/x/auth/client/context/context.go b/x/auth/client/context/context.go index 1cfa435ee5..8d0a94136d 100644 --- a/x/auth/client/context/context.go +++ b/x/auth/client/context/context.go @@ -110,9 +110,7 @@ func (ctx TxContext) Build(msgs []sdk.Msg) (auth.StdSignMsg, error) { Sequence: ctx.Sequence, Memo: ctx.Memo, Msgs: msgs, - - // TODO: run simulate to estimate gas? - Fee: auth.NewStdFee(ctx.Gas, fee), + Fee: auth.NewStdFee(ctx.Gas, fee), }, nil } diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index 431d3d27d5..07b109d403 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" @@ -32,15 +33,13 @@ func QueryAccountRequestHandlerFn( addr, err := sdk.AccAddressFromBech32(bech32addr) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } res, err := cliCtx.QueryStore(auth.AddressStoreKey(addr), storeName) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't query account. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("couldn't query account. Error: %s", err.Error())) return } @@ -53,16 +52,14 @@ func QueryAccountRequestHandlerFn( // decode the value account, err := decoder(res) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't parse query result. Result: %s. Error: %s", res, err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("couldn't parse query result. Result: %s. Error: %s", res, err.Error())) return } // print out whole account output, err := cdc.MarshalJSON(account) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't marshall query result. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("couldn't marshall query result. Error: %s", err.Error())) return } diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index e060a3bb4f..d27be38b57 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -47,37 +48,32 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo to, err := sdk.AccAddressFromBech32(bech32addr) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } var m sendBody body, err := ioutil.ReadAll(r.Body) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } err = msgCdc.UnmarshalJSON(body, &m) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } info, err := kb.Get(m.LocalAccountName) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } // build message msg := client.BuildMsg(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount) if err != nil { // XXX rechecking same error ? - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -89,24 +85,29 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo Sequence: m.Sequence, } + if m.Gas == 0 { + txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + if err != nil { + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + return + } + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } res, err := cliCtx.BroadcastTx(txBytes) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } output, err := wire.MarshalJSONIndent(cdc, res) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 5cdc7bda2b..d6a9199d49 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/gov" @@ -76,7 +77,7 @@ func postProposalHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.Hand msg := gov.NewMsgSubmitProposal(req.Title, req.Description, req.ProposalType, req.Proposer, req.InitialDeposit) err = msg.ValidateBasic() if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -90,10 +91,8 @@ func depositHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFu strProposalID := vars[RestProposalID] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -115,7 +114,7 @@ func depositHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFu msg := gov.NewMsgDeposit(req.Depositer, proposalID, req.Amount) err = msg.ValidateBasic() if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -129,10 +128,8 @@ func voteHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFunc strProposalID := vars[RestProposalID] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -154,7 +151,7 @@ func voteHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFunc msg := gov.NewMsgVote(req.Voter, proposalID, req.Option) err = msg.ValidateBasic() if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -168,10 +165,8 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { strProposalID := vars[RestProposalID] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -188,16 +183,13 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -212,10 +204,8 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { bechDepositerAddr := vars[RestDepositer] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -225,19 +215,15 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { } if len(bechDepositerAddr) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("depositer address required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestDepositer) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -250,16 +236,13 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/gov/deposit", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -268,14 +251,12 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { if deposit.Empty() { res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) if err != nil || len(res) == 0 { - w.WriteHeader(http.StatusNotFound) err := errors.Errorf("proposalID [%d] does not exist", proposalID) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusNotFound, err.Error()) return } - w.WriteHeader(http.StatusNotFound) err = errors.Errorf("depositer [%s] did not deposit on proposalID [%d]", bechDepositerAddr, proposalID) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusNotFound, err.Error()) return } @@ -290,9 +271,8 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { bechVoterAddr := vars[RestVoter] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -302,18 +282,15 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { } if len(bechVoterAddr) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("voter address required but not specified") - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestVoter) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -325,16 +302,13 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { } bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/gov/vote", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -343,20 +317,17 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { if vote.Empty() { bz, err := cdc.MarshalJSON(gov.QueryProposalParams{params.ProposalID}) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) if err != nil || len(res) == 0 { - w.WriteHeader(http.StatusNotFound) err := errors.Errorf("proposalID [%d] does not exist", proposalID) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusNotFound, err.Error()) return } - w.WriteHeader(http.StatusNotFound) err = errors.Errorf("voter [%s] did not deposit on proposalID [%d]", bechVoterAddr, proposalID) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusNotFound, err.Error()) return } w.Write(res) @@ -371,10 +342,8 @@ func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { strProposalID := vars[RestProposalID] if len(strProposalID) == 0 { - w.WriteHeader(http.StatusBadRequest) err := errors.New("proposalId required but not specified") - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -390,15 +359,13 @@ func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { } bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/gov/votes", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -420,9 +387,8 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { if len(bechVoterAddr) != 0 { voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestVoter) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } params.Voter = voterAddr @@ -431,10 +397,8 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { if len(bechDepositerAddr) != 0 { depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestDepositer) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } params.Depositer = depositerAddr @@ -443,10 +407,8 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { if len(strProposalStatus) != 0 { proposalStatus, err := gov.ProposalStatusFromString(strProposalStatus) if err != nil { - w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' is not a valid Proposal Status", strProposalStatus) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } params.ProposalStatus = proposalStatus @@ -461,8 +423,7 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } @@ -470,9 +431,7 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { res, err := cliCtx.QueryWithData("custom/gov/proposals", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index e6aa83cc4b..c6b360dc80 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -7,11 +7,10 @@ import ( "strconv" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" - - "github.com/pkg/errors" ) type baseReq struct { @@ -26,12 +25,12 @@ type baseReq struct { func buildReq(w http.ResponseWriter, r *http.Request, cdc *wire.Codec, req interface{}) error { body, err := ioutil.ReadAll(r.Body) if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return err } err = cdc.UnmarshalJSON(body, req) if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return err } return nil @@ -39,41 +38,36 @@ func buildReq(w http.ResponseWriter, r *http.Request, cdc *wire.Codec, req inter func (req baseReq) baseReqValidate(w http.ResponseWriter) bool { if len(req.Name) == 0 { - writeErr(&w, http.StatusUnauthorized, "Name required but not specified") + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Name required but not specified") return false } if len(req.Password) == 0 { - writeErr(&w, http.StatusUnauthorized, "Password required but not specified") + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Password required but not specified") return false } if len(req.ChainID) == 0 { - writeErr(&w, http.StatusUnauthorized, "ChainID required but not specified") + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "ChainID required but not specified") return false } if req.AccountNumber < 0 { - writeErr(&w, http.StatusUnauthorized, "Account Number required but not specified") + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Account Number required but not specified") return false } if req.Sequence < 0 { - writeErr(&w, http.StatusUnauthorized, "Sequence required but not specified") + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Sequence required but not specified") return false } return true } -func writeErr(w *http.ResponseWriter, status int, msg string) { - (*w).WriteHeader(status) - err := errors.New(msg) - (*w).Write([]byte(err.Error())) -} - // TODO: Build this function out into a more generic base-request // (probably should live in client/lcd). func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq baseReq, msg sdk.Msg, cdc *wire.Codec) { + var err error txCtx := authctx.TxContext{ Codec: cdc, AccountNumber: baseReq.AccountNumber, @@ -82,21 +76,28 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base Gas: baseReq.Gas, } + if baseReq.Gas == 0 { + txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, []sdk.Msg{msg}) + if err != nil { + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + return + } + } txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { - writeErr(&w, http.StatusUnauthorized, err.Error()) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } res, err := cliCtx.BroadcastTx(txBytes) if err != nil { - writeErr(&w, http.StatusInternalServerError, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } output, err := wire.MarshalJSONIndent(cdc, res) if err != nil { - writeErr(&w, http.StatusInternalServerError, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 4470f556e0..8c12a4b826 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -40,30 +41,26 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C to, err := sdk.AccAddressFromBech32(bech32addr) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } var m transferBody body, err := ioutil.ReadAll(r.Body) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } err = cdc.UnmarshalJSON(body, &m) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } info, err := kb.Get(m.LocalAccountName) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } @@ -79,24 +76,30 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C Gas: m.Gas, } + if m.Gas == 0 { + txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte(err.Error())) + return + } + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } res, err := cliCtx.BroadcastTx(txBytes) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } output, err := cdc.MarshalJSON(res) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 6e45230b01..956e7a5712 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -8,6 +8,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -40,34 +41,29 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI var m UnjailBody body, err := ioutil.ReadAll(r.Body) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } err = json.Unmarshal(body, &m) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error()) return } info, err := kb.Get(m.LocalAccountName) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } validatorAddr, err := sdk.AccAddressFromBech32(m.ValidatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), validatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own validator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own validator address") return } @@ -81,24 +77,29 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI msg := slashing.NewMsgUnjail(validatorAddr) + if m.Gas == 0 { + txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + if err != nil { + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + return + } + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own validator address") return } res, err := cliCtx.BroadcastTx(txBytes) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } output, err := json.MarshalIndent(res, "", " ") if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index d8b9b60113..e049212d8b 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" @@ -105,21 +106,18 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for _, msg := range m.Delegations { delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own delegator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } @@ -135,34 +133,29 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for _, msg := range m.BeginRedelegates { delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own delegator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } validatorSrcAddr, err := sdk.AccAddressFromBech32(msg.ValidatorSrcAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } validatorDstAddr, err := sdk.AccAddressFromBech32(msg.ValidatorDstAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } shares, err := sdk.NewDecFromStr(msg.SharesAmount) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())) return } @@ -179,27 +172,23 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for _, msg := range m.CompleteRedelegates { delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } validatorSrcAddr, err := sdk.AccAddressFromBech32(msg.ValidatorSrcAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } validatorDstAddr, err := sdk.AccAddressFromBech32(msg.ValidatorDstAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own delegator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } @@ -215,28 +204,24 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for _, msg := range m.BeginUnbondings { delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own delegator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } shares, err := sdk.NewDecFromStr(msg.SharesAmount) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())) return } @@ -252,21 +237,18 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for _, msg := range m.CompleteUnbondings { delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error()))) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Must use own delegator address")) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } @@ -293,10 +275,17 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex m.Sequence++ + if m.Gas == 0 { + txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + if err != nil { + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + return + } + } + txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) return } @@ -310,8 +299,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex for i, txBytes := range signedTxs { res, err := cliCtx.BroadcastTx(txBytes) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } @@ -320,8 +308,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex output, err := wire.MarshalJSONIndent(cdc, results[:]) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } From 323fac3bf7791acbaff51fb7a69eb0f9837014cb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 22 Aug 2018 12:40:07 +0100 Subject: [PATCH 11/47] Update PENDING.md --- PENDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PENDING.md b/PENDING.md index 01bdc2158b..d1f87da5ab 100644 --- a/PENDING.md +++ b/PENDING.md @@ -35,6 +35,8 @@ FEATURES * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params * [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in + * [cli] \#2047 Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. + * [cli] \#2047 The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. * Gaia From 47d55bd57217fb2adaedb6ada42b0edeb16d7b71 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 23 Aug 2018 16:10:33 +0100 Subject: [PATCH 12/47] Add/refresh docs --- docs/sdk/clients.md | 6 ++++++ docs/sdk/core/app1.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index be42a46dba..0a1c2a38d9 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -97,6 +97,12 @@ gaiacli send \ The `--amount` flag accepts the format `--amount=`. ::: +::: tip Note +You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag. +If set to 0, the gas limit will be automatically estimated. +Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.2. +::: + Now, view the updated balances of the origin and destination accounts: ```bash diff --git a/docs/sdk/core/app1.md b/docs/sdk/core/app1.md index a2978ffb08..9338d30d99 100644 --- a/docs/sdk/core/app1.md +++ b/docs/sdk/core/app1.md @@ -208,7 +208,7 @@ type Result struct { // GasWanted is the maximum units of work we allow this tx to perform. GasWanted int64 - // GasUsed is the amount of gas actually consumed. NOTE: unimplemented + // GasUsed is the amount of gas actually consumed. GasUsed int64 // Tx fee amount and denom. From e959478e61697a446762bf7863bb0fff438f6eca Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 07:34:24 +0100 Subject: [PATCH 13/47] comment getContextForAnte(), rename applyTxMode() --- baseapp/baseapp.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 2669aa9f30..2a52b7179f 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -493,6 +493,8 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { return nil } +// retrieve the context for the ante handler and store the tx bytes; store +// the signing validators if the tx runs within the deliverTx() state. func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) { // Get the context ctx = getState(app, mode).ctx.WithTxBytes(txBytes) @@ -565,7 +567,7 @@ func getState(app *BaseApp, mode runTxMode) *state { return app.deliverState } -func (app *BaseApp) applyTxMode(ctx sdk.Context, mode runTxMode) sdk.Context { +func (app *BaseApp) initializeContext(ctx sdk.Context, mode runTxMode) sdk.Context { if mode != runTxModeSimulate { return ctx } @@ -582,7 +584,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk var gasWanted int64 var msCache sdk.CacheMultiStore ctx := app.getContextForAnte(mode, txBytes) - ctx = app.applyTxMode(ctx, mode) + ctx = app.initializeContext(ctx, mode) defer func() { if r := recover(); r != nil { From 7e9ceb452db5d1f0256af66004f6f0a357863f19 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 07:35:12 +0100 Subject: [PATCH 14/47] clarifyy that adjustment is a multiplicative factor --- client/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/flags.go b/client/flags.go index d128d32f66..15cc9effa4 100644 --- a/client/flags.go +++ b/client/flags.go @@ -53,7 +53,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") c.Flags().Int64(FlagGas, 0, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") - c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "gas adjustment to be applied on the estimate returned by the tx simulation") + c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; defaults to an internal value") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") From 2dea46779c562d6af21bedd62866aed9c8813569 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 07:37:41 +0100 Subject: [PATCH 15/47] TestCoinSend: test success case when setting gas by hand --- client/lcd/lcd_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 2db2f6d618..67d8708832 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -267,6 +267,10 @@ func TestCoinSend(t *testing.T) { // test failure with too little gas res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 100) require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) + + // test success with just enough gas + res, body, _ = doSendWithGas(t, port, seed, name, password, addr, 3000) + require.Equal(t, http.StatusOK, res.StatusCode, body) } func TestIBCTransfer(t *testing.T) { From fb5fe9914d2489f15450a0b9ccde9b5c06a26e16 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 07:54:25 +0100 Subject: [PATCH 16/47] simplify json handling in LCD tests --- client/lcd/lcd_test.go | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 67d8708832..298cf0027e 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -738,27 +738,22 @@ func doSendWithGas(t *testing.T, port, seed, name, password string, addr sdk.Acc panic(err) } - jsonStr := func() []byte { - if gas > 0 { - return []byte(fmt.Sprintf(`{ - "name":"%s", - "password":"%s", - "account_number":"%d", - "sequence":"%d", - "amount":[%s], - "chain_id":"%s", - "gas":"%v" - }`, name, password, accnum, sequence, coinbz, chainID, gas)) - } - return []byte(fmt.Sprintf(`{ - "name":"%s", - "password":"%s", - "account_number":"%d", - "sequence":"%d", - "amount":[%s], - "chain_id":"%s" - }`, name, password, accnum, sequence, coinbz, chainID)) - }() + gasStr := "" + if gas > 0 { + gasStr = fmt.Sprintf(` + "gas":"%v", + `, gas) + } + jsonStr := []byte(fmt.Sprintf(`{ + %v + "name":"%s", + "password":"%s", + "account_number":"%d", + "sequence":"%d", + "amount":[%s], + "chain_id":"%s" + }`, gasStr, name, password, accnum, sequence, coinbz, chainID)) + res, body = Request(t, port, "POST", fmt.Sprintf("/accounts/%s/send", receiveAddr), jsonStr) return } From f36f749818e1f2d08cddbe52cc9c3a62a2b8c202 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 09:48:02 +0100 Subject: [PATCH 17/47] Incorporating @ValarDragon's comments --- client/utils/utils.go | 45 +++++++++++++++++++++-------------- x/bank/client/rest/sendtx.go | 17 +++++++++++-- x/gov/client/rest/util.go | 17 +++++++++++-- x/ibc/client/rest/transfer.go | 18 +++++++++++--- x/slashing/client/rest/tx.go | 17 +++++++++++-- x/stake/client/rest/tx.go | 17 +++++++++++-- 6 files changed, 102 insertions(+), 29 deletions(-) diff --git a/client/utils/utils.go b/client/utils/utils.go index 9f06dda1d7..da49ff5e03 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -9,6 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/libs/common" ) // DefaultGasAdjustment is applied to gas estimates to avoid tx @@ -58,7 +59,7 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) return err } - txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, cliCtx.FromAddressName, passphrase, msgs) + txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, passphrase, msgs) if err != nil { return err } @@ -72,35 +73,43 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) return cliCtx.EnsureBroadcastTx(txBytes) } -func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { +func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { if cliCtx.Gas == 0 { - return EnrichTxContextWithGas(txCtx, cliCtx, name, passphrase, msgs) + txBytes, err := BuildAndSignTxWithZeroGas(txCtx, cliCtx.FromAddressName, passphrase, msgs) + if err != nil { + return txCtx, err + } + estimate, adjusted, err := CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, err + } + fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) + return txCtx.WithGas(adjusted), nil } return txCtx, nil } -// EnrichTxContextWithGas simulates the execution of a transaction to -// then populate the relevant TxContext.Gas field with the estimate -// obtained by the query. -func EnrichTxContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { - txCtxSimulation := txCtx.WithGas(0) - txBytes, err := txCtxSimulation.BuildAndSign(name, passphrase, msgs) - if err != nil { - return txCtx, err - } +// BuildAndSignTxWithZeroGas builds transactions with GasWanted set to 0. +func BuildAndSignTxWithZeroGas(txCtx authctx.TxContext, name, passphrase string, msgs []sdk.Msg) ([]byte, error) { + return txCtx.WithGas(0).BuildAndSign(name, passphrase, msgs) +} + +// CalculateGas simulates the execution of a transaction and returns +// both the estimate obtained by the query and the adjusted amount. +func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *amino.Codec, txBytes []byte, adjustment float64) (estimate, adjusted int64, err error) { // run a simulation (via /app/simulate query) to // estimate gas and update TxContext accordingly - rawRes, err := cliCtx.Query("/app/simulate", txBytes) + rawRes, err := queryFunc("/app/simulate", txBytes) if err != nil { - return txCtx, err + return } - estimate, err := parseQueryResponse(cliCtx.Codec, rawRes) + estimate, err = parseQueryResponse(cdc, rawRes) if err != nil { - return txCtx, err + return } - adjusted := adjustGasEstimate(estimate, cliCtx.GasAdjustment) + adjusted = adjustGasEstimate(estimate, adjustment) fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) - return txCtx.WithGas(adjusted), nil + return } func adjustGasEstimate(estimate int64, adjustment float64) int64 { diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index d27be38b57..14bff9a49b 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -86,11 +86,12 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo } if m.Gas == 0 { - txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) if err != nil { - utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + utils.WriteErrorResponse(&w, httperr, err.Error()) return } + txCtx = newCtx } txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) @@ -114,3 +115,15 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo w.Write(output) } } + +func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { + txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) + if err != nil { + return txCtx, http.StatusInternalServerError, err + } + _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, http.StatusUnauthorized, err + } + return txCtx.WithGas(adjusted), http.StatusOK, nil +} diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index c6b360dc80..e204028310 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -77,11 +77,12 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base } if baseReq.Gas == 0 { - txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, []sdk.Msg{msg}) + newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, msg) if err != nil { - utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + utils.WriteErrorResponse(&w, httperr, err.Error()) return } + txCtx = newCtx } txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { @@ -115,3 +116,15 @@ func parseInt64OrReturnBadRequest(s string, w http.ResponseWriter) (n int64, ok } return n, true } + +func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { + txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) + if err != nil { + return txCtx, http.StatusInternalServerError, err + } + _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, http.StatusUnauthorized, err + } + return txCtx.WithGas(adjusted), http.StatusOK, nil +} diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 8c12a4b826..cf0f24b312 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -77,12 +77,12 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C } if m.Gas == 0 { - txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(&w, httperr, err.Error()) return } + txCtx = newCtx } txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) @@ -106,3 +106,15 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C w.Write(output) } } + +func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { + txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) + if err != nil { + return txCtx, http.StatusInternalServerError, err + } + _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, http.StatusUnauthorized, err + } + return txCtx.WithGas(adjusted), http.StatusOK, nil +} diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 956e7a5712..414b05cfda 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -78,11 +78,12 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI msg := slashing.NewMsgUnjail(validatorAddr) if m.Gas == 0 { - txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) if err != nil { - utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + utils.WriteErrorResponse(&w, httperr, err.Error()) return } + txCtx = newCtx } txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) @@ -106,3 +107,15 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI w.Write(output) } } + +func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { + txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) + if err != nil { + return txCtx, http.StatusInternalServerError, err + } + _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, http.StatusUnauthorized, err + } + return txCtx.WithGas(adjusted), http.StatusOK, nil +} diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index e049212d8b..729f578957 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -276,11 +276,12 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex m.Sequence++ if m.Gas == 0 { - txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) + newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) if err != nil { - utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) + utils.WriteErrorResponse(&w, httperr, err.Error()) return } + txCtx = newCtx } txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) @@ -315,3 +316,15 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex w.Write(output) } } + +func enrichContextWithGas(txCtx authcliCtx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authcliCtx.TxContext, int, error) { + txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) + if err != nil { + return txCtx, http.StatusInternalServerError, err + } + _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, http.StatusUnauthorized, err + } + return txCtx.WithGas(adjusted), http.StatusOK, nil +} From 2146450aaa101b9500970969116a02d4fd1f1d0e Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 23 Aug 2018 02:34:59 -0700 Subject: [PATCH 18/47] Fix export segfault Closes #1834 --- PENDING.md | 1 + server/export.go | 26 +++++++++++++++++++++ server/export_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++ server/mock/app.go | 8 ++++++- 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 server/export_test.go diff --git a/PENDING.md b/PENDING.md index 01bdc2158b..46e861013b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -51,6 +51,7 @@ IMPROVEMENTS * Gaia CLI (`gaiacli`) * [cli] #2060 removed `--select` from `block` command + * [cli] #2128 fixed segfault when exporting directly after `gaiad init` * Gaia * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. diff --git a/server/export.go b/server/export.go index fa1c1907a1..1d0f760ce1 100644 --- a/server/export.go +++ b/server/export.go @@ -9,6 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/wire" tmtypes "github.com/tendermint/tendermint/types" + "io/ioutil" + "path" ) // ExportCmd dumps app state to JSON. @@ -19,6 +21,21 @@ func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Co RunE: func(cmd *cobra.Command, args []string) error { home := viper.GetString("home") traceStore := viper.GetString(flagTraceStore) + emptyState, err := isEmptyState(home) + if err != nil { + return err + } + + if emptyState { + fmt.Println("WARNING: State is not initialized. Returning genesis file.") + genesisFile := path.Join(home, "config", "genesis.json") + genesis, err := ioutil.ReadFile(genesisFile) + if err != nil { + return err + } + fmt.Println(string(genesis)) + return nil + } appState, validators, err := appExporter(home, ctx.Logger, traceStore) if err != nil { @@ -43,3 +60,12 @@ func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Co }, } } + +func isEmptyState(home string) (bool, error) { + files, err := ioutil.ReadDir(path.Join(home, "data")) + if err != nil { + return false, err + } + + return len(files) == 0, nil +} diff --git a/server/export_test.go b/server/export_test.go new file mode 100644 index 0000000000..358f72cf60 --- /dev/null +++ b/server/export_test.go @@ -0,0 +1,53 @@ +package server + +import ( + "testing" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/tendermint/tendermint/libs/log" + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + "os" + "bytes" + "io" + "github.com/cosmos/cosmos-sdk/server/mock" + ) + +func TestEmptyState(t *testing.T) { + defer setupViper(t)() + logger := log.NewNopLogger() + cfg, err := tcmd.ParseConfig() + require.Nil(t, err) + ctx := NewContext(cfg, logger) + cdc := wire.NewCodec() + appInit := AppInit{ + AppGenTx: mock.AppGenTx, + AppGenState: mock.AppGenStateEmpty, + } + cmd := InitCmd(ctx, cdc, appInit) + err = cmd.RunE(nil, nil) + require.NoError(t, err) + + old := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + cmd = ExportCmd(ctx, cdc, nil) + err = cmd.RunE(nil, nil) + require.NoError(t, err) + + outC := make(chan string) + go func() { + var buf bytes.Buffer + io.Copy(&buf, r) + outC <- buf.String() + }() + + w.Close() + os.Stdout = old + out := <-outC + require.Contains(t, out, "WARNING: State is not initialized") + require.Contains(t, out, "genesis_time") + require.Contains(t, out, "chain_id") + require.Contains(t, out, "consensus_params") + require.Contains(t, out, "validators") + require.Contains(t, out, "app_hash") +} diff --git a/server/mock/app.go b/server/mock/app.go index 7b22328b06..eb2dfc3cc3 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -121,9 +121,15 @@ func AppGenState(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMessage, return } +// AppGenStateEmpty returns an empty transaction state for mocking. +func AppGenStateEmpty(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMessage, err error) { + appState = json.RawMessage(``) + return +} + // Return a validator, not much else func AppGenTx(_ *wire.Codec, pk crypto.PubKey, genTxConfig gc.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { + appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { validator = tmtypes.GenesisValidator{ PubKey: pk, From 7e8feec73833e3c793f6268b289f82778e48cb33 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 24 Aug 2018 14:57:45 +0100 Subject: [PATCH 19/47] Incorporating @cwgoes comments --- baseapp/baseapp.go | 11 +++++------ client/flags.go | 4 ++-- client/utils/utils.go | 33 +++++++++++++++++---------------- x/bank/client/rest/sendtx.go | 16 ++-------------- x/gov/client/rest/util.go | 16 ++-------------- x/ibc/client/rest/transfer.go | 16 ++-------------- x/slashing/client/rest/tx.go | 16 ++-------------- x/stake/client/rest/tx.go | 16 ++-------------- 8 files changed, 34 insertions(+), 94 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 2a52b7179f..20faf06cd0 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -498,10 +498,9 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) { // Get the context ctx = getState(app, mode).ctx.WithTxBytes(txBytes) - if mode != runTxModeDeliver { - return + if mode == runTxModeDeliver { + ctx = ctx.WithSigningValidators(app.signedValidators) } - ctx = ctx.WithSigningValidators(app.signedValidators) return } @@ -568,10 +567,10 @@ func getState(app *BaseApp, mode runTxMode) *state { } func (app *BaseApp) initializeContext(ctx sdk.Context, mode runTxMode) sdk.Context { - if mode != runTxModeSimulate { - return ctx + if mode == runTxModeSimulate { + ctx = ctx.WithMultiStore(getState(app, runTxModeSimulate).CacheMultiStore()) } - return ctx.WithMultiStore(getState(app, runTxModeSimulate).CacheMultiStore()) + return ctx } // runTx processes a transaction. The transactions is proccessed via an diff --git a/client/flags.go b/client/flags.go index 15cc9effa4..7337e97411 100644 --- a/client/flags.go +++ b/client/flags.go @@ -4,7 +4,7 @@ import "github.com/spf13/cobra" // nolint const ( - DefaultGasAdjustment = 0 + DefaultGasAdjustment = 1.2 FlagUseLedger = "ledger" FlagChainID = "chain-id" @@ -53,7 +53,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") c.Flags().Int64(FlagGas, 0, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") - c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; defaults to an internal value") + c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") diff --git a/client/utils/utils.go b/client/utils/utils.go index da49ff5e03..fb5d619887 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -59,9 +59,11 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) return err } - txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, passphrase, msgs) - if err != nil { - return err + if cliCtx.Gas == 0 { + txCtx, err = EnrichCtxWithGas(txCtx, cliCtx, cliCtx.FromAddressName, passphrase, msgs) + if err != nil { + return err + } } // build and sign the transaction @@ -73,20 +75,19 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg) return cliCtx.EnsureBroadcastTx(txBytes) } -func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { - if cliCtx.Gas == 0 { - txBytes, err := BuildAndSignTxWithZeroGas(txCtx, cliCtx.FromAddressName, passphrase, msgs) - if err != nil { - return txCtx, err - } - estimate, adjusted, err := CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, err - } - fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) - return txCtx.WithGas(adjusted), nil +// EnrichCtxWithGas calculates the gas estimate that would be consumed by the +// transaction and set the transaction's respective value accordingly. +func EnrichCtxWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { + txBytes, err := BuildAndSignTxWithZeroGas(txCtx, name, passphrase, msgs) + if err != nil { + return txCtx, err } - return txCtx, nil + estimate, adjusted, err := CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) + if err != nil { + return txCtx, err + } + fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) + return txCtx.WithGas(adjusted), nil } // BuildAndSignTxWithZeroGas builds transactions with GasWanted set to 0. diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 14bff9a49b..c7baa96910 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -86,9 +86,9 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo } if m.Gas == 0 { - newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) + newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - utils.WriteErrorResponse(&w, httperr, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } txCtx = newCtx @@ -115,15 +115,3 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo w.Write(output) } } - -func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { - txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) - if err != nil { - return txCtx, http.StatusInternalServerError, err - } - _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, http.StatusUnauthorized, err - } - return txCtx.WithGas(adjusted), http.StatusOK, nil -} diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index e204028310..f98f7bfa59 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -77,9 +77,9 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base } if baseReq.Gas == 0 { - newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, msg) + newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, []sdk.Msg{msg}) if err != nil { - utils.WriteErrorResponse(&w, httperr, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } txCtx = newCtx @@ -116,15 +116,3 @@ func parseInt64OrReturnBadRequest(s string, w http.ResponseWriter) (n int64, ok } return n, true } - -func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { - txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) - if err != nil { - return txCtx, http.StatusInternalServerError, err - } - _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, http.StatusUnauthorized, err - } - return txCtx.WithGas(adjusted), http.StatusOK, nil -} diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index cf0f24b312..765208b056 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -77,9 +77,9 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C } if m.Gas == 0 { - newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) + newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - utils.WriteErrorResponse(&w, httperr, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } txCtx = newCtx @@ -106,15 +106,3 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C w.Write(output) } } - -func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { - txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) - if err != nil { - return txCtx, http.StatusInternalServerError, err - } - _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, http.StatusUnauthorized, err - } - return txCtx.WithGas(adjusted), http.StatusOK, nil -} diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 414b05cfda..26412ebc00 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -78,9 +78,9 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI msg := slashing.NewMsgUnjail(validatorAddr) if m.Gas == 0 { - newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) + newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - utils.WriteErrorResponse(&w, httperr, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } txCtx = newCtx @@ -107,15 +107,3 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI w.Write(output) } } - -func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { - txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) - if err != nil { - return txCtx, http.StatusInternalServerError, err - } - _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, http.StatusUnauthorized, err - } - return txCtx.WithGas(adjusted), http.StatusOK, nil -} diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index 729f578957..3d7d419a3a 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -276,9 +276,9 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex m.Sequence++ if m.Gas == 0 { - newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg) + newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) if err != nil { - utils.WriteErrorResponse(&w, httperr, err.Error()) + utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) return } txCtx = newCtx @@ -316,15 +316,3 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex w.Write(output) } } - -func enrichContextWithGas(txCtx authcliCtx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authcliCtx.TxContext, int, error) { - txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg}) - if err != nil { - return txCtx, http.StatusInternalServerError, err - } - _, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment) - if err != nil { - return txCtx, http.StatusUnauthorized, err - } - return txCtx.WithGas(adjusted), http.StatusOK, nil -} From f6cb4d4fb66970c3b8e31b009db9a02e14cabae4 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Fri, 24 Aug 2018 10:18:17 -0700 Subject: [PATCH 20/47] Speedup IAVL iterator by removing defers when unneeded. Note each defer occurs a 30ish ns overhead here, which is significant for IAVL iteration. We were previously using around 3-4 defers. (2 in next, one in Valid, one in Key, one in Value) This slows down the entire application quite significantly, as we require fast iteration. --- Gopkg.lock | 53 +++++++++++++++++++++-------------------- PENDING.md | 1 + store/iavlstore.go | 35 +++++++++++++++++---------- store/iavlstore_test.go | 23 ++++++++++++++++++ 4 files changed, 73 insertions(+), 39 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 81591a0ae3..fa6fafb99d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,11 +34,11 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" + revision = "d81d8877b8f327112e94e814937143a71d1692a7" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" + digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" + digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" + digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -230,12 +231,12 @@ version = "v1.0.1" [[projects]] - branch = "master" - digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" + digest = "1:645110e089152bd0f4a011a2648fbb0e4df5977be73ca605781157ac297f50c4" name = "github.com/mitchellh/mapstructure" packages = ["."] pruneopts = "UT" - revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" + revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8" + version = "v1.0.0" [[projects]] digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" @@ -262,7 +263,7 @@ version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" + digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +274,7 @@ [[projects]] branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +282,7 @@ [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" + digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +294,7 @@ [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" + digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +313,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +332,7 @@ version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" + digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -363,7 +364,7 @@ version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" + digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +376,7 @@ [[projects]] branch = "master" - digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" + digest = "1:442d2ffa75ffae302ce8800bf4144696b92bef02917923ea132ce2d39efe7d65" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +397,7 @@ [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" + digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +424,7 @@ version = "v0.9.2" [[projects]] - digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6" + digest = "1:963f6c04345ce36f900c1d6367200eebc3cc2db6ee632ff865ea8dcf64b748a0" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -490,7 +491,7 @@ version = "v0.23.1-rc0" [[projects]] - digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e" + digest = "1:ad879bb8c71020a3f92f0c61f414d93eae1d5dc2f37023b6abaa3cc84b00165e" name = "github.com/tendermint/tmlibs" packages = ["cli"] pruneopts = "UT" @@ -506,7 +507,7 @@ [[projects]] branch = "master" - digest = "1:27507554c6d4f060d8d700c31c624a43d3a92baa634e178ddc044bdf7d13b44a" + digest = "1:2a3ce1f08dcae8bac666deb6e4c88b5d7170c510da38fd746231144cac351704" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -528,7 +529,7 @@ revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" + digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" name = "golang.org/x/net" packages = [ "context", @@ -545,17 +546,17 @@ [[projects]] branch = "master" - digest = "1:a0e12bc26f317c0e2d497baf767285e1790e526e8dd46553c5a67fcbc8692157" + digest = "1:c8baf78f0ac6eb27c645e264fe5e8a74d5a50db188ab41a7ff3b275c112e0735" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" + revision = "11551d06cbcc94edc80a0facaccbda56473c19c1" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" name = "golang.org/x/text" packages = [ "collate", @@ -586,7 +587,7 @@ revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" name = "google.golang.org/grpc" packages = [ ".", diff --git a/PENDING.md b/PENDING.md index 01bdc2158b..426f368a39 100644 --- a/PENDING.md +++ b/PENDING.md @@ -59,6 +59,7 @@ IMPROVEMENTS * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. + * [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143) * Tendermint diff --git a/store/iavlstore.go b/store/iavlstore.go index 6ab50dfc96..daffa7dd55 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -332,39 +332,42 @@ func (iter *iavlIterator) Domain() (start, end []byte) { func (iter *iavlIterator) Valid() bool { iter.waitInit() iter.mtx.Lock() - defer iter.mtx.Unlock() - return !iter.invalid + validity := !iter.invalid + iter.mtx.Unlock() + return validity } // Implements Iterator. func (iter *iavlIterator) Next() { iter.waitInit() iter.mtx.Lock() - defer iter.mtx.Unlock() - iter.assertIsValid() + iter.assertIsValid(true) iter.receiveNext() + iter.mtx.Unlock() } // Implements Iterator. func (iter *iavlIterator) Key() []byte { iter.waitInit() iter.mtx.Lock() - defer iter.mtx.Unlock() - iter.assertIsValid() + iter.assertIsValid(true) - return iter.key + key := iter.key + iter.mtx.Unlock() + return key } // Implements Iterator. func (iter *iavlIterator) Value() []byte { iter.waitInit() iter.mtx.Lock() - defer iter.mtx.Unlock() - iter.assertIsValid() + iter.assertIsValid(true) - return iter.value + val := iter.value + iter.mtx.Unlock() + return val } // Implements Iterator. @@ -375,14 +378,14 @@ func (iter *iavlIterator) Close() { //---------------------------------------- func (iter *iavlIterator) setNext(key, value []byte) { - iter.assertIsValid() + iter.assertIsValid(false) iter.key = key iter.value = value } func (iter *iavlIterator) setInvalid() { - iter.assertIsValid() + iter.assertIsValid(false) iter.invalid = true } @@ -400,8 +403,14 @@ func (iter *iavlIterator) receiveNext() { } } -func (iter *iavlIterator) assertIsValid() { +// assertIsValid panics if the iterator is invalid. If unlockMutex is true, +// it also unlocks the mutex before panicing, to prevent deadlocks in code that +// recovers from panics +func (iter *iavlIterator) assertIsValid(unlockMutex bool) { if iter.invalid { + if unlockMutex { + iter.mtx.Unlock() + } panic("invalid iterator") } } diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 38d85c6581..793089a26e 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -464,3 +464,26 @@ func TestIAVLStoreQuery(t *testing.T) { require.Equal(t, uint32(sdk.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) } + +func BenchmarkIAVLIteratorNext(b *testing.B) { + db := dbm.NewMemDB() + treeSize := 1000 + tree := iavl.NewVersionedTree(db, cacheSize) + for i := 0; i < treeSize; i++ { + key := cmn.RandBytes(4) + value := cmn.RandBytes(50) + tree.Set(key, value) + } + iavlStore := newIAVLStore(tree, numRecent, storeEvery) + iterators := make([]Iterator, b.N/treeSize) + for i := 0; i < len(iterators); i++ { + iterators[i] = iavlStore.Iterator([]byte{0}, []byte{255, 255, 255, 255, 255}) + } + b.ResetTimer() + for i := 0; i < len(iterators); i++ { + iter := iterators[i] + for j := 0; j < treeSize; j++ { + iter.Next() + } + } +} From 639161100515156455c5349096268d4f61f8caa7 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Wed, 22 Aug 2018 18:44:35 -0700 Subject: [PATCH 21/47] asdf --- x/gov/client/cli/tx.go | 246 +++++++++++++++++++++++--------------- x/gov/client/rest/rest.go | 43 +++++++ 2 files changed, 190 insertions(+), 99 deletions(-) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 2a7e71aac8..26883b9c37 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -13,11 +13,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov" "encoding/json" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" "io/ioutil" "strings" + + "github.com/spf13/cobra" + "github.com/spf13/viper" ) const ( @@ -252,20 +252,21 @@ func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { cliCtx := context.NewCLIContext().WithCodec(cdc) proposalID := viper.GetInt64(flagProposalID) - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if len(res) == 0 || err != nil { - return errors.Errorf("proposalID [%d] is not existed", proposalID) + params := gov.QueryProposalParams{ + ProposalID: proposalID, } - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - output, err := wire.MarshalJSONIndent(cdc, proposal) + bz, err := cdc.MarshalJSON(params) if err != nil { return err } - fmt.Println(string(output)) + res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) + if err != nil { + return err + } + + fmt.Println(string(res)) return nil }, } @@ -287,88 +288,47 @@ func GetCmdQueryProposals(storeName string, cdc *wire.Codec) *cobra.Command { strProposalStatus := viper.GetString(flagStatus) latestProposalsIDs := viper.GetInt64(flagLatestProposalIDs) - var err error - var voterAddr sdk.AccAddress - var depositerAddr sdk.AccAddress - var proposalStatus gov.ProposalStatus + params := gov.QueryProposalsParams{ + NumLatestProposals: latestProposalsIDs, + } if len(bechDepositerAddr) != 0 { - depositerAddr, err = sdk.AccAddressFromBech32(bechDepositerAddr) + depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr) if err != nil { return err } + params.Depositer = depositerAddr } if len(bechVoterAddr) != 0 { - voterAddr, err = sdk.AccAddressFromBech32(bechVoterAddr) + voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr) if err != nil { return err } + params.Voter = voterAddr } if len(strProposalStatus) != 0 { - proposalStatus, err = gov.ProposalStatusFromString(strProposalStatus) + proposalStatus, err := gov.ProposalStatusFromString(strProposalStatus) if err != nil { return err } + params.ProposalStatus = proposalStatus + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + return err } cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyNextProposalID, storeName) + res, err := cliCtx.QueryWithData("custom/gov/proposals", bz) if err != nil { return err } - var maxProposalID int64 - cdc.MustUnmarshalBinary(res, &maxProposalID) - - matchingProposals := []gov.Proposal{} - - if latestProposalsIDs == 0 { - latestProposalsIDs = maxProposalID - } - - for proposalID := maxProposalID - latestProposalsIDs; proposalID < maxProposalID; proposalID++ { - if voterAddr != nil { - res, err = cliCtx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName) - if err != nil || len(res) == 0 { - continue - } - } - - if depositerAddr != nil { - res, err = cliCtx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName) - if err != nil || len(res) == 0 { - continue - } - } - - res, err = cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - continue - } - - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - if len(strProposalStatus) != 0 { - if proposal.GetStatus() != proposalStatus { - continue - } - } - - matchingProposals = append(matchingProposals, proposal) - } - - if len(matchingProposals) == 0 { - fmt.Println("No matching proposals found") - return nil - } - - for _, proposal := range matchingProposals { - fmt.Printf(" %d - %s\n", proposal.GetProposalID(), proposal.GetTitle()) - } + fmt.Println(string(res)) return nil }, } @@ -396,20 +356,21 @@ func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName) - if len(res) == 0 || err != nil { - return errors.Errorf("proposalID [%d] does not exist", proposalID) + params := gov.QueryVoteParams{ + Voter: voterAddr, + ProposalID: proposalID, } - - var vote gov.Vote - cdc.MustUnmarshalBinary(res, &vote) - - output, err := wire.MarshalJSONIndent(cdc, vote) + bz, err := cdc.MarshalJSON(params) if err != nil { return err } - fmt.Println(string(output)) + res, err := cliCtx.QueryWithData("custom/gov/vote", bz) + if err != nil { + return err + } + + fmt.Println(string(res)) return nil }, } @@ -429,37 +390,20 @@ func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { cliCtx := context.NewCLIContext().WithCodec(cdc) proposalID := viper.GetInt64(flagProposalID) - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if len(res) == 0 || err != nil { - return errors.Errorf("proposalID [%d] does not exist", proposalID) + params := gov.QueryVotesParams{ + ProposalID: proposalID, } - - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - if proposal.GetStatus() != gov.StatusVotingPeriod { - fmt.Println("Proposal not in voting period.") - return nil - } - - res2, err := cliCtx.QuerySubspace(gov.KeyVotesSubspace(proposalID), storeName) + bz, err := cdc.MarshalJSON(params) if err != nil { return err } - var votes []gov.Vote - for i := 0; i < len(res2); i++ { - var vote gov.Vote - cdc.MustUnmarshalBinary(res2[i].Value, &vote) - votes = append(votes, vote) - } - - output, err := wire.MarshalJSONIndent(cdc, votes) + res, err := cliCtx.QueryWithData("custom/gov/votes", bz) if err != nil { return err } - fmt.Println(string(output)) + fmt.Println(string(res)) return nil }, } @@ -468,3 +412,107 @@ func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { return cmd } + +// Command to Get a specific Deposit Information +// GetCmdQueryDeposit implements the query proposal deposit command. +func GetCmdQueryDeposit(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "query-deposit", + Short: "query deposit", + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + proposalID := viper.GetInt64(flagProposalID) + + depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer)) + if err != nil { + return err + } + + params := gov.QueryDepositParams{ + Depositer: depositerAddr, + ProposalID: proposalID, + } + bz, err := cdc.MarshalJSON(params) + if err != nil { + return err + } + + res, err := cliCtx.QueryWithData("custom/gov/deposit", bz) + if err != nil { + return err + } + + fmt.Println(string(res)) + return nil + }, + } + + cmd.Flags().String(flagProposalID, "", "proposalID of proposal deposited on") + cmd.Flags().String(flagDepositer, "", "bech32 depositer address") + + return cmd +} + +// GetCmdQueryDeposits implements the command to query for proposal deposits. +func GetCmdQueryDeposits(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "query-deposits", + Short: "query deposits on a proposal", + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + proposalID := viper.GetInt64(flagProposalID) + + params := gov.QueryDepositsParams{ + ProposalID: proposalID, + } + bz, err := cdc.MarshalJSON(params) + if err != nil { + return err + } + + res, err := cliCtx.QueryWithData("custom/gov/deposits", bz) + if err != nil { + return err + } + + fmt.Println(string(res)) + return nil + }, + } + + cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's deposits are being queried") + + return cmd +} + +// GetCmdQueryDeposits implements the command to query for proposal deposits. +func GetCmdQueryTally(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "query-tally", + Short: "get the tally of a proposal vote", + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + proposalID := viper.GetInt64(flagProposalID) + + params := gov.QueryTallyParams{ + ProposalID: proposalID, + } + bz, err := cdc.MarshalJSON(params) + if err != nil { + return err + } + + res, err := cliCtx.QueryWithData("custom/gov/tally", bz) + if err != nil { + return err + } + + fmt.Println(string(res)) + return nil + }, + } + + cmd.Flags().String(flagProposalID, "", "proposalID of which proposal is being tallied") + + return cmd +} diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 5cdc7bda2b..ebe6123141 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -479,3 +479,46 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { w.Write(res) } } + +// nolint: gocyclo +// todo: Split this functionality into helper functions to remove the above +func queryTallyOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strProposalID := vars[RestProposalID] + + if len(strProposalID) == 0 { + w.WriteHeader(http.StatusBadRequest) + err := errors.New("proposalId required but not specified") + w.Write([]byte(err.Error())) + + return + } + + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { + return + } + + cliCtx := context.NewCLIContext().WithCodec(cdc) + + params := gov.QueryTallyParams{ + ProposalID: proposalID, + } + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + res, err := cliCtx.QueryWithData("custom/gov/tally", bz) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Write(res) + } +} From 96fc6c6f7b3e79248c74237958bdd0d48144aca2 Mon Sep 17 00:00:00 2001 From: Jordan Bibla Date: Fri, 24 Aug 2018 15:05:40 -0400 Subject: [PATCH 22/47] double curlies breaks vuepress - single curlies does not --- docs/RELEASE_PROCESS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index 503c5d3fa0..8ff722b335 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -4,7 +4,7 @@ - [ ] 2. Add commits/PRs that are desired for this release **that haven’t already been added to develop** - [ ] 3. Merge items in `PENDING.md` into the `CHANGELOG.md`. While doing this make sure that each entry contains links to issues/PRs for each item - [ ] 4. Summarize breaking API changes section under “Breaking Changes” section to the `CHANGELOG.md` to bring attention to any breaking API changes that affect RPC consumers. -- [ ] 5. Tag the commit `{{ .Release.Name }}-rcN` +- [ ] 5. Tag the commit `{ .Release.Name }-rcN` - [ ] 6. Kick off 1 day of automated fuzz testing - [ ] 7. Release Lead assigns 2 people to perform [buddy testing script](/docs/RELEASE_TEST_SCRIPT.md) and update the relevant documentation - [ ] 8. If errors are found in either #6 or #7 go back to #2 (*NOTE*: be sure to increment the `rcN`) From 76a16ab288b388eb8a036313f2efcfff410819db Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 25 Aug 2018 20:12:14 +0100 Subject: [PATCH 23/47] Modify AnteHandler to take a simulate boolean parameter --- baseapp/baseapp.go | 2 +- baseapp/baseapp_test.go | 12 ++--- client/flags.go | 3 +- client/utils/utils_test.go | 38 ++++++++++++++++ docs/sdk/core/examples/app2.go | 2 +- types/handler.go | 2 +- x/auth/ante.go | 4 +- x/auth/ante_test.go | 80 +++++++++++++++++----------------- x/params/msg_status.go | 2 +- 9 files changed, 93 insertions(+), 52 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 20faf06cd0..60c694ff76 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -608,7 +608,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // run the ante handler if app.anteHandler != nil { - newCtx, result, abort := app.anteHandler(ctx, tx) + newCtx, result, abort := app.anteHandler(ctx, tx, (mode == runTxModeSimulate)) if abort { return result } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 269424e589..04e47214dd 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -365,7 +365,7 @@ func testTxDecoder(cdc *wire.Codec) sdk.TxDecoder { } func anteHandlerTxTest(t *testing.T, capKey *sdk.KVStoreKey, storeKey []byte) sdk.AnteHandler { - return func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { + return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { store := ctx.KVStore(capKey) msgCounter := tx.(txTest).Counter res = incrementingCounter(t, store, storeKey, msgCounter) @@ -595,7 +595,7 @@ func TestSimulateTx(t *testing.T) { gasConsumed := int64(5) anteOpt := func(bapp *BaseApp) { - bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { + bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasConsumed)) return }) @@ -659,7 +659,9 @@ func TestSimulateTx(t *testing.T) { func TestRunInvalidTransaction(t *testing.T) { anteOpt := func(bapp *BaseApp) { - bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return }) + bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { + return + }) } routerOpt := func(bapp *BaseApp) { bapp.Router().AddRoute(typeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) @@ -734,7 +736,7 @@ func TestRunInvalidTransaction(t *testing.T) { func TestTxGasLimits(t *testing.T) { gasGranted := int64(10) anteOpt := func(bapp *BaseApp) { - bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { + bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasGranted)) // NOTE/TODO/XXX: @@ -825,7 +827,7 @@ func TestTxGasLimits(t *testing.T) { func TestQuery(t *testing.T) { key, value := []byte("hello"), []byte("goodbye") anteOpt := func(bapp *BaseApp) { - bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { + bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { store := ctx.KVStore(capKey1) store.Set(key, value) return diff --git a/client/flags.go b/client/flags.go index 7337e97411..81e0670678 100644 --- a/client/flags.go +++ b/client/flags.go @@ -4,6 +4,7 @@ import "github.com/spf13/cobra" // nolint const ( + DefaultGasLimit = 200000 DefaultGasAdjustment = 1.2 FlagUseLedger = "ledger" @@ -52,7 +53,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") - c.Flags().Int64(FlagGas, 0, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") + c.Flags().Int64(FlagGas, DefaultGasLimit, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") diff --git a/client/utils/utils_test.go b/client/utils/utils_test.go index d9ea444881..731ded903f 100644 --- a/client/utils/utils_test.go +++ b/client/utils/utils_test.go @@ -1,11 +1,13 @@ package utils import ( + "errors" "testing" "github.com/cosmos/cosmos-sdk/cmd/gaia/app" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/libs/common" ) func TestParseQueryResponse(t *testing.T) { @@ -18,3 +20,39 @@ func TestParseQueryResponse(t *testing.T) { assert.Equal(t, gas, int64(0)) assert.NotNil(t, err) } + +func TestCalculateGas(t *testing.T) { + cdc := app.MakeCodec() + makeQueryFunc := func(gasUsed int64, wantErr bool) func(string, common.HexBytes) ([]byte, error) { + return func(string, common.HexBytes) ([]byte, error) { + if wantErr { + return nil, errors.New("") + } + return cdc.MustMarshalBinary(sdk.Result{GasUsed: gasUsed}), nil + } + } + type args struct { + queryFuncGasUsed int64 + queryFuncWantErr bool + adjustment float64 + } + tests := []struct { + name string + args args + wantEstimate int64 + wantAdjusted int64 + wantErr bool + }{ + {"error", args{0, true, 1.2}, 0, 0, true}, + {"adjusted gas", args{10, false, 1.2}, 10, 12, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + queryFunc := makeQueryFunc(tt.args.queryFuncGasUsed, tt.args.queryFuncWantErr) + gotEstimate, gotAdjusted, err := CalculateGas(queryFunc, cdc, []byte(""), tt.args.adjustment) + assert.Equal(t, err != nil, tt.wantErr) + assert.Equal(t, gotEstimate, tt.wantEstimate) + assert.Equal(t, gotAdjusted, tt.wantAdjusted) + }) + } +} diff --git a/docs/sdk/core/examples/app2.go b/docs/sdk/core/examples/app2.go index 3c7f71f6d6..5f23abe071 100644 --- a/docs/sdk/core/examples/app2.go +++ b/docs/sdk/core/examples/app2.go @@ -211,7 +211,7 @@ func tx2Decoder(cdc *wire.Codec) sdk.TxDecoder { // Simple anteHandler that ensures msg signers have signed. // Provides no replay protection. -func antehandler(ctx sdk.Context, tx sdk.Tx) (_ sdk.Context, _ sdk.Result, abort bool) { +func antehandler(ctx sdk.Context, tx sdk.Tx, simulate bool) (_ sdk.Context, _ sdk.Result, abort bool) { appTx, ok := tx.(app2Tx) if !ok { // set abort boolean to true so that we don't continue to process failed tx diff --git a/types/handler.go b/types/handler.go index 3a50e0ce05..b978e8e51e 100644 --- a/types/handler.go +++ b/types/handler.go @@ -5,4 +5,4 @@ type Handler func(ctx Context, msg Msg) Result // AnteHandler authenticates transactions, before their internal messages are handled. // If newCtx.IsZero(), ctx is used instead. -type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool) +type AnteHandler func(ctx Context, tx Tx, simulate bool) (newCtx Context, result Result, abort bool) diff --git a/x/auth/ante.go b/x/auth/ante.go index dd291a4a65..c0a129be3e 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -25,7 +25,7 @@ const ( func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler { return func( - ctx sdk.Context, tx sdk.Tx, + ctx sdk.Context, tx sdk.Tx, simulate bool, ) (newCtx sdk.Context, res sdk.Result, abort bool) { // This AnteHandler requires Txs to be StdTxs @@ -35,7 +35,7 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler { } // set the gas meter - if stdTx.Fee.Gas == 0 { + if simulate { newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) } else { newCtx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas)) diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index 25d31b067e..a841bc7760 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -39,16 +39,16 @@ func privAndAddr() (crypto.PrivKey, sdk.AccAddress) { } // run the tx through the anteHandler and ensure its valid -func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx) { - _, result, abort := anteHandler(ctx, tx) +func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool) { + _, result, abort := anteHandler(ctx, tx, simulate) require.False(t, abort) require.Equal(t, sdk.ABCICodeOK, result.Code) require.True(t, result.IsOK()) } // run the tx through the anteHandler and ensure it fails with the given code -func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, code sdk.CodeType) { - newCtx, result, abort := anteHandler(ctx, tx) +func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, code sdk.CodeType) { + newCtx, result, abort := anteHandler(ctx, tx, simulate) require.True(t, abort) require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), result.Code, fmt.Sprintf("Expected %v, got %v", sdk.ToABCICode(sdk.CodespaceRoot, code), result)) @@ -140,23 +140,23 @@ func TestAnteHandlerSigErrors(t *testing.T) { require.Equal(t, expectedSigners, stdTx.GetSigners()) // Check no signatures fails - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) // test num sigs dont match GetSigners privs, accNums, seqs = []crypto.PrivKey{priv1}, []int64{0}, []int64{0} tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) // test an unrecognized account privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{0, 0, 0} tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnknownAddress) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress) // save the first account, but second is still unrecognized acc1 := mapper.NewAccountWithAddress(ctx, addr1) acc1.SetCoins(fee.Amount) mapper.SetAccount(ctx, acc1) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnknownAddress) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress) } // Test logic around account number checking with one signer and many signers. @@ -192,17 +192,17 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { // test good tx from one signer privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // new tx from wrong account number seqs = []int64{1} tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence) // from correct account number seqs = []int64{1} tx = newTestTx(ctx, msgs, privs, []int64{0}, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // new tx with another signer and incorrect account numbers msg1 := newTestMsg(addr1, addr2) @@ -210,12 +210,12 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { msgs = []sdk.Msg{msg1, msg2} privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{1, 0}, []int64{2, 0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence) // correct account numbers privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{2, 0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) } // Test logic around sequence checking with one signer and many signers. @@ -255,15 +255,15 @@ func TestAnteHandlerSequences(t *testing.T) { // test good tx from one signer privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // test sending it again fails (replay protection) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence) // fix sequence, should pass seqs = []int64{1} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // new tx with another signer and correct sequences msg1 := newTestMsg(addr1, addr2) @@ -272,28 +272,28 @@ func TestAnteHandlerSequences(t *testing.T) { privs, accnums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{2, 0, 0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // replay fails - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence) // tx from just second signer with incorrect sequence fails msg = newTestMsg(addr2) msgs = []sdk.Msg{msg} privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{1}, []int64{0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence) // fix the sequence and it passes tx = newTestTx(ctx, msgs, []crypto.PrivKey{priv2}, []int64{1}, []int64{1}, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // another tx from both of them that passes msg = newTestMsg(addr1, addr2) msgs = []sdk.Msg{msg} privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{3, 2} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) } // Test logic around fee deduction. @@ -323,17 +323,17 @@ func TestAnteHandlerFees(t *testing.T) { // signer does not have enough funds to pay the fee tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds) acc1.SetCoins(sdk.Coins{sdk.NewInt64Coin("atom", 149)}) mapper.SetAccount(ctx, acc1) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds) require.True(t, feeCollector.GetCollectedFees(ctx).IsEqual(emptyCoins)) acc1.SetCoins(sdk.Coins{sdk.NewInt64Coin("atom", 150)}) mapper.SetAccount(ctx, acc1) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) require.True(t, feeCollector.GetCollectedFees(ctx).IsEqual(sdk.Coins{sdk.NewInt64Coin("atom", 150)})) } @@ -360,26 +360,26 @@ func TestAnteHandlerMemoGas(t *testing.T) { var tx sdk.Tx msg := newTestMsg(addr1) privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} - fee := NewStdFee(1, sdk.NewInt64Coin("atom", 0)) + fee := NewStdFee(0, sdk.NewInt64Coin("atom", 0)) // tx does not have enough gas tx = newTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) // tx with memo doesn't have enough gas fee = NewStdFee(801, sdk.NewInt64Coin("atom", 0)) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd") - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) // memo too large fee = NewStdFee(2001, sdk.NewInt64Coin("atom", 0)) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsd") - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeMemoTooLarge) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeMemoTooLarge) // tx with memo has enough gas fee = NewStdFee(1100, sdk.NewInt64Coin("atom", 0)) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd") - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) } func TestAnteHandlerMultiSigner(t *testing.T) { @@ -420,17 +420,17 @@ func TestAnteHandlerMultiSigner(t *testing.T) { privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{0, 0, 0} tx = newTestTxWithMemo(ctx, msgs, privs, accnums, seqs, fee, "Check signers are in expected order and different account numbers works") - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // change sequence numbers tx = newTestTx(ctx, []sdk.Msg{msg1}, []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{1, 1}, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) tx = newTestTx(ctx, []sdk.Msg{msg2}, []crypto.PrivKey{priv3, priv1}, []int64{2, 0}, []int64{1, 2}, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) // expected seqs = [3, 2, 2] tx = newTestTxWithMemo(ctx, msgs, privs, accnums, []int64{3, 2, 2}, fee, "Check signers are in expected order and different account numbers and sequence numbers works") - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) } func TestAnteHandlerBadSignBytes(t *testing.T) { @@ -467,7 +467,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { // test good tx and signBytes privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) chainID := ctx.ChainID() chainID2 := chainID + "somemorestuff" @@ -497,20 +497,20 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { StdSignBytes(cs.chainID, cs.accnum, cs.seq, cs.fee, cs.msgs, ""), "", ) - checkInvalidTx(t, anteHandler, ctx, tx, cs.code) + checkInvalidTx(t, anteHandler, ctx, tx, false, cs.code) } // test wrong signer if public key exist privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{0}, []int64{1} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) // test wrong signer if public doesn't exist msg = newTestMsg(addr2) msgs = []sdk.Msg{msg} privs, accnums, seqs = []crypto.PrivKey{priv1}, []int64{1}, []int64{0} tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) } @@ -544,7 +544,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) { privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} fee := newStdFee() tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkValidTx(t, anteHandler, ctx, tx) + checkValidTx(t, anteHandler, ctx, tx, false) acc1 = mapper.GetAccount(ctx, addr1) require.Equal(t, acc1.GetPubKey(), priv1.PubKey()) @@ -555,14 +555,14 @@ func TestAnteHandlerSetPubKey(t *testing.T) { tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee) sigs := tx.(StdTx).GetSignatures() sigs[0].PubKey = nil - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) acc2 = mapper.GetAccount(ctx, addr2) require.Nil(t, acc2.GetPubKey()) // test invalid signature and public key tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) acc2 = mapper.GetAccount(ctx, addr2) require.Nil(t, acc2.GetPubKey()) diff --git a/x/params/msg_status.go b/x/params/msg_status.go index 72704e4dc7..7f9197c5c1 100644 --- a/x/params/msg_status.go +++ b/x/params/msg_status.go @@ -24,7 +24,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { // NewAnteHandler returns an AnteHandler that checks // whether msg type is activate or not func NewAnteHandler(k Keeper) sdk.AnteHandler { - return func(ctx sdk.Context, tx sdk.Tx) (sdk.Context, sdk.Result, bool) { + return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, sdk.Result, bool) { for _, msg := range tx.GetMsgs() { ok := k.Getter().GetBoolWithDefault(ctx, ActivatedParamKey(msg.Type()), false) if !ok { From 305589faf4a6b34fa3d17ed78ce475a5e2416330 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 26 Aug 2018 16:41:08 -0700 Subject: [PATCH 24/47] Update bech32 human readable spec to simply "cosmos" (#2103) Update bech32 human readable to simply "cosmos" --- docs/spec/other/bech32.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/spec/other/bech32.md b/docs/spec/other/bech32.md index 1d337ef6c3..866c4b6a40 100644 --- a/docs/spec/other/bech32.md +++ b/docs/spec/other/bech32.md @@ -7,12 +7,12 @@ In the Cosmos network, keys and addresses may refer to a number of different rol ## HRP table -| HRP | Definition | +| HRP | Definition | | ------------- |:-------------:| -| `cosmosaccaddr` | Cosmos Account Address | -| `cosmosaccpub` | Cosmos Account Public Key | -| `cosmosvaladdr` | Cosmos Consensus Address | -| `cosmosvalpub` | Cosmos Consensus Public Key| +| `cosmos` | Cosmos Account Address | +| `cosmospub` | Cosmos Account Public Key | +| `cosmosval` | Cosmos Validator Consensus Address | +| `cosmosval` | Cosmos Validator Consensus Public Key| ## Encoding @@ -22,4 +22,4 @@ To covert between other binary reprsentation of addresses and keys, it is import A complete implementation of the Amino serialization format is unncessary in most cases. Simply prepending bytes from this [table](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography) to the bytestring payload before bech32 encoding will sufficient for compatible representation. -  \ No newline at end of file +  From bec53fb1dfdb243ef96eefcd25450e19ab752442 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 26 Aug 2018 16:44:51 -0700 Subject: [PATCH 25/47] fixed bech32 for validator pubkeys --- docs/spec/other/bech32.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/spec/other/bech32.md b/docs/spec/other/bech32.md index 866c4b6a40..1558c1ec37 100644 --- a/docs/spec/other/bech32.md +++ b/docs/spec/other/bech32.md @@ -12,7 +12,7 @@ In the Cosmos network, keys and addresses may refer to a number of different rol | `cosmos` | Cosmos Account Address | | `cosmospub` | Cosmos Account Public Key | | `cosmosval` | Cosmos Validator Consensus Address | -| `cosmosval` | Cosmos Validator Consensus Public Key| +| `cosmosvalpub`| Cosmos Validator Consensus Public Key| ## Encoding From 44517556007371a6fd871d70a430c4c45f3a7626 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sun, 26 Aug 2018 18:04:52 -0700 Subject: [PATCH 26/47] simulation: rename TestAndRunTx to Operation, make timestamp randomized --- PENDING.md | 2 ++ cmd/gaia/app/sim_test.go | 4 ++-- x/bank/simulation/msgs.go | 2 +- x/bank/simulation/sim_test.go | 2 +- x/gov/simulation/msgs.go | 6 +++--- x/gov/simulation/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 18 ++++++++++++------ x/mock/simulation/types.go | 13 +++++++++---- x/slashing/simulation/msgs.go | 2 +- x/stake/simulation/msgs.go | 14 +++++++------- x/stake/simulation/sim_test.go | 2 +- 11 files changed, 40 insertions(+), 27 deletions(-) diff --git a/PENDING.md b/PENDING.md index 46e861013b..51d80bd5be 100644 --- a/PENDING.md +++ b/PENDING.md @@ -23,6 +23,7 @@ BREAKING CHANGES * [core] \#1807 Switch from use of rational to decimal * [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() * [types] \#2119 Parsed error messages and ABCI log errors to make them more human readable. + * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint @@ -60,6 +61,7 @@ IMPROVEMENTS * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. + * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 5fa75a9313..9036c7e145 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -85,8 +85,8 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json return appState } -func testAndRunTxs(app *GaiaApp) []simulation.TestAndRunTx { - return []simulation.TestAndRunTx{ +func testAndRunTxs(app *GaiaApp) []simulation.Operation { + return []simulation.Operation{ banksim.TestAndRunSingleInputMsgSend(app.accountMapper), govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 43d7e1fd70..633f6787fc 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -20,7 +20,7 @@ import ( // TestAndRunSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both // accounts already exist. -func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.TestAndRunTx { +func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { fromKey := simulation.RandomKey(r, keys) fromAddr := sdk.AccAddress(fromKey.PubKey().Address()) diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 8fedeca795..88e7a5f3a3 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -33,7 +33,7 @@ func TestBankWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ TestAndRunSingleInputMsgSend(mapper), }, []simulation.RandSetup{}, diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index ed80ab4e63..f270d3a7d0 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -21,7 +21,7 @@ const ( ) // SimulateMsgSubmitProposal -func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) @@ -50,7 +50,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd } // SimulateMsgDeposit -func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) @@ -77,7 +77,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgVote -func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 691aa1cd2d..6f0f9830cd 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -55,7 +55,7 @@ func TestGovWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ SimulateMsgSubmitProposal(govKeeper, stakeKeeper), SimulateMsgDeposit(govKeeper, stakeKeeper), SimulateMsgVote(govKeeper, stakeKeeper), diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index c7e6166149..5b1d4030c9 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -3,6 +3,7 @@ package simulation import ( "encoding/json" "fmt" + "math" "math/rand" "sort" "testing" @@ -20,7 +21,7 @@ import ( // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { time := time.Now().UnixNano() @@ -30,12 +31,20 @@ func Simulate( // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) - fmt.Printf("%s\n", log) r := rand.New(rand.NewSource(seed)) + + unixTime := r.Int63n(int64(math.Pow(2, 40))) + + // Set the timestamp for simulation + timestamp := time.Unix(unixTime, 0) + log = fmt.Sprintf("%s\nStarting the simulation from time %v, unixtime %v", log, timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) + fmt.Printf("%s\n", log) + timeDiff := maxTimePerBlock - minTimePerBlock + keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) // Setup event stats @@ -45,9 +54,6 @@ func SimulateFromSeed( events[what]++ } - timestamp := time.Unix(0, 0) - timeDiff := maxTimePerBlock - minTimePerBlock - res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) validators := make(map[string]mockValidator) for _, validator := range res.Validators { diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 35769b0b25..3ece3c2e9f 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -11,10 +11,15 @@ import ( ) type ( - // TestAndRunTx produces a fuzzed transaction, and ensures the state - // transition was as expected. It returns a descriptive message "action" - // about what this fuzzed tx actually did, for ease of debugging. - TestAndRunTx func( + // Operation runs a state machine transition, + // and ensures the transition happened as expected. + // The operation could be running and testing a fuzzed transaction, + // or doing the same for a message. + // + // For ease of debugging, + // an operation returns a descriptive message "action", + // which details what this fuzzed state machine transition actually did. + Operation func( t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string), ) (action string, err sdk.Error) diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index 8ef24493be..e694bd1d70 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -16,7 +16,7 @@ import ( ) // SimulateMsgUnjail -func SimulateMsgUnjail(k slashing.Keeper) simulation.TestAndRunTx { +func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) address := sdk.AccAddress(key.PubKey().Address()) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 17f9808931..995e4f3580 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -18,7 +18,7 @@ import ( ) // SimulateMsgCreateValidator -func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ @@ -55,7 +55,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation } // SimulateMsgEditValidator -func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -83,7 +83,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgDelegate -func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -115,7 +115,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAn } // SimulateMsgBeginUnbonding -func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -147,7 +147,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. } // SimulateMsgCompleteUnbonding -func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -170,7 +170,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgBeginRedelegate -func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) @@ -206,7 +206,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation } // SimulateMsgCompleteRedelegate -func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 84745cd1d4..c5d301c569 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -44,7 +44,7 @@ func TestStakeWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ SimulateMsgCreateValidator(mapper, stakeKeeper), SimulateMsgEditValidator(stakeKeeper), SimulateMsgDelegate(mapper, stakeKeeper), From 909a68ed654efb694747fd0b9ed475dd202db2f4 Mon Sep 17 00:00:00 2001 From: Greg Szabo <16846635+greg-szabo@users.noreply.github.com> Date: Mon, 27 Aug 2018 12:34:16 -0400 Subject: [PATCH 27/47] Updating config.js for docs website build process This change will put the documentation to the right folder for website deployment. --- docs/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.js b/docs/config.js index 61607b1b08..42df9de92d 100644 --- a/docs/config.js +++ b/docs/config.js @@ -1,7 +1,7 @@ module.exports = { title: "Cosmos Network", description: "Documentation for the Cosmos Network.", - dest: "./site-docs", + dest: "./dist/docs", base: "/", markdown: { lineNumbers: true From 855222e8c343fa10e2ff46cf968614ae2e493625 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 27 Aug 2018 14:27:00 -0700 Subject: [PATCH 28/47] simulation: Allow operations to specify future operations The intent of this is to allow for simulating things like slashing for not voting on a governance proposal. To test this, you would queue all the validator votes in future blocks, and keep track of which ones you didn't slash. Then you could add queue a "check governance slashing operation" after the voting period is over. --- PENDING.md | 1 + cmd/gaia/app/sim_test.go | 6 +-- x/bank/simulation/msgs.go | 12 +++--- x/bank/simulation/sim_test.go | 2 +- x/gov/simulation/msgs.go | 19 +++++----- x/mock/simulation/random_simulate_blocks.go | 42 ++++++++++++++++++++- x/mock/simulation/types.go | 14 ++++++- x/slashing/simulation/msgs.go | 4 +- x/stake/simulation/msgs.go | 36 +++++++++--------- 9 files changed, 94 insertions(+), 42 deletions(-) diff --git a/PENDING.md b/PENDING.md index cee2ae14c4..f413a18009 100644 --- a/PENDING.md +++ b/PENDING.md @@ -41,6 +41,7 @@ FEATURES * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers + * [simulation] \#1924 allow operations to specify future operations * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 9036c7e145..0ca936bdbf 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -3,7 +3,6 @@ package app import ( "encoding/json" "flag" - "fmt" "math/rand" "testing" @@ -87,7 +86,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json func testAndRunTxs(app *GaiaApp) []simulation.Operation { return []simulation.Operation{ - banksim.TestAndRunSingleInputMsgSend(app.accountMapper), + banksim.SimulateSingleInputMsgSend(app.accountMapper), govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), @@ -171,11 +170,10 @@ func TestAppStateDeterminism(t *testing.T) { true, ) appHash := app.LastCommitID().Hash - fmt.Printf(">>> APP HASH: %v, %X\n", appHash, appHash) appHashList[j] = appHash } for k := 1; k < numTimesToRunPerSeed; k++ { - require.Equal(t, appHashList[0], appHashList[k]) + require.Equal(t, appHashList[0], appHashList[k], "appHash list: %v", appHashList) } } } diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 633f6787fc..e3f3ab77b8 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -18,10 +18,10 @@ import ( "github.com/tendermint/tendermint/crypto" ) -// TestAndRunSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both +// SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both // accounts already exist. -func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { +func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { fromKey := simulation.RandomKey(r, keys) fromAddr := sdk.AccAddress(fromKey.PubKey().Address()) toKey := simulation.RandomKey(r, keys) @@ -36,13 +36,13 @@ func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operatio initFromCoins := mapper.GetAccount(ctx, fromAddr).GetCoins() if len(initFromCoins) == 0 { - return "skipping, no coins at all", nil + return "skipping, no coins at all", nil, nil } denomIndex := r.Intn(len(initFromCoins)) amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) if goErr != nil { - return "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, nil + return "skipping bank send due to account having no coins of denomination " + initFromCoins[denomIndex].Denom, nil, nil } action = fmt.Sprintf("%s is sending %s %s to %s", @@ -61,7 +61,7 @@ func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operatio sendAndVerifyMsgSend(t, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey}) event("bank/sendAndVerifyMsgSend/ok") - return action, nil + return action, nil, nil } } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 88e7a5f3a3..f61f72b4fa 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -34,7 +34,7 @@ func TestBankWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, []simulation.Operation{ - TestAndRunSingleInputMsgSend(mapper), + SimulateSingleInputMsgSend(mapper), }, []simulation.RandSetup{}, []simulation.Invariant{ diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index f270d3a7d0..0b1530138f 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -20,9 +20,10 @@ const ( denom = "steak" ) -// SimulateMsgSubmitProposal +// SimulateMsgSubmitProposal simulates a msg Submit Proposal +// Note: Currently doesn't ensure that the proposal txt is in JSON form func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) deposit := randomDeposit(r) @@ -45,18 +46,18 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operati } event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgDeposit func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) proposalID, ok := randomProposalID(r, k, ctx) if !ok { - return "no-operation", nil + return "no-operation", nil, nil } deposit := randomDeposit(r) msg := gov.NewMsgDeposit(addr, proposalID, deposit) @@ -72,18 +73,18 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { } event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK())) action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgVote func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) proposalID, ok := randomProposalID(r, k, ctx) if !ok { - return "no-operation", nil + return "no-operation", nil, nil } option := randomVotingOption(r) msg := gov.NewMsgVote(addr, proposalID, option) @@ -95,7 +96,7 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { } event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK())) action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 5b1d4030c9..995013ef8f 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -70,6 +70,8 @@ func SimulateFromSeed( request := abci.RequestBeginBlock{Header: header} var pastTimes []time.Time + // These are operations which have been queued by previous operations + operationQueue := make(map[int][]Operation) for i := 0; i < numBlocks; i++ { @@ -96,9 +98,14 @@ func SimulateFromSeed( default: thisBlockSize = r.Intn(blockSize * 4) } + // Run queued operations. Ignores blocksize if blocksize is too small + log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), t, r, app, ctx, keys, log, event) + opCount += numQueuedOpsRan + thisBlockSize -= numQueuedOpsRan for j := 0; j < thisBlockSize; j++ { - logUpdate, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) + logUpdate, futureOps, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) log += "\n" + logUpdate + queueOperations(operationQueue, futureOps) require.Nil(t, err, log) if onOperation { @@ -134,6 +141,39 @@ func SimulateFromSeed( DisplayEvents(events) } +// adds all future operations into the operation queue. +func queueOperations(queuedOperations map[int][]Operation, futureOperations []FutureOperation) { + if futureOperations == nil { + return + } + for _, futureOp := range futureOperations { + if val, ok := queuedOperations[futureOp.BlockHeight]; ok { + queuedOperations[futureOp.BlockHeight] = append(val, futureOp.Op) + } else { + queuedOperations[futureOp.BlockHeight] = []Operation{futureOp.Op} + } + } +} + +func runQueuedOperations(queueOperations map[int][]Operation, height int, t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + privKeys []crypto.PrivKey, log string, event func(string)) (updatedLog string, numOpsRan int) { + updatedLog = log + if queuedOps, ok := queueOperations[height]; ok { + numOps := len(queuedOps) + for i := 0; i < numOps; i++ { + // For now, queued operations cannot queue more operations. + // If a need arises for us to support queued messages to queue more messages, this can + // be changed. + logUpdate, _, err := queuedOps[i](t, r, app, ctx, privKeys, updatedLog, event) + updatedLog += "\n" + logUpdate + require.Nil(t, err, updatedLog) + } + delete(queueOperations, height) + return updatedLog, numOps + } + return log, 0 +} + func getKeys(validators map[string]mockValidator) []string { keys := make([]string, len(validators)) i := 0 diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 3ece3c2e9f..2516e07ae5 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -19,10 +19,13 @@ type ( // For ease of debugging, // an operation returns a descriptive message "action", // which details what this fuzzed state machine transition actually did. + // + // Operations can optionally provide a list of "FutureOperations" to run later + // These will be ran at the beginning of the corresponding block. Operation func( t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string), - ) (action string, err sdk.Error) + ) (action string, futureOperations []FutureOperation, err sdk.Error) // RandSetup performs the random setup the mock module needs. RandSetup func(r *rand.Rand, privKeys []crypto.PrivKey) @@ -36,6 +39,15 @@ type ( val abci.Validator livenessState int } + + // FutureOperation is an operation which will be ran at the + // beginning of the provided BlockHeight. + // In the (likely) event that multiple operations are queued at the same + // block height, they will execute in a FIFO pattern. + FutureOperation struct { + BlockHeight int + Op Operation + } ) // PeriodicInvariant returns an Invariant function closure that asserts diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index e694bd1d70..e4900889e3 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -17,7 +17,7 @@ import ( // SimulateMsgUnjail func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) address := sdk.AccAddress(key.PubKey().Address()) msg := slashing.NewMsgUnjail(address) @@ -29,6 +29,6 @@ func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { } event(fmt.Sprintf("slashing/MsgUnjail/%v", result.IsOK())) action = fmt.Sprintf("TestMsgUnjail: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 995e4f3580..4280e70c13 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -19,7 +19,7 @@ import ( // SimulateMsgCreateValidator func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -32,7 +32,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation amount = simulation.RandomAmount(r, amount) } if amount.Equal(sdk.ZeroInt()) { - return "no-operation", nil + return "no-operation", nil, nil } msg := stake.MsgCreateValidator{ Description: description, @@ -50,13 +50,13 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation event(fmt.Sprintf("stake/MsgCreateValidator/%v", result.IsOK())) // require.True(t, result.IsOK(), "expected OK result but instead got %v", result) action = fmt.Sprintf("TestMsgCreateValidator: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgEditValidator func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), Identity: simulation.RandStringOfLength(r, 10), @@ -78,13 +78,13 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { } event(fmt.Sprintf("stake/MsgEditValidator/%v", result.IsOK())) action = fmt.Sprintf("TestMsgEditValidator: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgDelegate func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -95,7 +95,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat amount = simulation.RandomAmount(r, amount) } if amount.Equal(sdk.ZeroInt()) { - return "no-operation", nil + return "no-operation", nil, nil } msg := stake.MsgDelegate{ DelegatorAddr: delegatorAddress, @@ -110,13 +110,13 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat } event(fmt.Sprintf("stake/MsgDelegate/%v", result.IsOK())) action = fmt.Sprintf("TestMsgDelegate: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgBeginUnbonding func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -127,7 +127,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. amount = simulation.RandomAmount(r, amount) } if amount.Equal(sdk.ZeroInt()) { - return "no-operation", nil + return "no-operation", nil, nil } msg := stake.MsgBeginUnbonding{ DelegatorAddr: delegatorAddress, @@ -142,13 +142,13 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. } event(fmt.Sprintf("stake/MsgBeginUnbonding/%v", result.IsOK())) action = fmt.Sprintf("TestMsgBeginUnbonding: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) @@ -165,13 +165,13 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { } event(fmt.Sprintf("stake/MsgCompleteUnbonding/%v", result.IsOK())) action = fmt.Sprintf("TestMsgCompleteUnbonding: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgBeginRedelegate func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address()) @@ -185,7 +185,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation amount = simulation.RandomAmount(r, amount) } if amount.Equal(sdk.ZeroInt()) { - return "no-operation", nil + return "no-operation", nil, nil } msg := stake.MsgBeginRedelegate{ DelegatorAddr: delegatorAddress, @@ -201,13 +201,13 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation } event(fmt.Sprintf("stake/MsgBeginRedelegate/%v", result.IsOK())) action = fmt.Sprintf("TestMsgBeginRedelegate: %s", msg.GetSignBytes()) - return action, nil + return action, nil, nil } } // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { - return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) validatorDstKey := simulation.RandomKey(r, keys) @@ -227,7 +227,7 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { } event(fmt.Sprintf("stake/MsgCompleteRedelegate/%v", result.IsOK())) action = fmt.Sprintf("TestMsgCompleteRedelegate: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) - return action, nil + return action, nil, nil } } From bfdeb3f8ce33d08828dd2e0f0822c3006d6751cc Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Mon, 27 Aug 2018 15:18:01 -0700 Subject: [PATCH 29/47] works --- x/gov/client/cli/tx.go | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 26883b9c37..65c922c6c1 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -244,7 +244,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { } // GetCmdQueryProposal implements the query proposal command. -func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryProposal(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-proposal", Short: "query proposal details", @@ -261,7 +261,7 @@ func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposal", queryRoute), bz) if err != nil { return err } @@ -278,7 +278,7 @@ func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { // nolint: gocyclo // GetCmdQueryProposals implements a query proposals command. -func GetCmdQueryProposals(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryProposals(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-proposals", Short: "query proposals with optional filters", @@ -323,12 +323,26 @@ func GetCmdQueryProposals(storeName string, cdc *wire.Codec) *cobra.Command { cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryWithData("custom/gov/proposals", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposals", queryRoute), bz) if err != nil { return err } - fmt.Println(string(res)) + var matchingProposals []gov.Proposal + err = cdc.UnmarshalJSON(res, &matchingProposals) + if err != nil { + return err + } + + if len(matchingProposals) == 0 { + fmt.Println("No matching proposals found") + return nil + } + + for _, proposal := range matchingProposals { + fmt.Printf(" %d - %s\n", proposal.GetProposalID(), proposal.GetTitle()) + } + return nil }, } @@ -343,7 +357,7 @@ func GetCmdQueryProposals(storeName string, cdc *wire.Codec) *cobra.Command { // Command to Get a Proposal Information // GetCmdQueryVote implements the query proposal vote command. -func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryVote(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-vote", Short: "query vote", @@ -365,7 +379,7 @@ func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/vote", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/vote", queryRoute), bz) if err != nil { return err } @@ -382,7 +396,7 @@ func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { } // GetCmdQueryVotes implements the command to query for proposal votes. -func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryVotes(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-votes", Short: "query votes on a proposal", @@ -398,7 +412,7 @@ func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/votes", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz) if err != nil { return err } @@ -415,7 +429,7 @@ func GetCmdQueryVotes(storeName string, cdc *wire.Codec) *cobra.Command { // Command to Get a specific Deposit Information // GetCmdQueryDeposit implements the query proposal deposit command. -func GetCmdQueryDeposit(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryDeposit(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-deposit", Short: "query deposit", @@ -437,7 +451,7 @@ func GetCmdQueryDeposit(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/deposit", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposit", queryRoute), bz) if err != nil { return err } @@ -454,7 +468,7 @@ func GetCmdQueryDeposit(storeName string, cdc *wire.Codec) *cobra.Command { } // GetCmdQueryDeposits implements the command to query for proposal deposits. -func GetCmdQueryDeposits(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryDeposits(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-deposits", Short: "query deposits on a proposal", @@ -470,7 +484,7 @@ func GetCmdQueryDeposits(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/deposits", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposits", queryRoute), bz) if err != nil { return err } @@ -486,7 +500,7 @@ func GetCmdQueryDeposits(storeName string, cdc *wire.Codec) *cobra.Command { } // GetCmdQueryDeposits implements the command to query for proposal deposits. -func GetCmdQueryTally(storeName string, cdc *wire.Codec) *cobra.Command { +func GetCmdQueryTally(queryRoute string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-tally", Short: "get the tally of a proposal vote", @@ -502,7 +516,7 @@ func GetCmdQueryTally(storeName string, cdc *wire.Codec) *cobra.Command { return err } - res, err := cliCtx.QueryWithData("custom/gov/tally", bz) + res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/tally", queryRoute), bz) if err != nil { return err } From 5ed1775681e4e6e0ef05933d223218ff8314cb2d Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Tue, 28 Aug 2018 06:18:18 +0800 Subject: [PATCH 30/47] Merge PR #2148: Change delegation amount from int64 to sdk.Int * Change delegation amount from int64 to sdk.Int * Refactor code according to code review * leave freeFermionVal to int64 in case of overflow --- cmd/gaia/app/genesis.go | 8 ++-- x/stake/keeper/delegation.go | 2 +- x/stake/keeper/delegation_test.go | 4 +- x/stake/keeper/slash_test.go | 2 +- x/stake/keeper/validator_test.go | 62 +++++++++++++++---------------- x/stake/types/validator.go | 4 +- x/stake/types/validator_test.go | 10 ++--- 7 files changed, 46 insertions(+), 46 deletions(-) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 24b160a510..0fbbc06031 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -26,7 +26,7 @@ const DefaultKeyPass = "12345678" var ( // bonded tokens given to genesis validators/accounts freeFermionVal = int64(100) - freeFermionsAcc = int64(50) + freeFermionsAcc = sdk.NewInt(50) ) // State to Unmarshal @@ -183,11 +183,11 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState accAuth := auth.NewBaseAccountWithAddress(genTx.Address) accAuth.Coins = sdk.Coins{ {genTx.Name + "Token", sdk.NewInt(1000)}, - {"steak", sdk.NewInt(freeFermionsAcc)}, + {"steak", freeFermionsAcc}, } acc := NewGenesisAccount(&accAuth) genaccs[i] = acc - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionsAcc)) // increase the supply + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply // add the validator if len(genTx.Name) > 0 { @@ -199,7 +199,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // add some new shares to the validator var issuedDelShares sdk.Dec - validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal) + validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, sdk.NewInt(freeFermionVal)) stakeData.Validators = append(stakeData.Validators, validator) // create the self-delegation from the issuedDelShares diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 2bad79c20f..a6e48517c9 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -239,7 +239,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt } pool := k.GetPool(ctx) - validator, pool, newShares = validator.AddTokensFromDel(pool, bondAmt.Amount.Int64()) + validator, pool, newShares = validator.AddTokensFromDel(pool, bondAmt.Amount) delegation.Shares = delegation.Shares.Add(newShares) // Update delegation height diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 4333a74942..cd86f456ea 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -16,7 +16,7 @@ func TestDelegation(t *testing.T) { pool := keeper.GetPool(ctx) //construct the validators - amts := []int64{9, 8, 7} + amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8), sdk.NewInt(7)} var validators [3]types.Validator for i, amt := range amts { validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{}) @@ -146,7 +146,7 @@ func TestUnbondDelegation(t *testing.T) { //create a validator and a delegator to that validator validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - validator, pool, issuedShares := validator.AddTokensFromDel(pool, 10) + validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, int64(10), issuedShares.RoundInt64()) keeper.SetPool(ctx, pool) validator = keeper.UpdateValidator(ctx, validator) diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 156f0602e9..30236bb8d3 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -24,7 +24,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { // add numVals validators for i := 0; i < numVals; i++ { validator := types.NewValidator(addrVals[i], PKs[i], types.Description{}) - validator, pool, _ = validator.AddTokensFromDel(pool, amt) + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) validator = keeper.UpdateValidator(ctx, validator) keeper.SetValidatorByPubKeyIndex(ctx, validator) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 54149707e8..9e92ca33e7 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -18,7 +18,7 @@ func TestSetValidator(t *testing.T) { // test how the validator is set from a purely unbonbed pool validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - validator, pool, _ = validator.AddTokensFromDel(pool, 10) + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, sdk.Unbonded, validator.Status) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) @@ -61,7 +61,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { // add a validator validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - validator, pool, delSharesCreated := validator.AddTokensFromDel(pool, 100) + validator, pool, delSharesCreated := validator.AddTokensFromDel(pool, sdk.NewInt(100)) require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, int64(100), validator.Tokens.RoundInt64()) keeper.SetPool(ctx, pool) @@ -112,7 +112,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { val := types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) val.BondHeight = int64(i) val.BondIntraTxCounter = int16(i) - val, pool, _ = val.AddTokensFromDel(pool, int64((i+1)*10)) + val, pool, _ = val.AddTokensFromDel(pool, sdk.NewInt(int64((i+1)*10))) keeper.SetPool(ctx, pool) val = keeper.UpdateValidator(ctx, val) @@ -175,7 +175,7 @@ func TestCliffValidatorChange(t *testing.T) { val := types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) val.BondHeight = int64(i) val.BondIntraTxCounter = int16(i) - val, pool, _ = val.AddTokensFromDel(pool, int64((i+1)*10)) + val, pool, _ = val.AddTokensFromDel(pool, sdk.NewInt(int64((i+1)*10))) keeper.SetPool(ctx, pool) val = keeper.UpdateValidator(ctx, val) @@ -184,7 +184,7 @@ func TestCliffValidatorChange(t *testing.T) { // add a large amount of tokens to current cliff validator currCliffVal := validators[numVals-maxVals] - currCliffVal, pool, _ = currCliffVal.AddTokensFromDel(pool, 200) + currCliffVal, pool, _ = currCliffVal.AddTokensFromDel(pool, sdk.NewInt(200)) keeper.SetPool(ctx, pool) currCliffVal = keeper.UpdateValidator(ctx, currCliffVal) @@ -197,7 +197,7 @@ func TestCliffValidatorChange(t *testing.T) { require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) // add small amount of tokens to new current cliff validator - newCliffVal, pool, _ = newCliffVal.AddTokensFromDel(pool, 1) + newCliffVal, pool, _ = newCliffVal.AddTokensFromDel(pool, sdk.NewInt(1)) keeper.SetPool(ctx, pool) newCliffVal = keeper.UpdateValidator(ctx, newCliffVal) @@ -207,7 +207,7 @@ func TestCliffValidatorChange(t *testing.T) { require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) // add enough power to cliff validator to be equal in rank to next validator - newCliffVal, pool, _ = newCliffVal.AddTokensFromDel(pool, 9) + newCliffVal, pool, _ = newCliffVal.AddTokensFromDel(pool, sdk.NewInt(9)) keeper.SetPool(ctx, pool) newCliffVal = keeper.UpdateValidator(ctx, newCliffVal) @@ -227,7 +227,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { // add a validator validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - validator, pool, _ = validator.AddTokensFromDel(pool, 100) + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(100)) require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, int64(100), validator.Tokens.RoundInt64()) keeper.SetPool(ctx, pool) @@ -254,7 +254,7 @@ func TestValidatorBasics(t *testing.T) { validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{}) validators[i].Status = sdk.Unbonded validators[i].Tokens = sdk.ZeroDec() - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens)) @@ -480,7 +480,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { pool := keeper.GetPool(ctx) moniker := fmt.Sprintf("val#%d", int64(i)) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) validators[i] = keeper.UpdateValidator(ctx, validators[i]) } @@ -495,7 +495,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.True(ValEq(t, validators[3], resValidators[1])) pool := keeper.GetPool(ctx) - validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 500) + validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(500)) keeper.SetPool(ctx, pool) validators[0] = keeper.UpdateValidator(ctx, validators[0]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -512,7 +512,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[3], found = keeper.GetValidator(ctx, validators[3].Operator) require.True(t, found) - validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 1) + validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(1)) keeper.SetPool(ctx, pool) validators[3] = keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -530,7 +530,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.True(ValEq(t, validators[2], resValidators[1])) // validator 4 does not get spot back - validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 200) + validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(200)) keeper.SetPool(ctx, pool) validators[3] = keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -557,9 +557,9 @@ func TestValidatorBondHeight(t *testing.T) { validators[1] = types.NewValidator(Addrs[1], PKs[1], types.Description{}) validators[2] = types.NewValidator(Addrs[2], PKs[2], types.Description{}) - validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 200) - validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 100) - validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 100) + validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(200)) + validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(100)) + validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(100)) keeper.SetPool(ctx, pool) validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -577,8 +577,8 @@ func TestValidatorBondHeight(t *testing.T) { assert.True(ValEq(t, validators[0], resValidators[0])) assert.True(ValEq(t, validators[1], resValidators[1])) - validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 50) - validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 50) + validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(50)) + validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(50)) keeper.SetPool(ctx, pool) validators[2] = keeper.UpdateValidator(ctx, validators[2]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -601,7 +601,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validators[i]) } @@ -622,7 +622,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { // test a swap in voting power pool := keeper.GetPool(ctx) - validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 600) + validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(600)) keeper.SetPool(ctx, pool) validators[0] = keeper.UpdateValidator(ctx, validators[0]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -640,7 +640,7 @@ func TestClearTendermintUpdates(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validators[i]) } @@ -660,7 +660,7 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -699,7 +699,7 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -722,7 +722,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -750,7 +750,7 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -761,8 +761,8 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { // test multiple value change // tendermintUpdate set: {c1, c3} -> {c1', c3'} pool := keeper.GetPool(ctx) - validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 190) - validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 80) + validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(190)) + validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(80)) keeper.SetPool(ctx, pool) validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) @@ -781,7 +781,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -824,7 +824,7 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -844,7 +844,7 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) { require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) pool := keeper.GetPool(ctx) - validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 10) + validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10)) keeper.SetPool(ctx, pool) validators[2] = keeper.UpdateValidator(ctx, validators[2]) @@ -862,7 +862,7 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } validators[0] = keeper.UpdateValidator(ctx, validators[0]) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index f8404b5963..9d04357528 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -376,11 +376,11 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) { //_________________________________________________________________________________________________________ // AddTokensFromDel adds tokens to a validator -func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Dec) { +func (v Validator) AddTokensFromDel(pool Pool, amount sdk.Int) (Validator, Pool, sdk.Dec) { // bondedShare/delegatedShare exRate := v.DelegatorShareExRate() - amountDec := sdk.NewDec(amount) + amountDec := sdk.NewDecFromInt(amount) if v.Status == sdk.Bonded { pool = pool.looseTokensToBonded(amountDec) diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index f4c874057f..b81ae44585 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -109,7 +109,7 @@ func TestAddTokensValidatorBonded(t *testing.T) { pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Bonded) - validator, pool, delShares := validator.AddTokensFromDel(pool, 10) + validator, pool, delShares := validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) @@ -122,7 +122,7 @@ func TestAddTokensValidatorUnbonding(t *testing.T) { pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Unbonding) - validator, pool, delShares := validator.AddTokensFromDel(pool, 10) + validator, pool, delShares := validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) @@ -136,7 +136,7 @@ func TestAddTokensValidatorUnbonded(t *testing.T) { pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Unbonded) - validator, pool, delShares := validator.AddTokensFromDel(pool, 10) + validator, pool, delShares := validator.AddTokensFromDel(pool, sdk.NewInt(10)) require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) @@ -206,7 +206,7 @@ func TestUpdateStatus(t *testing.T) { pool.LooseTokens = sdk.NewDec(100) validator := NewValidator(addr1, pk1, Description{}) - validator, pool, _ = validator.AddTokensFromDel(pool, 100) + validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(100)) require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, int64(100), validator.Tokens.RoundInt64()) require.Equal(t, int64(0), pool.BondedTokens.RoundInt64()) @@ -243,7 +243,7 @@ func TestPossibleOverflow(t *testing.T) { } tokens := int64(71) msg := fmt.Sprintf("validator %#v", validator) - newValidator, _, _ := validator.AddTokensFromDel(pool, tokens) + newValidator, _, _ := validator.AddTokensFromDel(pool, sdk.NewInt(tokens)) msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg) require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroDec()), From fc20f757ecb0761de17c189de4380a0feea405e0 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 27 Aug 2018 18:42:03 -0400 Subject: [PATCH 31/47] Load ledger device at runtime --- crypto/ledger.go | 17 ++++++++++------- crypto/ledger_secp256k1.go | 31 ++++++++++++++++++------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/crypto/ledger.go b/crypto/ledger.go index 9d446202f7..5489810bca 100644 --- a/crypto/ledger.go +++ b/crypto/ledger.go @@ -6,13 +6,16 @@ import ( ledger "github.com/zondax/ledger-goclient" ) -// If ledger support (build tag) has been enabled, automically attempt to load -// and set the ledger device, ledgerDevice, if it has not already been set. +// If ledger support (build tag) has been enabled, set the DiscoverLedger +// function which is responsible for loading the Ledger device at runtime or +// returning an error. func init() { - device, err := ledger.FindLedger() - if err != nil { - ledgerDeviceErr = err - } else { - ledgerDevice = device + DiscoverLedger = func() (LedgerSECP256K1, error) { + device, err := ledger.FindLedger() + if err != nil { + return nil, err + } + + return device, nil } } diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index 8cb175d4f5..5f6bcb1ad7 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -1,24 +1,26 @@ package crypto import ( - "errors" "fmt" + "github.com/pkg/errors" + secp256k1 "github.com/btcsuite/btcd/btcec" tmcrypto "github.com/tendermint/tendermint/crypto" tmsecp256k1 "github.com/tendermint/tendermint/crypto/secp256k1" ) var ( - ledgerDevice LedgerSECP256K1 - ledgerDeviceErr error - - // ErrMissingLedgerDevice is used to reflect that a ledger device load has - // not been attempted. - ErrMissingLedgerDevice = errors.New("missing ledger device") + // DiscoverLedger defines a function to be invoked at runtime for discovering + // a connected Ledger device. + DiscoverLedger DiscoverLedgerFn ) type ( + // DiscoverLedgerFn defines a Ledger discovery function that returns a + // connected device or an error upon failure. + DiscoverLedgerFn func() (LedgerSECP256K1, error) + // DerivationPath represents a Ledger derivation path. DerivationPath []uint32 @@ -47,18 +49,21 @@ type ( // CONTRACT: The ledger device, ledgerDevice, must be loaded and set prior to // any creation of a PrivKeyLedgerSecp256k1. func NewPrivKeyLedgerSecp256k1(path DerivationPath) (tmcrypto.PrivKey, error) { - if ledgerDevice == nil { - err := ErrMissingLedgerDevice - if ledgerDeviceErr != nil { - err = ledgerDeviceErr + var ledgerDevice LedgerSECP256K1 + + if DiscoverLedger != nil { + device, err := DiscoverLedger() + if err != nil { + return nil, errors.Wrap(err, "failed to create PrivKeyLedgerSecp256k1") } - return nil, fmt.Errorf("failed to create PrivKeyLedgerSecp256k1: %v", err) + ledgerDevice = device + } else { + return nil, errors.New("no ledger discovery function defined") } pkl := &PrivKeyLedgerSecp256k1{Path: path, ledger: ledgerDevice} - // cache the pubkey for later use pubKey, err := pkl.getPubKey() if err != nil { return nil, err From 0245a4b5ee6cd0a85f037b83c96325a147862112 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 27 Aug 2018 18:45:34 -0400 Subject: [PATCH 32/47] Update pending log --- PENDING.md | 2 ++ crypto/ledger_secp256k1.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index cee2ae14c4..11f7180312 100644 --- a/PENDING.md +++ b/PENDING.md @@ -79,5 +79,7 @@ BUG FIXES * SDK * \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) * \#2105 Fix DB Iterator leak, which may leak a go routine. + * [ledger] \#2064 Fix inability to sign and send transactions via the LCD by + loading a Ledger device at runtime. * Tendermint diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index 5f6bcb1ad7..b295701792 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -59,7 +59,7 @@ func NewPrivKeyLedgerSecp256k1(path DerivationPath) (tmcrypto.PrivKey, error) { ledgerDevice = device } else { - return nil, errors.New("no ledger discovery function defined") + return nil, errors.New("no Ledger discovery function defined") } pkl := &PrivKeyLedgerSecp256k1{Path: path, ledger: ledgerDevice} From de061fa8e195f41b7669556761fc26cea00c40f7 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 27 Aug 2018 18:57:06 -0400 Subject: [PATCH 33/47] Do not export ledger discovery types --- crypto/ledger.go | 4 ++-- crypto/ledger_secp256k1.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crypto/ledger.go b/crypto/ledger.go index 5489810bca..346d4bfb32 100644 --- a/crypto/ledger.go +++ b/crypto/ledger.go @@ -6,11 +6,11 @@ import ( ledger "github.com/zondax/ledger-goclient" ) -// If ledger support (build tag) has been enabled, set the DiscoverLedger +// If ledger support (build tag) has been enabled, set the discoverLedger // function which is responsible for loading the Ledger device at runtime or // returning an error. func init() { - DiscoverLedger = func() (LedgerSECP256K1, error) { + discoverLedger = func() (LedgerSECP256K1, error) { device, err := ledger.FindLedger() if err != nil { return nil, err diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index b295701792..c59f8e3b4a 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -11,15 +11,15 @@ import ( ) var ( - // DiscoverLedger defines a function to be invoked at runtime for discovering + // discoverLedger defines a function to be invoked at runtime for discovering // a connected Ledger device. - DiscoverLedger DiscoverLedgerFn + discoverLedger discoverLedgerFn ) type ( - // DiscoverLedgerFn defines a Ledger discovery function that returns a + // discoverLedgerFn defines a Ledger discovery function that returns a // connected device or an error upon failure. - DiscoverLedgerFn func() (LedgerSECP256K1, error) + discoverLedgerFn func() (LedgerSECP256K1, error) // DerivationPath represents a Ledger derivation path. DerivationPath []uint32 @@ -51,8 +51,8 @@ type ( func NewPrivKeyLedgerSecp256k1(path DerivationPath) (tmcrypto.PrivKey, error) { var ledgerDevice LedgerSECP256K1 - if DiscoverLedger != nil { - device, err := DiscoverLedger() + if discoverLedger != nil { + device, err := discoverLedger() if err != nil { return nil, errors.Wrap(err, "failed to create PrivKeyLedgerSecp256k1") } From 4ddfef6204065cba8f84fc481bd982d2a026f6d9 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 28 Aug 2018 01:28:27 -0700 Subject: [PATCH 34/47] Add documentation regarding environment variables Closes #1973. --- docs/validators/security.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/validators/security.md b/docs/validators/security.md index d3e3d6988d..5ccf988148 100644 --- a/docs/validators/security.md +++ b/docs/validators/security.md @@ -39,3 +39,14 @@ Sentry Nodes should edit their config.toml: # Comma separated list of peer IDs to keep private (will not be gossiped to other peers) private_peer_ids = "ipaddress of validator nodes" ``` + +## Environment Variables + +By default, uppercase environment variables with the following prefixes will replace lowercase command-line flags: + +- `GA` (for Gaia flags) +- `TM` (for Tendermint flags) +- `BC` (for democli or basecli flags) + +For example, the environment variable `GA_CHAIN_ID` will map to the command line flag `--chain-id`. Note that while explicit command-line flags will take precedence over environment variables, environment variables will take precedence over any of your configuration files. For this reason, it's imperative that you lock down your environment such that any critical parameters are defined as flags on the CLI or prevent modification of any environment variables. + \ No newline at end of file From 1a6c4785e9b824a2f229050eb3644d951fb03716 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 28 Aug 2018 08:16:50 -0400 Subject: [PATCH 35/47] Cleanup ledger godocs and reduce complexity --- crypto/ledger.go | 6 +++--- crypto/ledger_secp256k1.go | 18 +++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/crypto/ledger.go b/crypto/ledger.go index 346d4bfb32..b9aa65b56f 100644 --- a/crypto/ledger.go +++ b/crypto/ledger.go @@ -6,9 +6,9 @@ import ( ledger "github.com/zondax/ledger-goclient" ) -// If ledger support (build tag) has been enabled, set the discoverLedger -// function which is responsible for loading the Ledger device at runtime or -// returning an error. +// If ledger support (build tag) has been enabled, which implies a CGO dependency, +// set the discoverLedger function which is responsible for loading the Ledger +// device at runtime or returning an error. func init() { discoverLedger = func() (LedgerSECP256K1, error) { device, err := ledger.FindLedger() diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index c59f8e3b4a..49f110b3d7 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -49,20 +49,16 @@ type ( // CONTRACT: The ledger device, ledgerDevice, must be loaded and set prior to // any creation of a PrivKeyLedgerSecp256k1. func NewPrivKeyLedgerSecp256k1(path DerivationPath) (tmcrypto.PrivKey, error) { - var ledgerDevice LedgerSECP256K1 - - if discoverLedger != nil { - device, err := discoverLedger() - if err != nil { - return nil, errors.Wrap(err, "failed to create PrivKeyLedgerSecp256k1") - } - - ledgerDevice = device - } else { + if discoverLedger == nil { return nil, errors.New("no Ledger discovery function defined") } - pkl := &PrivKeyLedgerSecp256k1{Path: path, ledger: ledgerDevice} + device, err := discoverLedger() + if err != nil { + return nil, errors.Wrap(err, "failed to create PrivKeyLedgerSecp256k1") + } + + pkl := &PrivKeyLedgerSecp256k1{Path: path, ledger: device} pubKey, err := pkl.getPubKey() if err != nil { From bdbdd1a8323f14b27b4d5d6f5cf879282a326658 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 28 Aug 2018 08:24:19 -0400 Subject: [PATCH 36/47] Further godoc updates --- crypto/ledger_secp256k1.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index 49f110b3d7..ff05d31bae 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -18,7 +18,8 @@ var ( type ( // discoverLedgerFn defines a Ledger discovery function that returns a - // connected device or an error upon failure. + // connected device or an error upon failure. Its allows a method to avoid CGO + // dependencies when Ledger support is potentially not enabled. discoverLedgerFn func() (LedgerSECP256K1, error) // DerivationPath represents a Ledger derivation path. From e89e860524c76025992b99787da44e28444ae8b0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 16:18:06 +0200 Subject: [PATCH 37/47] Update config.js --- docs/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.js b/docs/config.js index 42df9de92d..93426bcc5f 100644 --- a/docs/config.js +++ b/docs/config.js @@ -2,7 +2,7 @@ module.exports = { title: "Cosmos Network", description: "Documentation for the Cosmos Network.", dest: "./dist/docs", - base: "/", + base: "/docs/", markdown: { lineNumbers: true }, From 946e24d7bfce0ebbe72ffde6dd2d1a382e76e96e Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 28 Aug 2018 09:53:56 -0700 Subject: [PATCH 38/47] Merge PR #2152: Make CI not update the lock file * CI: Make CI not update the lock file We want CI to be running the lock in the repo, not generating a new one. Linting now ensures that the lock file is up to date. * Switch to Chris' comment * Update pending to indicate this new command --- Makefile | 5 +++++ PENDING.md | 1 + 2 files changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 66d5663092..983234dbc3 100644 --- a/Makefile +++ b/Makefile @@ -106,6 +106,11 @@ get_dev_tools: cd tools && $(MAKE) get_dev_tools get_vendor_deps: + @echo "--> Generating vendor directory via dep ensure" + @rm -rf .vendor-new + @dep ensure -v -vendor-only + +update_vendor_deps: @echo "--> Running dep ensure" @rm -rf .vendor-new @dep ensure -v diff --git a/PENDING.md b/PENDING.md index d65d34d8a7..dd18be3c0b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -12,6 +12,7 @@ BREAKING CHANGES * [cli] \#1983 you can now pass --pubkey or --address to gaiacli keys show to return a plaintext representation of the key's address or public key for use with other commands * [cli] \#2061 changed proposalID in governance REST endpoints to proposal-id * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively + * [makefile] `get_vendor_deps` no longer updates lock file it just updates vendor directory. Use `update_vendor_deps` to update the lock file. [#2152](https://github.com/cosmos/cosmos-sdk/pull/2152) * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) From c6d692e27fa19df8ae4d4b0206cd803c61f7a3f4 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 28 Aug 2018 09:59:42 -0700 Subject: [PATCH 39/47] Merge PR #2172: Use cobra.NoArgs where appropriate Closes #885. --- x/slashing/client/cli/tx.go | 2 +- x/stake/client/cli/query.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 5831ef3100..2fdd65c6c3 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -18,7 +18,7 @@ import ( func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "unjail", - Args: cobra.ExactArgs(0), + Args: cobra.NoArgs, Short: "unjail validator previously jailed for downtime", RunE: func(cmd *cobra.Command, args []string) error { txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 4b8e99e7d2..d58ea39381 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -423,7 +423,7 @@ func GetCmdQueryPool(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "pool", Short: "Query the current staking pool values", - Args: cobra.ExactArgs(0), + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { key := stake.PoolKey cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -462,7 +462,7 @@ func GetCmdQueryParams(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "parameters", Short: "Query the current staking parameters information", - Args: cobra.ExactArgs(0), + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { key := stake.ParamKey cliCtx := context.NewCLIContext().WithCodec(cdc) From dfd29a523cffb2320174ee05a8580f6ba308f756 Mon Sep 17 00:00:00 2001 From: Jack Zampolin Date: Tue, 28 Aug 2018 11:13:21 -0700 Subject: [PATCH 40/47] Update PRIORIEIES.md --- docs/PRIORITIES.md | 92 +++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/docs/PRIORITIES.md b/docs/PRIORITIES.md index 631d9b9ea5..d5e4257764 100644 --- a/docs/PRIORITIES.md +++ b/docs/PRIORITIES.md @@ -4,48 +4,72 @@ - Collection - Simple flat fee set in-config by validators & full nodes - ref [#1921](https://github.com/cosmos/cosmos-sdk/issues/1921) + - @sunnya97 working on implementation + - _*BLOCKER:*_ Blocked on [tendermint/tendermint#2275](https://github.com/tendermint/tendermint/issues/2275) @ValarDragon - Distribution - "Piggy bank" fee distribution - ref [#1944](https://github.com/cosmos/cosmos-sdk/pull/1944) (spec) -- Reserve pool - - Collects in a special field for now, no spending + - @rigelrozanski working on implementation +- EST TIMELINE: + - Work on fees should be completed in the `v0.25.0` release + +## Staking/Slashing/Stability + +- Unbonding state for validators (WIP) [#2163](https://github.com/cosmos/cosmos-sdk/pull/2163) @rigelrozanski + - Needs :eyes: from @chris + - Should be in `v0.25.0` release +- Slashing period PR - ref [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) + - Needs :eyes: from @cwgoes and @jaekwon + - Should be in `v0.25.0` release +- Other slashing issues blocking for launch - [#1256](https://github.com/cosmos/cosmos-sdk/issues/1256) +- Update staking/slashing for NextValSet change + - @cwgoes to start next +- Miscellaneous minor staking issues + - [List here](https://github.com/cosmos/cosmos-sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Astaking+label%3Aprelaunch) + - Need to figure out scope of work here to estimate time + - @rigelrozanski to start next + +## Vesting + +- Single `VestingAccount` allowing delegation/voting but no withdrawals +- Ref [#1875](https://github.com/cosmos/cosmos-sdk/pull/1875) (spec) +- @AdityaSripal working on this. + - Should be in `v0.25.0` release + +## Multisig + +- Already implemented on TM side, need simple CLI interface +- @alessio working on the SDK side of things here +- Need to schedule some time with @alessio, @ebuchman and @ValarDragon this week to finalize feature set/implementation plan + +## ABCI Changes + +- Need to update for new ABCI changes - error string, tags are list of lists, proposer in header (Tendermint 0.24?) +- @cwgoes has done some work here. Should be on `develop` in tendermint w/in next week. +- Include in tendermint `v0.24.0` release? + +## Gas + +- Simple transaction benchmarking work by @jlandrews to inform additional work here +- Integrate @alessio's simulation work into CLI and LCD +- Sanity Checks + +## LCD + +- Bianje working on implementation ([#2147](https://github.com/cosmos/cosmos-sdk/pull/2147)) + - ICS 0,ICS 1, ICS 20 and ICS 21 implemented in this PR :point_up: + - @fedekunze, @jackzampolin and @alexanderbez to review +- Additional PR incoming for ICS 22 and ICS 23 +- Include [#382](https://github.com/cosmos/cosmos-sdk/issues/382) + +# Lower priority ## Governance v2 - Simple software upgrade proposals - Implementation described in [#1079](https://github.com/cosmos/cosmos-sdk/issues/1079) - Agree upon a block height to switch to new version - -## Staking/Slashing/Stability - -- Miscellaneous minor staking issues - - [List here](https://github.com/cosmos/cosmos-sdk/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Astaking+label%3Aprelaunch) -- Unbonding state for validators https://github.com/cosmos/cosmos-sdk/issues/1676 -- Slashing period - ref [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) (spec) - - Various other slashing issues needing resolution - ref [#1256](https://github.com/cosmos/cosmos-sdk/issues/1256) -- Update staking/slashing for NextValSet change - -## Vesting - -- Single `VestingAccount` allowing delegation/voting but no withdrawals -- Ref [#1875](https://github.com/cosmos/cosmos-sdk/pull/1875) (spec) - -## Multisig - -- Already implemented on TM side, need simple CLI interface - -## Other - -- Need to update for new ABCI changes - error string, tags are list of lists, proposer in header (Tendermint 0.24?) - -## Gas - -- Benchmark gas, choose better constants - -# Lower priority - -## Governance - -- Circuit breaker +- Another Governance proposal from @jaekwon [#2116](https://github.com/cosmos/cosmos-sdk/pull/2116) +- Circuit breaker - Parameter change proposals (roughly the same implementation as circuit breaker) ## Documentation From fd8c1e5253d95628eff9d88d9435ec10d498a23e Mon Sep 17 00:00:00 2001 From: Mike Xu Date: Wed, 29 Aug 2018 13:22:39 +0800 Subject: [PATCH 41/47] Merge PR #2159: fix the gov/slash error --- PENDING.md | 1 + x/gov/tally.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/PENDING.md b/PENDING.md index dd18be3c0b..f45541ccdc 100644 --- a/PENDING.md +++ b/PENDING.md @@ -86,5 +86,6 @@ BUG FIXES * \#2105 Fix DB Iterator leak, which may leak a go routine. * [ledger] \#2064 Fix inability to sign and send transactions via the LCD by loading a Ledger device at runtime. + * \#2158 Fix non-deterministic ordering of validator iteration when slashing in `gov EndBlocker` * Tendermint diff --git a/x/gov/tally.go b/x/gov/tally.go index cfb113ae33..b6c9ee2a14 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -103,5 +103,8 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall return true, tallyResults, nonVoting } // If more than 1/2 of non-abstaining voters vote No, proposal fails + + SortAddresses(nonVoting) + return false, tallyResults, nonVoting } From fa78303253c2380f6fcb0918629f18d335310d5d Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Wed, 29 Aug 2018 14:54:22 -0400 Subject: [PATCH 42/47] DataDog hostname reporting fix --- .../roles/update-datadog-agent/templates/datadog.yaml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 index 7e35a5255e..3c2e031dde 100644 --- a/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 +++ b/networks/remote/ansible/roles/update-datadog-agent/templates/datadog.yaml.j2 @@ -31,7 +31,7 @@ api_key: {{DD_API_KEY}} force_tls_12: yes # Force the hostname to whatever you want. (default: auto-detected) -hostname: {{inventory_hostname}} +hostname: {{inventory_hostname | replace ("_","-")}} # Make the agent use "hostname -f" on unix-based systems as a last resort # way of determining the hostname instead of Golang "os.Hostname()" From 03c56fc02442099e415a9f5ad5752bd5ae2e336c Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 30 Aug 2018 18:33:48 -0700 Subject: [PATCH 43/47] Merge PR #2190: Rename --gen-txs to --with-txs * Rename --gen-txs to --with-txs Closes #1088. * Update CHANGELOG.md --- PENDING.md | 1 + docs/getting-started/create-testnet.md | 2 +- .../remote/ansible/roles/setup-validators/tasks/main.yml | 2 +- server/init.go | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/PENDING.md b/PENDING.md index f45541ccdc..339868c99d 100644 --- a/PENDING.md +++ b/PENDING.md @@ -13,6 +13,7 @@ BREAKING CHANGES * [cli] \#2061 changed proposalID in governance REST endpoints to proposal-id * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * [makefile] `get_vendor_deps` no longer updates lock file it just updates vendor directory. Use `update_vendor_deps` to update the lock file. [#2152](https://github.com/cosmos/cosmos-sdk/pull/2152) + * [cli] \#2190 `gaiacli init --gen-txs` is now `gaiacli init --with-txs` to reduce confusion * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) diff --git a/docs/getting-started/create-testnet.md b/docs/getting-started/create-testnet.md index 0b68b3287b..74fd1d5ef2 100644 --- a/docs/getting-started/create-testnet.md +++ b/docs/getting-started/create-testnet.md @@ -13,7 +13,7 @@ Now these json files need to be aggregated together via Github, a Google form, p Place all files on one computer in `$HOME/.gaiad/gen-tx/` ```bash -gaiad init --gen-txs -o --chain= +gaiad init --with-txs -o --chain= ``` This will generate a `genesis.json` in `$HOME/.gaiad/config/genesis.json` distribute this file to all validators on your testnet. diff --git a/networks/remote/ansible/roles/setup-validators/tasks/main.yml b/networks/remote/ansible/roles/setup-validators/tasks/main.yml index 8832db4aa2..d8cb499135 100644 --- a/networks/remote/ansible/roles/setup-validators/tasks/main.yml +++ b/networks/remote/ansible/roles/setup-validators/tasks/main.yml @@ -70,7 +70,7 @@ unarchive: src=files/gen-tx.tgz dest=/home/gaiad/.gaiad/config/gentx owner=gaiad - name: Generate genesis.json - command: "/usr/bin/gaiad init --gen-txs --name=node{{nodeid.stdout_lines[0]}} --chain-id={{TESTNET_NAME}}" + command: "/usr/bin/gaiad init --with-txs --name=node{{nodeid.stdout_lines[0]}} --chain-id={{TESTNET_NAME}}" become: yes become_user: gaiad args: diff --git a/server/init.go b/server/init.go index 39f3d0b7f8..105325e0d5 100644 --- a/server/init.go +++ b/server/init.go @@ -41,7 +41,7 @@ var ( //parameter names, init command var ( FlagOverwrite = "overwrite" - FlagGenTxs = "gen-txs" + FlagWithTxs = "with-txs" FlagIP = "ip" FlagChainID = "chain-id" ) @@ -169,7 +169,7 @@ func InitCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command { config.SetRoot(viper.GetString(tmcli.HomeFlag)) initConfig := InitConfig{ viper.GetString(FlagChainID), - viper.GetBool(FlagGenTxs), + viper.GetBool(FlagWithTxs), filepath.Join(config.RootDir, "config", "gentx"), viper.GetBool(FlagOverwrite), } @@ -198,7 +198,7 @@ func InitCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command { } cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file") cmd.Flags().String(FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") - cmd.Flags().Bool(FlagGenTxs, false, "apply genesis transactions from [--home]/config/gentx/") + cmd.Flags().Bool(FlagWithTxs, false, "apply existing genesis transactions from [--home]/config/gentx/") cmd.Flags().AddFlagSet(appInit.FlagsAppGenState) cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx) // need to add this flagset for when no GenTx's provided cmd.AddCommand(GenTxCmd(ctx, cdc, appInit)) From dc0f13214d75734d2ab47c7ee6c86ecb06d72077 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 30 Aug 2018 18:38:28 -0700 Subject: [PATCH 44/47] Merge PR #2170: Add show-address command * Add show-address command Closes #1274. * Add PENDING entry * Add godoc * Updates from code review --- PENDING.md | 1 + server/tm_cmds.go | 50 +++++++++++++++++++++++++++++++++++------------ server/util.go | 1 + 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/PENDING.md b/PENDING.md index 339868c99d..14747be9d6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -42,6 +42,7 @@ FEATURES * [cli] \#2047 The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. * Gaia + * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` * SDK * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers diff --git a/server/tm_cmds.go b/server/tm_cmds.go index c2395e3996..d84022183a 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -11,6 +11,7 @@ import ( tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" "github.com/tendermint/tendermint/p2p" pvm "github.com/tendermint/tendermint/privval" + "github.com/cosmos/cosmos-sdk/client" ) // ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout @@ -32,7 +33,6 @@ func ShowNodeIDCmd(ctx *Context) *cobra.Command { // ShowValidator - ported from Tendermint, show this node's validator info func ShowValidatorCmd(ctx *Context) *cobra.Command { - flagJSON := "json" cmd := cobra.Command{ Use: "show-validator", Short: "Show this node's tendermint validator info", @@ -42,16 +42,8 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile()) valPubKey := privValidator.PubKey - if viper.GetBool(flagJSON) { - - cdc := wire.NewCodec() - wire.RegisterCrypto(cdc) - pubKeyJSONBytes, err := cdc.MarshalJSON(valPubKey) - if err != nil { - return err - } - fmt.Println(string(pubKeyJSONBytes)) - return nil + if viper.GetBool(client.FlagJson) { + return printlnJSON(valPubKey) } pubkey, err := sdk.Bech32ifyValPub(valPubKey) if err != nil { @@ -61,10 +53,44 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { return nil }, } - cmd.Flags().Bool(flagJSON, false, "get machine parseable output") + cmd.Flags().Bool(client.FlagJson, false, "get machine parseable output") return &cmd } +// ShowAddressCmd - show this node's validator address +func ShowAddressCmd(ctx *Context) *cobra.Command { + cmd := &cobra.Command{ + Use: "show-address", + Short: "Shows this node's tendermint validator address", + RunE: func(cmd *cobra.Command, args []string) error { + cfg := ctx.Config + privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorFile()) + valAddr := (sdk.ValAddress)(privValidator.Address) + + if viper.GetBool(client.FlagJson) { + return printlnJSON(valAddr) + } + + fmt.Println(valAddr.String()) + return nil + }, + } + + cmd.Flags().Bool(client.FlagJson, false, "get machine parseable output") + return cmd +} + +func printlnJSON(v interface{}) error { + cdc := wire.NewCodec() + wire.RegisterCrypto(cdc) + marshalled, err := cdc.MarshalJSON(v) + if err != nil { + return err + } + fmt.Println(string(marshalled)) + return nil +} + // UnsafeResetAllCmd - extension of the tendermint command, resets initialization func UnsafeResetAllCmd(ctx *Context) *cobra.Command { return &cobra.Command{ diff --git a/server/util.go b/server/util.go index 0f5a7b3eb2..04c539eb42 100644 --- a/server/util.go +++ b/server/util.go @@ -112,6 +112,7 @@ func AddCommands( tendermintCmd.AddCommand( ShowNodeIDCmd(ctx), ShowValidatorCmd(ctx), + ShowAddressCmd(ctx), ) rootCmd.AddCommand( From 2d92803b9f7789fd5c03fdd207d0b70b2ee1dd5a Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Fri, 31 Aug 2018 00:06:44 -0400 Subject: [PATCH 45/47] Merge PR #2040: Refactor Validator Account Types/Bech32 Prefixing * Add new account bech32 prefixes with godocs * Restructure spacing of existing account code * Update account godocs * More account godoc updates + new tm pub/addr helpers * Update validator type to use new account types/bech32 prefixes * Fix account documentation errors * Update Bech32 prefix for consensus nodes * Update Bech32 spec doc * Fix account type tests * Add missing account consensus functions, clear up godocs, and fix tests * Add to TestRandBech32PubkeyConsistency check * Update initialization of validator public keys * Update query signing info command * Implement new ConsAddress type with associated unit tests * [WIP] Update stake and slashing parameters * Update all calls to MustBech32ifyValPub * [WIP] Validator operator API updates * [WIP] Fix and update unit tests * Fix gov logs (helping to debug failing tests) * Fix gov tally * Fix all broken x/ unit tests * Update gaia app genesis address logic * Fix linting errors * Fix broken LCD tests * Fix broken CLI tests * Implement command to get validator address and pubkey from key name * Add support for getting validator key information via REST endpoint * Update PENDING log * Update docs * Revert GaiaGenTx.PubKey bech32 prefix * Fix broken docs and cli tests * Update genesis to use correct Bech32 (cons) prefix for pubkeys * Update docs and unit tests to reflect new cosmos account bech32 prefix * minor formatting --- PENDING.md | 8 + client/keys/add.go | 3 +- client/keys/root.go | 2 +- client/keys/show.go | 110 ++++-- client/keys/utils.go | 70 +++- client/lcd/lcd_test.go | 64 ++-- client/rpc/validators.go | 2 +- cmd/gaia/app/genesis.go | 9 +- cmd/gaia/app/sim_test.go | 4 +- cmd/gaia/cli_test/cli_test.go | 15 +- docs/clients/lcd-rest-api.yaml | 6 +- docs/clients/ledger.md | 2 +- docs/ics/ics-030-signed-messages.md | 2 +- docs/light/api.md | 24 +- docs/sdk/clients.md | 76 ++-- docs/spec/other/bech32.md | 27 +- docs/validators/validator-faq.md | 13 +- docs/validators/validator-setup.md | 14 +- examples/README.md | 20 +- examples/democoin/mock/validator.go | 8 +- examples/democoin/x/assoc/validator_set.go | 22 +- examples/democoin/x/oracle/handler.go | 4 +- examples/democoin/x/pow/types_test.go | 4 +- server/tm_cmds.go | 4 +- types/account.go | 420 +++++++++++++++------ types/account_test.go | 80 +++- types/stake.go | 6 +- x/bank/msgs_test.go | 4 +- x/gov/endblocker_test.go | 19 +- x/gov/handler.go | 8 +- x/gov/tally.go | 24 +- x/gov/tally_test.go | 124 ++++-- x/gov/test_common.go | 14 + x/slashing/app_test.go | 8 +- x/slashing/client/cli/query.go | 2 +- x/slashing/client/cli/tx.go | 4 +- x/slashing/client/rest/query.go | 2 +- x/slashing/client/rest/tx.go | 6 +- x/slashing/handler_test.go | 6 +- x/slashing/keeper_test.go | 30 +- x/slashing/msg.go | 10 +- x/slashing/msg_test.go | 4 +- x/slashing/simulation/msgs.go | 2 +- x/slashing/test_common.go | 4 +- x/slashing/tick_test.go | 4 +- x/stake/app_test.go | 34 +- x/stake/client/cli/query.go | 12 +- x/stake/client/cli/tx.go | 58 +-- x/stake/client/rest/query.go | 47 ++- x/stake/client/rest/tx.go | 67 ++-- x/stake/client/rest/utils.go | 25 +- x/stake/genesis_test.go | 10 +- x/stake/handler_test.go | 92 ++--- x/stake/keeper/delegation.go | 71 ++-- x/stake/keeper/key.go | 80 ++-- x/stake/keeper/sdk_types.go | 4 +- x/stake/keeper/test_common.go | 12 +- x/stake/keeper/validator.go | 8 +- x/stake/keeper/validator_test.go | 52 +-- x/stake/simulation/msgs.go | 22 +- x/stake/types/delegation.go | 19 +- x/stake/types/delegation_test.go | 22 +- x/stake/types/msg.go | 105 +++--- x/stake/types/msg_test.go | 92 ++--- x/stake/types/test_utils.go | 8 +- x/stake/types/validator.go | 16 +- 66 files changed, 1315 insertions(+), 835 deletions(-) diff --git a/PENDING.md b/PENDING.md index 14747be9d6..832f25e8f4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -14,12 +14,18 @@ BREAKING CHANGES * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * [makefile] `get_vendor_deps` no longer updates lock file it just updates vendor directory. Use `update_vendor_deps` to update the lock file. [#2152](https://github.com/cosmos/cosmos-sdk/pull/2152) * [cli] \#2190 `gaiacli init --gen-txs` is now `gaiacli init --with-txs` to reduce confusion + * \#2040 All commands that utilize a validator's address must now use the new + bech32 prefix, `cosmosval`. A validator's Tendermint signing key and address + now use a new bech32 prefix, `cosmoscons`. * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) * [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface. * [docs] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) Update slashing spec for slashing period * [x/stake, x/slashing] [#1305](https://github.com/cosmos/cosmos-sdk/issues/1305) - Rename "revoked" to "jailed" + * [x/stake] \#2040 Validator operator type has now changed to `sdk.ValAddress` + * A new bech32 prefix has been introduced for Tendermint signing keys and + addresses, `cosmosconspub` and `cosmoscons` respectively. * SDK * [core] \#1807 Switch from use of rational to decimal @@ -38,6 +44,8 @@ FEATURES * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params * [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in + * \#2040 Add `--bech` to `gaiacli keys show` and respective REST endpoint to + provide desired Bech32 prefix encoding * [cli] \#2047 Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution. The gas estimate obtained via the simulation will be used as gas limit in the actual execution. * [cli] \#2047 The --gas-adjustment flag can be used to adjust the estimate obtained via the simulation triggered by --gas=0. diff --git a/client/keys/add.go b/client/keys/add.go index d462db1c06..c421728196 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -128,7 +128,8 @@ func printCreate(info keys.Info, seed string) { output := viper.Get(cli.OutputFlag) switch output { case "text": - printInfo(info) + printKeyInfo(info, Bech32KeyOutput) + // print seed unless requested not to. if !viper.GetBool(client.FlagUseLedger) && !viper.GetBool(flagNoBackup) { fmt.Println("**Important** write this seed phrase in a safe place.") diff --git a/client/keys/root.go b/client/keys/root.go index c8f6aea693..f2a27dc0c8 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -21,7 +21,7 @@ func Commands() *cobra.Command { cmd.AddCommand( addKeyCommand(), listKeysCmd, - showKeysCmd, + showKeysCmd(), client.LineBreak, deleteKeyCommand(), updateKeyCommand(), diff --git a/client/keys/show.go b/client/keys/show.go index e9d692ece5..9710cac11e 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -2,6 +2,7 @@ package keys import ( "encoding/json" + "fmt" "net/http" "github.com/cosmos/cosmos-sdk/crypto/keys" @@ -18,46 +19,69 @@ const ( FlagAddress = "address" // FlagPublicKey represents the user's public key on the command line. FlagPublicKey = "pubkey" + // FlagBechPrefix defines a desired Bech32 prefix encoding for a key + FlagBechPrefix = "bech" ) -var showKeysCmd = &cobra.Command{ - Use: "show ", - Short: "Show key info for the given name", - Long: `Return public details of one local key.`, - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - name := args[0] - info, err := getKey(name) - if err != nil { - return err - } +func showKeysCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "show [name]", + Short: "Show key info for the given name", + Long: `Return public details of one local key.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + info, err := getKey(name) + if err != nil { + return err + } - showAddress := viper.GetBool(FlagAddress) - showPublicKey := viper.GetBool(FlagPublicKey) - outputSet := cmd.Flag(cli.OutputFlag).Changed - if showAddress && showPublicKey { - return errors.New("cannot use both --address and --pubkey at once") - } - if outputSet && (showAddress || showPublicKey) { - return errors.New("cannot use --output with --address or --pubkey") - } - if showAddress { - printKeyAddress(info) - return nil - } - if showPublicKey { - printPubKey(info) - return nil - } + showAddress := viper.GetBool(FlagAddress) + showPublicKey := viper.GetBool(FlagPublicKey) + outputSet := cmd.Flag(cli.OutputFlag).Changed - printInfo(info) - return nil - }, + if showAddress && showPublicKey { + return errors.New("cannot use both --address and --pubkey at once") + } + if outputSet && (showAddress || showPublicKey) { + return errors.New("cannot use --output with --address or --pubkey") + } + + bechKeyOut, err := getBechKeyOut(viper.GetString(FlagBechPrefix)) + if err != nil { + return err + } + + switch { + case showAddress: + printKeyAddress(info, bechKeyOut) + case showPublicKey: + printPubKey(info, bechKeyOut) + default: + printKeyInfo(info, bechKeyOut) + } + return nil + }, + } + + cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)") + cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") + cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") + + return cmd } -func init() { - showKeysCmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") - showKeysCmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") +func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { + switch bechPrefix { + case "acc": + return Bech32KeyOutput, nil + case "val": + return Bech32ValKeyOutput, nil + case "cons": + return Bech32ConsKeyOutput, nil + } + + return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix) } func getKey(name string) (keys.Info, error) { @@ -76,21 +100,35 @@ func getKey(name string) (keys.Info, error) { func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] + bechPrefix := r.URL.Query().Get(FlagBechPrefix) + + if bechPrefix == "" { + bechPrefix = "acc" + } + + bechKeyOut, err := getBechKeyOut(bechPrefix) + if err != nil { + w.WriteHeader(400) + w.Write([]byte(err.Error())) + return + } info, err := getKey(name) - // TODO check for the error if key actually does not exist, instead of assuming this as the reason + // TODO: check for the error if key actually does not exist, instead of + // assuming this as the reason if err != nil { w.WriteHeader(404) w.Write([]byte(err.Error())) return } - keyOutput, err := Bech32KeyOutput(info) + keyOutput, err := bechKeyOut(info) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } + output, err := json.MarshalIndent(keyOutput, "", " ") if err != nil { w.WriteHeader(500) diff --git a/client/keys/utils.go b/client/keys/utils.go index aa1b4bed9c..95fc83ed65 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -21,6 +21,8 @@ const KeyDBName = "keys" // keybase is used to make GetKeyBase a singleton var keybase keys.Keybase +type bechKeyOutFn func(keyInfo keys.Info) (KeyOutput, error) + // TODO make keybase take a database not load from the directory // initialize a keybase based on the configuration @@ -97,11 +99,11 @@ func SetKeyBase(kb keys.Keybase) { // used for outputting keys.Info over REST type KeyOutput struct { - Name string `json:"name"` - Type string `json:"type"` - Address sdk.AccAddress `json:"address"` - PubKey string `json:"pub_key"` - Seed string `json:"seed,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Address string `json:"address"` + PubKey string `json:"pub_key"` + Seed string `json:"seed,omitempty"` } // create a list of KeyOutput in bech32 format @@ -119,24 +121,61 @@ func Bech32KeysOutput(infos []keys.Info) ([]KeyOutput, error) { // create a KeyOutput in bech32 format func Bech32KeyOutput(info keys.Info) (KeyOutput, error) { - account := sdk.AccAddress(info.GetPubKey().Address().Bytes()) + accAddr := sdk.AccAddress(info.GetPubKey().Address().Bytes()) bechPubKey, err := sdk.Bech32ifyAccPub(info.GetPubKey()) if err != nil { return KeyOutput{}, err } + return KeyOutput{ Name: info.GetName(), Type: info.GetType().String(), - Address: account, + Address: accAddr.String(), PubKey: bechPubKey, }, nil } -func printInfo(info keys.Info) { - ko, err := Bech32KeyOutput(info) +// Bech32ConsKeyOutput returns key output for a consensus node's key +// information. +func Bech32ConsKeyOutput(keyInfo keys.Info) (KeyOutput, error) { + consAddr := sdk.ConsAddress(keyInfo.GetPubKey().Address().Bytes()) + + bechPubKey, err := sdk.Bech32ifyConsPub(keyInfo.GetPubKey()) + if err != nil { + return KeyOutput{}, err + } + + return KeyOutput{ + Name: keyInfo.GetName(), + Type: keyInfo.GetType().String(), + Address: consAddr.String(), + PubKey: bechPubKey, + }, nil +} + +// Bech32ValKeyOutput returns key output for a validator's key information. +func Bech32ValKeyOutput(keyInfo keys.Info) (KeyOutput, error) { + valAddr := sdk.ValAddress(keyInfo.GetPubKey().Address().Bytes()) + + bechPubKey, err := sdk.Bech32ifyValPub(keyInfo.GetPubKey()) + if err != nil { + return KeyOutput{}, err + } + + return KeyOutput{ + Name: keyInfo.GetName(), + Type: keyInfo.GetType().String(), + Address: valAddr.String(), + PubKey: bechPubKey, + }, nil +} + +func printKeyInfo(keyInfo keys.Info, bechKeyOut bechKeyOutFn) { + ko, err := bechKeyOut(keyInfo) if err != nil { panic(err) } + switch viper.Get(cli.OutputFlag) { case "text": fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n") @@ -146,6 +185,7 @@ func printInfo(info keys.Info) { if err != nil { panic(err) } + fmt.Println(string(out)) } } @@ -174,18 +214,20 @@ func printKeyOutput(ko KeyOutput) { fmt.Printf("%s\t%s\t%s\t%s\n", ko.Name, ko.Type, ko.Address, ko.PubKey) } -func printKeyAddress(info keys.Info) { - ko, err := Bech32KeyOutput(info) +func printKeyAddress(info keys.Info, bechKeyOut bechKeyOutFn) { + ko, err := bechKeyOut(info) if err != nil { panic(err) } - fmt.Println(ko.Address.String()) + + fmt.Println(ko.Address) } -func printPubKey(info keys.Info) { - ko, err := Bech32KeyOutput(info) +func printPubKey(info keys.Info, bechKeyOut bechKeyOutFn) { + ko, err := bechKeyOut(info) if err != nil { panic(err) } + fmt.Println(ko.PubKey) } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 298cf0027e..d68ba278c1 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -62,7 +62,7 @@ func TestKeys(t *testing.T) { err = wire.Cdc.UnmarshalJSON([]byte(body), &resp) require.Nil(t, err, body) - addr2Bech32 := resp.Address.String() + addr2Bech32 := resp.Address _, err = sdk.AccAddressFromBech32(addr2Bech32) require.NoError(t, err, "Failed to return a correct bech32 address") @@ -81,9 +81,9 @@ func TestKeys(t *testing.T) { addrBech32 := addr.String() require.Equal(t, name, m[0].Name, "Did not serve keys name correctly") - require.Equal(t, addrBech32, m[0].Address.String(), "Did not serve keys Address correctly") + require.Equal(t, addrBech32, m[0].Address, "Did not serve keys Address correctly") require.Equal(t, newName, m[1].Name, "Did not serve keys name correctly") - require.Equal(t, addr2Bech32, m[1].Address.String(), "Did not serve keys Address correctly") + require.Equal(t, addr2Bech32, m[1].Address, "Did not serve keys Address correctly") // select key keyEndpoint := fmt.Sprintf("/keys/%s", newName) @@ -94,7 +94,7 @@ func TestKeys(t *testing.T) { require.Nil(t, err) require.Equal(t, newName, m2.Name, "Did not serve keys name correctly") - require.Equal(t, addr2Bech32, m2.Address.String(), "Did not serve keys Address correctly") + require.Equal(t, addr2Bech32, m2.Address, "Did not serve keys Address correctly") // update key jsonStr = []byte(fmt.Sprintf(`{ @@ -204,8 +204,8 @@ func TestValidators(t *testing.T) { require.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals) - require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosvaladdr") - require.Contains(t, resultVals.Validators[0].PubKey, "cosmosvalpub") + require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosval") + require.Contains(t, resultVals.Validators[0].PubKey, "cosmosconspub") // -- @@ -313,7 +313,7 @@ func TestTxs(t *testing.T) { require.Equal(t, http.StatusBadRequest, res.StatusCode, body) // query empty - res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32='%s'", "cosmosaccaddr1jawd35d9aq4u76sr3fjalmcqc8hqygs9gtnmv3"), nil) + res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32='%s'", "cosmos1jawd35d9aq4u76sr3fjalmcqc8hqygs90d0g0v"), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, "[]", body) @@ -407,7 +407,7 @@ func TestValidatorsQuery(t *testing.T) { // make sure all the validators were found (order unknown because sorted by operator addr) foundVal := false - pkBech := sdk.MustBech32ifyValPub(pks[0]) + pkBech := sdk.MustBech32ifyConsPub(pks[0]) if validators[0].PubKey == pkBech { foundVal = true } @@ -419,7 +419,7 @@ func TestValidatorQuery(t *testing.T) { defer cleanup() require.Equal(t, 1, len(pks)) - validator1Operator := sdk.AccAddress(pks[0].Address()) + validator1Operator := sdk.ValAddress(pks[0].Address()) validator := getValidator(t, port, validator1Operator) assert.Equal(t, validator.Operator, validator1Operator, "The returned validator does not hold the correct data") } @@ -430,7 +430,7 @@ func TestBonding(t *testing.T) { cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() - validator1Operator := sdk.AccAddress(pks[0].Address()) + validator1Operator := sdk.ValAddress(pks[0].Address()) validator := getValidator(t, port, validator1Operator) // create bond TX @@ -611,7 +611,7 @@ func TestUnjail(t *testing.T) { // XXX: any less than this and it fails tests.WaitForHeight(3, port) - pkString, _ := sdk.Bech32ifyValPub(pks[0]) + pkString, _ := sdk.Bech32ifyConsPub(pks[0]) signingInfo := getSigningInfo(t, port, pkString) tests.WaitForHeight(4, port) require.Equal(t, true, signingInfo.IndexOffset > 0) @@ -817,8 +817,8 @@ func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing. // ============= Stake Module ================ -func getDelegation(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) rest.DelegationWithoutRat { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delegatorAddr, validatorAddr), nil) +func getDelegation(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) rest.DelegationWithoutRat { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delAddr, valAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var bond rest.DelegationWithoutRat @@ -829,8 +829,8 @@ func getDelegation(t *testing.T, port string, delegatorAddr, validatorAddr sdk.A return bond } -func getUndelegations(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) []stake.UnbondingDelegation { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delegatorAddr, validatorAddr), nil) +func getUndelegations(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) []stake.UnbondingDelegation { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delAddr, valAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var unbondings []stake.UnbondingDelegation @@ -884,8 +884,8 @@ func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddr return bondedValidators } -func getDelegatorValidator(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) stake.BechValidator { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delegatorAddr, validatorAddr), nil) +func getDelegatorValidator(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) stake.BechValidator { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delAddr, valAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var bondedValidator stake.BechValidator @@ -895,8 +895,10 @@ func getDelegatorValidator(t *testing.T, port string, delegatorAddr sdk.AccAddre return bondedValidator } -func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, validatorAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { - acc := getAccount(t, port, delegatorAddr) +func doDelegate(t *testing.T, port, seed, name, password string, + delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { + + acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) @@ -918,9 +920,9 @@ func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, "complete_unbondings": [], "begin_redelegates": [], "complete_redelegates": [] - }`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, "steak", amount)) + }`, name, password, accnum, sequence, chainID, delAddr, valAddr, "steak", amount)) - res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr) + res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr) require.Equal(t, http.StatusOK, res.StatusCode, body) var results []ctypes.ResultBroadcastTxCommit @@ -931,9 +933,9 @@ func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, } func doBeginUnbonding(t *testing.T, port, seed, name, password string, - delegatorAddr, validatorAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { + delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { - acc := getAccount(t, port, delegatorAddr) + acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) @@ -955,9 +957,9 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string, "complete_unbondings": [], "begin_redelegates": [], "complete_redelegates": [] - }`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, amount)) + }`, name, password, accnum, sequence, chainID, delAddr, valAddr, amount)) - res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr) + res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr) require.Equal(t, http.StatusOK, res.StatusCode, body) var results []ctypes.ResultBroadcastTxCommit @@ -968,9 +970,9 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string, } func doBeginRedelegation(t *testing.T, port, seed, name, password string, - delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) { + delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (resultTx ctypes.ResultBroadcastTxCommit) { - acc := getAccount(t, port, delegatorAddr) + acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() @@ -994,9 +996,9 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, } ], "complete_redelegates": [] - }`, name, password, accnum, sequence, chainID, delegatorAddr, validatorSrcAddr, validatorDstAddr)) + }`, name, password, accnum, sequence, chainID, delAddr, valSrcAddr, valDstAddr)) - res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr) + res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr) require.Equal(t, http.StatusOK, res.StatusCode, body) var results []ctypes.ResultBroadcastTxCommit @@ -1015,8 +1017,8 @@ func getValidators(t *testing.T, port string) []stake.BechValidator { return validators } -func getValidator(t *testing.T, port string, validatorAddr sdk.AccAddress) stake.BechValidator { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", validatorAddr.String()), nil) +func getValidator(t *testing.T, port string, valAddr sdk.ValAddress) stake.BechValidator { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", valAddr.String()), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var validator stake.BechValidator err := cdc.UnmarshalJSON([]byte(body), &validator) diff --git a/client/rpc/validators.go b/client/rpc/validators.go index d2daa4ec5c..cb002d3ea0 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -45,7 +45,7 @@ type ResultValidatorsOutput struct { } func bech32ValidatorOutput(validator *tmtypes.Validator) (ValidatorOutput, error) { - bechValPubkey, err := sdk.Bech32ifyValPub(validator.PubKey) + bechValPubkey, err := sdk.Bech32ifyConsPub(validator.PubKey) if err != nil { return ValidatorOutput{}, err } diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 0fbbc06031..bfcaa92dde 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -142,7 +142,7 @@ func GaiaAppGenTxNF(cdc *wire.Codec, pk crypto.PubKey, addr sdk.AccAddress, name gaiaGenTx := GaiaGenTx{ Name: name, Address: addr, - PubKey: sdk.MustBech32ifyAccPub(pk), + PubKey: sdk.MustBech32ifyConsPub(pk), } bz, err = wire.MarshalJSONIndent(cdc, gaiaGenTx) if err != nil { @@ -192,8 +192,9 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // add the validator if len(genTx.Name) > 0 { desc := stake.NewDescription(genTx.Name, "", "", "") - validator := stake.NewValidator(genTx.Address, - sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc) + validator := stake.NewValidator( + sdk.ValAddress(genTx.Address), sdk.MustGetConsPubKeyBech32(genTx.PubKey), desc, + ) stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply @@ -204,7 +205,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // create the self-delegation from the issuedDelShares delegation := stake.Delegation{ - DelegatorAddr: validator.Operator, + DelegatorAddr: sdk.AccAddress(validator.Operator), ValidatorAddr: validator.Operator, Shares: issuedDelShares, Height: 0, diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 0ca936bdbf..559b8b4b9a 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -57,10 +57,10 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json // XXX Try different numbers of initially bonded validators numInitiallyBonded := int64(50) for i := 0; i < int(numInitiallyBonded); i++ { - validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) + validator := stake.NewValidator(sdk.ValAddress(accs[i]), keys[i].PubKey(), stake.Description{}) validator.Tokens = sdk.NewDec(100) validator.DelegatorShares = sdk.NewDec(100) - delegation := stake.Delegation{accs[i], accs[i], sdk.NewDec(100), 0} + delegation := stake.Delegation{accs[i], sdk.ValAddress(accs[i]), sdk.NewDec(100), 0} validators = append(validators, validator) delegations = append(delegations, delegation) } diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index f794e5140d..b91b5a45d6 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -124,7 +124,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --output=json --home=%s", gaiacliHome)) barAddr, barPubKey := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show bar --output=json --home=%s", gaiacliHome)) - barCeshPubKey := sdk.MustBech32ifyValPub(barPubKey) + barCeshPubKey := sdk.MustBech32ifyConsPub(barPubKey) executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -154,14 +154,14 @@ func TestGaiaCLICreateValidator(t *testing.T) { barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", barAddr, flags)) require.Equal(t, int64(8), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc) - validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) - require.Equal(t, validator.Operator, barAddr) + validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", sdk.ValAddress(barAddr), flags)) + require.Equal(t, validator.Operator, sdk.ValAddress(barAddr)) require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens)) // unbond a single share unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) unbondStr += fmt.Sprintf(" --from=%s", "bar") - unbondStr += fmt.Sprintf(" --validator=%s", barAddr) + unbondStr += fmt.Sprintf(" --validator=%s", sdk.ValAddress(barAddr)) unbondStr += fmt.Sprintf(" --shares-amount=%v", "1") success := executeWrite(t, unbondStr, app.DefaultKeyPass) @@ -172,7 +172,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags)) require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc) */ - validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) + validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", sdk.ValAddress(barAddr), flags)) require.Equal(t, "1.0000000000", validator.Tokens.String()) params := executeGetParams(t, fmt.Sprintf("gaiacli stake parameters --output=json %v", flags)) @@ -352,7 +352,10 @@ func executeGetAddrPK(t *testing.T, cmdStr string) (sdk.AccAddress, crypto.PubKe pk, err := sdk.GetAccPubKeyBech32(ko.PubKey) require.NoError(t, err) - return ko.Address, pk + accAddr, err := sdk.AccAddressFromBech32(ko.Address) + require.NoError(t, err) + + return accAddr, pk } func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { diff --git a/docs/clients/lcd-rest-api.yaml b/docs/clients/lcd-rest-api.yaml index 5be69302d5..4f402089ad 100644 --- a/docs/clients/lcd-rest-api.yaml +++ b/docs/clients/lcd-rest-api.yaml @@ -710,15 +710,15 @@ definitions: Address: type: string description: bech32 encoded addres - example: cosmosaccaddr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq + example: cosmos:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq ValidatorAddress: type: string description: bech32 encoded addres - example: cosmosvaladdr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq + example: cosmosval:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq PubKey: type: string description: bech32 encoded public key - example: cosmosaccpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq + example: cosmospub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq ValidatorPubKey: type: string description: bech32 encoded public key diff --git a/docs/clients/ledger.md b/docs/clients/ledger.md index 5ea1224eae..26b0215b3d 100644 --- a/docs/clients/ledger.md +++ b/docs/clients/ledger.md @@ -17,7 +17,7 @@ Once you have the Cosmos app installed on your Ledger, and the Ledger is accessi ```bash $ gaiacli keys add {{ .Key.Name }} --ledger NAME: TYPE: ADDRESS: PUBKEY: -{{ .Key.Name }} ledger cosmosaccaddr1aw64xxr80lwqqdk8u2xhlrkxqaxamkr3e2g943 cosmosaccpub1addwnpepqvhs678gh9aqrjc2tg2vezw86csnvgzqq530ujkunt5tkuc7lhjkz5mj629 +{{ .Key.Name }} ledger cosmos1aw64xxr80lwqqdk8u2xhlrkxqaxamkr3e2g943 cosmospub1addwnpepqvhs678gh9aqrjc2tg2vezw86csnvgzqq530ujkunt5tkuc7lhjkz5mj629 ``` This key will only be accessible while the Ledger is plugged in and unlocked. To send some coins with this key, run the following: diff --git a/docs/ics/ics-030-signed-messages.md b/docs/ics/ics-030-signed-messages.md index e73d9f5803..8f53238f7e 100644 --- a/docs/ics/ics-030-signed-messages.md +++ b/docs/ics/ics-030-signed-messages.md @@ -186,7 +186,7 @@ data = { "text": "I hereby claim I am ABC on Keybase!" } -cosmosSignBytes(data, "cosmosaccaddr1pvsch6cddahhrn5e8ekw0us50dpnugwnlfngt3") +cosmosSignBytes(data, "cosmos1pvsch6cddahhrn5e8ekw0us50dpnugwnlfngt3") > "0x7fc4a495473045022100dec81a9820df0102381cdbf7e8b0f1e2cb64c58e0ecda1324543742e0388e41a02200df37905a6505c1b56a404e23b7473d2c0bc5bcda96771d2dda59df6ed2b98f8" ``` diff --git a/docs/light/api.md b/docs/light/api.md index 6c5e8aa5f0..7168cf9d74 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -71,13 +71,13 @@ This API exposes all functionality needed for key creation, signing and manageme "account":[ { "name":"monkey", - "address":"cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", - "pub_key":"cosmosaccpub1zcjduc3q8s8ha96ry4xc5xvjp9tr9w9p0e5lk5y0rpjs5epsfxs4wmf72x3shvus0t" + "address":"cosmos1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "pub_key":"cosmospub1zcjduc3q8s8ha96ry4xc5xvjp9tr9w9p0e5lk5y0rpjs5epsfxs4wmf72x3shvus0t" }, { "name":"test", - "address":"cosmosaccaddr1thlqhjqw78zvcy0ua4ldj9gnazqzavyw4eske2", - "pub_key":"cosmosaccpub1zcjduc3qyx6hlf825jcnj39adpkaxjer95q7yvy25yhfj3dmqy2ctev0rxmse9cuak" + "address":"cosmos1thlqhjqw78zvcy0ua4ldj9gnazqzavyw4eske2", + "pub_key":"cosmospub1zcjduc3qyx6hlf825jcnj39adpkaxjer95q7yvy25yhfj3dmqy2ctev0rxmse9cuak" } ], "block_height":5241 @@ -125,8 +125,8 @@ Returns on success: "error":"", "result":{ "name":"test", - "address":"cosmosaccaddr1thlqhjqw78zvcy0ua4ldj9gnazqzavyw4eske2", - "pub_key":"cosmosaccpub1zcjduc3qyx6hlf825jcnj39adpkaxjer95q7yvy25yhfj3dmqy2ctev0rxmse9cuak" + "address":"cosmos1thlqhjqw78zvcy0ua4ldj9gnazqzavyw4eske2", + "pub_key":"cosmospub1zcjduc3qyx6hlf825jcnj39adpkaxjer95q7yvy25yhfj3dmqy2ctev0rxmse9cuak" } } ``` @@ -588,7 +588,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "description": "string", // PlainTextProposal supported now. SoftwareUpgradeProposal and other types may be supported soon "proposal_type": "string", - // A cosmosaccaddr address + // A cosmos address "proposer": "string", "initial_deposit": [ { @@ -689,7 +689,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "error":"", "result":{ "amount": {"atom": 150}, - "depositer": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "depositer": "cosmos1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", "proposal-id": 16 } } @@ -731,12 +731,12 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "result": [ { "proposal-id": 1, - "voter": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "voter": "cosmos1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", "option": "no_with_veto" }, { "proposal-id": 1, - "voter": "cosmosaccaddr1849m9wncrqp6v4tkss6a3j8uzvuv0cp7f75lrq", + "voter": "cosmos1849m9wncrqp6v4tkss6a3j8uzvuv0cp7f75lrq", "option": "yes" }, ] @@ -761,7 +761,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "sequence": 0, "gas": 0 }, - // A cosmosaccaddr address + // A cosmos address "voter": "string", // Value of the vote option `Yes`, `No` `Abstain`, `NoWithVeto` "option": "string", @@ -794,7 +794,7 @@ The GovernanceAPI exposes all functionality needed for casting votes on plain te "error":"", "result":{ "proposal-id": 1, - "voter": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "voter": "cosmos1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", "option": "no_with_veto" } } diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 0a1c2a38d9..7a23ba28ac 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -18,17 +18,21 @@ There are three types of key representations that are used: -- `cosmosaccaddr` +- `cosmos` - Derived from account keys generated by `gaiacli keys add` - Used to receive funds - - e.g. `cosmosaccaddr15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc` -- `cosmosaccpub` + - e.g. `cosmos15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc` +* `cosmosval` + * Used to associate a validator to it's operator + * Used to invoke staking commands + * e.g. `cosmosval1carzvgq3e6y3z5kz5y6gxp3wpy3qdrv928vyah` +- `cosmospub` - Derived from account keys generated by `gaiacli keys add` - - e.g. `cosmosaccpub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm` -- `cosmosvalpub` + - e.g. `cosmospub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm` +- `cosmosconspub` - Generated when the node is created with `gaiad init`. - Get this value with `gaiad tendermint show-validator` - - e.g. `cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c` + - e.g. `cosmosconspub1zcjduepq0ms2738680y72v44tfyqm3c9ppduku8fs6sr73fx7m666sjztznqzp2emf` #### Generate Keys @@ -48,6 +52,12 @@ If you check your private keys, you'll now see ``: gaiacli keys show ``` +View the validator operator's address via: + +```shell +gaiacli keys show --bech=val +``` + You can see all your available keys by typing: ```bash @@ -68,18 +78,18 @@ We strongly recommend _NOT_ using the same passphrase for multiple keys. The Ten #### Get Tokens -The best way to get tokens is from the [Cosmos Testnet Faucet](https://faucetcosmos.network). If the faucet is not working for you, try asking [#cosmos-validators](https://riot.im/app/#/room/#cosmos-validators:matrix.org). The faucet needs the `cosmosaccaddr` from the account you wish to use for staking. +The best way to get tokens is from the [Cosmos Testnet Faucet](https://faucetcosmos.network). If the faucet is not working for you, try asking [#cosmos-validators](https://riot.im/app/#/room/#cosmos-validators:matrix.org). The faucet needs the `cosmos` from the account you wish to use for staking. #### Query Account balance After receiving tokens to your address, you can view your account's balance by typing: ```bash -gaiacli account +gaiacli account ``` ::: warning Note -When you query an account balance with zero tokens, you will get this error: `No account with address was found in the state.` This can also happen if you fund the account before your node has fully synced with the chain. These are both normal. +When you query an account balance with zero tokens, you will get this error: `No account with address was found in the state.` This can also happen if you fund the account before your node has fully synced with the chain. These are both normal. ::: @@ -90,7 +100,7 @@ gaiacli send \ --amount=10faucetToken \ --chain-id= \ --name= \ - --to= + --to= ``` ::: warning Note @@ -106,14 +116,14 @@ Gas estimate might be inaccurate as state changes could occur in between the end Now, view the updated balances of the origin and destination accounts: ```bash -gaiacli account -gaiacli account +gaiacli account +gaiacli account ``` You can also check your balance at a given block by using the `--block` flag: ```bash -gaiacli account --block= +gaiacli account --block= ``` ### Staking @@ -137,7 +147,7 @@ gaiacli stake validators If you want to get the information of a single validator you can check it with: ```bash -gaiacli stake validator +gaiacli stake validator ``` #### Bond Tokens @@ -164,14 +174,14 @@ Once submitted a delegation to a validator, you can see it's information by usin ```bash gaiacli stake delegation \ - --address-delegator= \ - --address-validator=$(gaiad tendermint show-validator) + --address-delegator= \ + --validator= ``` Or if you want to check all your current delegations with disctinct validators: ```bash -gaiacli stake delegations +gaiacli stake delegations ``` You can also get previous delegation(s) status by adding the `--height` flag. @@ -182,7 +192,7 @@ If for any reason the validator misbehaves, or you just want to unbond a certain ```bash gaiacli stake unbond begin \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator= \ --shares-percent=100 \ --from= \ --chain-id= @@ -192,7 +202,7 @@ Later you must complete the unbonding process by using the `gaiacli stake unbond ```bash gaiacli stake unbond complete \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator= \ --from= \ --chain-id= ``` @@ -203,14 +213,14 @@ Once you begin an unbonding-delegation, you can see it's information by using th ```bash gaiacli stake unbonding-delegation \ - --address-delegator= \ - --address-validator=$(gaiad tendermint show-validator) \ + --address-delegator= \ + --validator= \ ``` Or if you want to check all your current unbonding-delegations with disctinct validators: ```bash -gaiacli stake unbonding-delegations +gaiacli stake unbonding-delegations ``` You can also get previous unbonding-delegation(s) status by adding the `--height` flag. @@ -221,8 +231,8 @@ A redelegation is a type delegation that allows you to bond illiquid tokens from ```bash gaiacli stake redelegate begin \ - --address-validator-source=$(gaiad tendermint show-validator) \ - --address-validator-dest= \ + --address-validator-source= \ + --address-validator-dest= \ --shares-percent=50 \ --from= \ --chain-id= @@ -234,7 +244,7 @@ Later you must complete the redelegation process by using the `gaiacli stake red ```bash gaiacli stake unbond complete \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator= \ --from= \ --chain-id= ``` @@ -245,15 +255,15 @@ Once you begin an redelegation, you can see it's information by using the follow ```bash gaiacli stake redelegation \ - --address-delegator= \ - --address-validator-source=$(gaiad tendermint show-validator) \ - --address-validator-dest= \ + --address-delegator= \ + --address-validator-source= \ + --address-validator-dest= \ ``` Or if you want to check all your current unbonding-delegations with disctinct validators: ```bash -gaiacli stake redelegations +gaiacli stake redelegations ``` You can also get previous redelegation(s) status by adding the `--height` flag. @@ -286,7 +296,7 @@ gaiacli gov submit-proposal \ --title= \ --description=<description> \ --type=<Text/ParameterChange/SoftwareUpgrade> \ - --proposer=<account_cosmosaccaddr> \ + --proposer=<account_cosmos> \ --deposit=<40steak> \ --from=<name> \ --chain-id=<chain_id> @@ -316,7 +326,7 @@ In order for a proposal to be broadcasted to the network, the amount deposited m ```bash gaiacli gov deposit \ --proposal-id=<proposal_id> \ - --depositer=<account_cosmosaccaddr> \ + --depositer=<account_cosmos> \ --deposit=<200steak> \ --from=<name> \ --chain-id=<chain_id> @@ -331,7 +341,7 @@ After a proposal's deposit reaches the `MinDeposit` value, the voting period ope ```bash gaiacli gov vote \ --proposal-id=<proposal_id> \ - --voter=<account_cosmosaccaddr> \ + --voter=<account_cosmos> \ --option=<Yes/No/NoWithVeto/Abstain> \ --from=<name> \ --chain-id=<chain_id> @@ -344,7 +354,7 @@ Check the vote with the option you just submitted: ```bash gaiacli gov query-vote \ --proposal-id=<proposal_id> \ - --voter=<account_cosmosaccaddr> + --voter=<account_cosmos> ``` #### Query Parameters diff --git a/docs/spec/other/bech32.md b/docs/spec/other/bech32.md index 1558c1ec37..911102a8a7 100644 --- a/docs/spec/other/bech32.md +++ b/docs/spec/other/bech32.md @@ -1,25 +1,24 @@ # Bech32 on Cosmos -The Cosmos network prefers to use the Bech32 address format whereever users must handle binary data. Bech32 encoding provides robust integrity checks on data and the human readable part(HRP) provides contextual hints that can assist UI developers with providing informative error messages. +The Cosmos network prefers to use the Bech32 address format wherever users must handle binary data. Bech32 encoding provides robust integrity checks on data and the human readable part(HRP) provides contextual hints that can assist UI developers with providing informative error messages. In the Cosmos network, keys and addresses may refer to a number of different roles in the network like accounts, validators etc. +## HRP table -## HRP table - -| HRP | Definition | -| ------------- |:-------------:| -| `cosmos` | Cosmos Account Address | -| `cosmospub` | Cosmos Account Public Key | -| `cosmosval` | Cosmos Validator Consensus Address | -| `cosmosvalpub`| Cosmos Validator Consensus Public Key| +| HRP | Definition | +|---------------|--------------------------------------| +| cosmos | Cosmos Account Address | +| cosmospub | Cosmos Account Public Key | +| cosmoscons | Cosmos Consensus Address | +| cosmosconspub | Cosmos Consensus Public Key | +| cosmosval | Cosmos Validator Operator Address | +| cosmosvalpub | Cosmos Validator Operator Public Key | ## Encoding -While all user facing interfaces to Cosmos software should exposed bech32 interfaces, many internal interfaces encode binary value in hex or base64 encoded form. +While all user facing interfaces to Cosmos software should exposed Bech32 interfaces, many internal interfaces encode binary value in hex or base64 encoded form. -To covert between other binary reprsentation of addresses and keys, it is important to first apply the Amino enocoding process before bech32 encoding. +To covert between other binary representation of addresses and keys, it is important to first apply the Amino encoding process before bech32 encoding. -A complete implementation of the Amino serialization format is unncessary in most cases. Simply prepending bytes from this [table](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography) to the bytestring payload before bech32 encoding will sufficient for compatible representation. - -  +A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography) to the byte string payload before bech32 encoding will sufficient for compatible representation. diff --git a/docs/validators/validator-faq.md b/docs/validators/validator-faq.md index 6018ac3233..470f139d43 100644 --- a/docs/validators/validator-faq.md +++ b/docs/validators/validator-faq.md @@ -77,13 +77,14 @@ We view testnet participation as a great way to signal to the community that you In short, there are two types of keys: -- **Tendermint Key**: This is a unique key used to sign block hashes. It is associated with a public key `cosmosvalpub`. - + Generated when the node is created with gaiad init. - + Get this value with gaiad tendermint show_validator - +M e.g. cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c - -- **Application keys**: These keys are created from the application and used to sign transactions. As a validator, you will probably use one key to sign staking-related transactions, and another key to sign governance-related transactions. Application keys are associated with a public key `cosmosaccpub` and an address `cosmosaccaddr`. Both are derived from account keys generated by `gaiacli keys add`. +* **Tendermint Key**: This is a unique key used to sign block hashes. It is associated with a public key `cosmosconspub`. + * Generated when the node is created with gaiad init. + * Get this value with `gaiad tendermint show-validator` + e.g. `cosmosconspub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c` +* **Application keys**: These keys are created from the application and used to sign transactions. As a validator, you will probably use one key to sign staking-related transactions, and another key to sign governance-related transactions. Application keys are associated with a public key `cosmospub` and an address `cosmos`. Both are derived from account keys generated by `gaiacli keys add`. + * Note: A validator's operator key is directly tied to an application key, but + uses reserved prefixes solely for this purpose: `cosmosval` and `cosmosvalpub` ### What are the different states a validator can be in? diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 6fa4fefd21..8bf3e951de 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -16,7 +16,7 @@ If you want to become a validator for the Hub's `mainnet`, you should [research ### Create Your Validator -Your `cosmosvalpub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running: +Your `cosmosconspub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running: ```bash gaiad tendermint show-validator @@ -32,7 +32,7 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau gaiacli stake create-validator \ --amount=5steak \ --pubkey=$(gaiad tendermint show-validator) \ - --address-validator=<account_cosmosaccaddr> + --address-validator=<account_cosmosval> --moniker="choose a moniker" \ --chain-id=<chain_id> \ --name=<key_name> @@ -46,7 +46,7 @@ The `--identity` can be used as to verify identity with systems like Keybase or ```bash gaiacli stake edit-validator - --validator=<account_cosmosaccaddr> + --validator=<account_cosmos> --moniker="choose a moniker" \ --website="https://cosmos.network" \ --identity=6A0D65E29A4CBC8E @@ -60,7 +60,7 @@ gaiacli stake edit-validator View the validator's information with this command: ```bash -gaiacli stake validator <account_cosmosaccaddr> +gaiacli stake validator <account_cosmos> ``` ### Track Validator Signing Information @@ -80,7 +80,7 @@ When a validator is "jailed" for downtime, you must submit an `Unjail` transacti gaiacli stake unjail \ --from=<key_name> \ --chain-id=<chain_id> - --validator=<account_cosmosaccaddr> \ + --validator=<account_cosmosval> \ --chain-id=gaia-6002 ``` @@ -110,10 +110,10 @@ Here's how you can return the voting power back to your validator. First, if `ga gaiad start ``` -Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmosaccaddr>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`. +Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmos>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`. ```bash -gaiacli stake unjail <cosmosaccaddr> --chain-id=<chain_id> --name=<name> +gaiacli stake unjail <cosmos> --chain-id=<chain_id> --name=<name> ``` ::: danger Warning diff --git a/examples/README.md b/examples/README.md index d12e3d3fcc..11aef9d280 100644 --- a/examples/README.md +++ b/examples/README.md @@ -103,10 +103,10 @@ basecli keys list You should now see alice, bob and charlie's account all show up. ``` -NAME: ADDRESS: PUBKEY: -alice cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f cosmosaccpub1addwnpepq0w037u5g7y7lvdvsred2dehg90j84k0weyss5ynysf0nnnax74agrsxns6 -bob cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz cosmosaccpub1addwnpepqwe97n8lryxrzvamrvjfj24jys3uzf8wndfvqa2l7mh5nsv4jrvdznvyeg6 -charlie cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q cosmosaccpub1addwnpepqdmtxv35rrmv2dvcr3yhfyxj7dzrd4z4rnhmclksq4g55a4wpl54clvx33l +NAME: ADDRESS: PUBKEY: +alice cosmos1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f cosmospub1addwnpepq0w037u5g7y7lvdvsred2dehg90j84k0weyss5ynysf0nnnax74agrsxns6 +bob cosmos18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz cosmospub1addwnpepqwe97n8lryxrzvamrvjfj24jys3uzf8wndfvqa2l7mh5nsv4jrvdznvyeg6 +charlie cosmos13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q cosmospub1addwnpepqdmtxv35rrmv2dvcr3yhfyxj7dzrd4z4rnhmclksq4g55a4wpl54clvx33l ``` @@ -115,15 +115,15 @@ charlie cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q cosmosaccpub1addwnp Lets send bob and charlie some tokens. First, lets query alice's account so we can see what kind of tokens she has: ``` -basecli account cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f +basecli account cosmos1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f ``` -Where `cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some! +Where `cosmos1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some! The following command will send coins from alice, to bob: ``` -basecli send --from=alice --amount=10000mycoin --to=cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz +basecli send --from=alice --amount=10000mycoin --to=cosmos18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz --sequence=0 --chain-id=test-chain-AE4XQo ``` @@ -136,13 +136,13 @@ Flag Descriptions: Now if we check bobs account, it should have `10000 mycoin`. You can do so by running : ``` -basecli account cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz +basecli account cosmos18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz ``` Now lets send some from bob to charlie. Make sure you send less than bob has, otherwise the transaction will fail: ``` -basecli send --from=bob --amount=5000mycoin --to=cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q +basecli send --from=bob --amount=5000mycoin --to=cosmos13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q --sequence=0 --chain-id=test-chain-AE4XQo ``` @@ -151,7 +151,7 @@ Note how we use the ``--from`` flag to select a different account to send from. Lets now try to send from bob back to alice: ``` -basecli send --from=bob --amount=3000mycoin --to=cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f +basecli send --from=bob --amount=3000mycoin --to=cosmos1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f --sequence=1 --chain-id=test-chain-AE4XQo ``` diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index bb936097cc..f937e45dcc 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -9,7 +9,7 @@ import ( // Validator implements sdk.Validator type Validator struct { - Address sdk.AccAddress + Address sdk.ValAddress Power sdk.Dec } @@ -19,7 +19,7 @@ func (v Validator) GetStatus() sdk.BondStatus { } // Implements sdk.Validator -func (v Validator) GetOperator() sdk.AccAddress { +func (v Validator) GetOperator() sdk.ValAddress { return v.Address } @@ -78,9 +78,9 @@ func (vs *ValidatorSet) IterateValidatorsBonded(ctx sdk.Context, fn func(index i } // Validator implements sdk.ValidatorSet -func (vs *ValidatorSet) Validator(ctx sdk.Context, addr sdk.AccAddress) sdk.Validator { +func (vs *ValidatorSet) Validator(ctx sdk.Context, addr sdk.ValAddress) sdk.Validator { for _, val := range vs.Validators { - if bytes.Equal(val.Address, addr) { + if bytes.Equal(val.Address.Bytes(), addr.Bytes()) { return val } } diff --git a/examples/democoin/x/assoc/validator_set.go b/examples/democoin/x/assoc/validator_set.go index ad89aab192..8a954c7203 100644 --- a/examples/democoin/x/assoc/validator_set.go +++ b/examples/democoin/x/assoc/validator_set.go @@ -37,7 +37,7 @@ func NewValidatorSet(cdc *wire.Codec, store sdk.KVStore, valset sdk.ValidatorSet } // Implements sdk.ValidatorSet -func (valset ValidatorSet) Validator(ctx sdk.Context, addr sdk.AccAddress) (res sdk.Validator) { +func (valset ValidatorSet) Validator(ctx sdk.Context, addr sdk.ValAddress) (res sdk.Validator) { base := valset.store.Get(GetBaseKey(addr)) res = valset.ValidatorSet.Validator(ctx, base) if res == nil { @@ -46,23 +46,23 @@ func (valset ValidatorSet) Validator(ctx sdk.Context, addr sdk.AccAddress) (res return } -// GetBaseKey :: sdk.AccAddress -> sdk.AccAddress -func GetBaseKey(addr sdk.AccAddress) []byte { +// GetBaseKey :: sdk.ValAddress -> sdk.ValAddress +func GetBaseKey(addr sdk.ValAddress) []byte { return append([]byte{0x00}, addr...) } -// GetAssocPrefix :: sdk.AccAddress -> (sdk.AccAddress -> byte) -func GetAssocPrefix(base sdk.AccAddress) []byte { +// GetAssocPrefix :: sdk.ValAddress -> (sdk.ValAddress -> byte) +func GetAssocPrefix(base sdk.ValAddress) []byte { return append([]byte{0x01}, base...) } -// GetAssocKey :: (sdk.AccAddress, sdk.AccAddress) -> byte -func GetAssocKey(base sdk.AccAddress, assoc sdk.AccAddress) []byte { +// GetAssocKey :: (sdk.ValAddress, sdk.ValAddress) -> byte +func GetAssocKey(base sdk.ValAddress, assoc sdk.ValAddress) []byte { return append(append([]byte{0x01}, base...), assoc...) } // Associate associates new address with validator address -func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.AccAddress, assoc sdk.AccAddress) bool { +func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.ValAddress, assoc sdk.ValAddress) bool { if len(base) != valset.addrLen || len(assoc) != valset.addrLen { return false } @@ -76,7 +76,7 @@ func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.AccAddress, assoc } // Dissociate removes association between addresses -func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.AccAddress, assoc sdk.AccAddress) bool { +func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.ValAddress, assoc sdk.ValAddress) bool { if len(base) != valset.addrLen || len(assoc) != valset.addrLen { return false } @@ -90,8 +90,8 @@ func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.AccAddress, asso } // Associations returns all associated addresses with a validator -func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.AccAddress) (res []sdk.AccAddress) { - res = make([]sdk.AccAddress, valset.maxAssoc) +func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.ValAddress) (res []sdk.ValAddress) { + res = make([]sdk.ValAddress, valset.maxAssoc) iter := sdk.KVStorePrefixIterator(valset.store, GetAssocPrefix(base)) defer iter.Close() i := 0 diff --git a/examples/democoin/x/oracle/handler.go b/examples/democoin/x/oracle/handler.go index 1aaefc7e16..c525222c4c 100644 --- a/examples/democoin/x/oracle/handler.go +++ b/examples/democoin/x/oracle/handler.go @@ -68,8 +68,8 @@ func (keeper Keeper) Handle(h Handler, ctx sdk.Context, o Msg, codespace sdk.Cod } info.LastSigned = ctx.BlockHeight() - // Check the signer is a validater - val := valset.Validator(ctx, signer) + // check the signer is a validator + val := valset.Validator(ctx, sdk.ValAddress(signer)) if val == nil { return ErrNotValidator(codespace, signer).Result() } diff --git a/examples/democoin/x/pow/types_test.go b/examples/democoin/x/pow/types_test.go index be848d9408..dbe6ad35e9 100644 --- a/examples/democoin/x/pow/types_test.go +++ b/examples/democoin/x/pow/types_test.go @@ -55,14 +55,14 @@ func TestMsgMineString(t *testing.T) { addr := sdk.AccAddress([]byte("sender")) msg := MsgMine{addr, 0, 0, 0, []byte("abc")} res := msg.String() - require.Equal(t, res, "MsgMine{Sender: cosmosaccaddr1wdjkuer9wg4wml9c, Difficulty: 0, Count: 0, Nonce: 0, Proof: abc}") + require.Equal(t, res, "MsgMine{Sender: cosmos1wdjkuer9wgh76ts6, Difficulty: 0, Count: 0, Nonce: 0, Proof: abc}") } func TestMsgMineGetSignBytes(t *testing.T) { addr := sdk.AccAddress([]byte("sender")) msg := MsgMine{addr, 1, 1, 1, []byte("abc")} res := msg.GetSignBytes() - require.Equal(t, string(res), `{"count":1,"difficulty":1,"nonce":1,"proof":"YWJj","sender":"cosmosaccaddr1wdjkuer9wg4wml9c"}`) + require.Equal(t, string(res), `{"count":1,"difficulty":1,"nonce":1,"proof":"YWJj","sender":"cosmos1wdjkuer9wgh76ts6"}`) } func TestMsgMineGetSigners(t *testing.T) { diff --git a/server/tm_cmds.go b/server/tm_cmds.go index d84022183a..b6daf07753 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -45,10 +45,12 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { if viper.GetBool(client.FlagJson) { return printlnJSON(valPubKey) } - pubkey, err := sdk.Bech32ifyValPub(valPubKey) + + pubkey, err := sdk.Bech32ifyConsPub(valPubKey) if err != nil { return err } + fmt.Println(pubkey) return nil }, diff --git a/types/account.go b/types/account.go index 00076b5299..1df600c36e 100644 --- a/types/account.go +++ b/types/account.go @@ -13,251 +13,422 @@ import ( "github.com/tendermint/tendermint/libs/bech32" ) -// Bech32 prefixes const ( - // expected address length + // AddrLen defines a valid address length AddrLen = 20 - // Bech32 prefixes - Bech32PrefixAccAddr = "cosmosaccaddr" - Bech32PrefixAccPub = "cosmosaccpub" - Bech32PrefixValAddr = "cosmosvaladdr" - Bech32PrefixValPub = "cosmosvalpub" + // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address + Bech32PrefixAccAddr = "cosmos" + // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key + Bech32PrefixAccPub = "cosmospub" + // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address + Bech32PrefixValAddr = "cosmosval" + // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key + Bech32PrefixValPub = "cosmosvalpub" + // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address + Bech32PrefixConsAddr = "cosmoscons" + // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key + Bech32PrefixConsPub = "cosmosconspub" ) -//__________________________________________________________ +// ---------------------------------------------------------------------------- +// account +// ---------------------------------------------------------------------------- -// AccAddress a wrapper around bytes meant to represent an account address -// When marshaled to a string or json, it uses bech32 +// AccAddress a wrapper around bytes meant to represent an account address. +// When marshaled to a string or JSON, it uses Bech32. type AccAddress []byte -// create an AccAddress from a hex string +// AccAddressFromHex creates an AccAddress from a hex string. func AccAddressFromHex(address string) (addr AccAddress, err error) { if len(address) == 0 { - return addr, errors.New("decoding bech32 address failed: must provide an address") + return addr, errors.New("decoding Bech32 address failed: must provide an address") } + bz, err := hex.DecodeString(address) if err != nil { return nil, err } + return AccAddress(bz), nil } -// create an AccAddress from a bech32 string +// AccAddressFromBech32 creates an AccAddress from a Bech32 string. func AccAddressFromBech32(address string) (addr AccAddress, err error) { bz, err := GetFromBech32(address, Bech32PrefixAccAddr) if err != nil { return nil, err } + return AccAddress(bz), nil } -// Marshal needed for protobuf compatibility -func (bz AccAddress) Marshal() ([]byte, error) { - return bz, nil +// Returns boolean for whether two AccAddresses are Equal +func (aa AccAddress) Equals(aa2 AccAddress) bool { + if aa.Empty() && aa2.Empty() { + return true + } + + return bytes.Compare(aa.Bytes(), aa2.Bytes()) == 0 } -// Unmarshal needed for protobuf compatibility -func (bz *AccAddress) Unmarshal(data []byte) error { - *bz = data +// Returns boolean for whether an AccAddress is empty +func (aa AccAddress) Empty() bool { + if aa == nil { + return true + } + + aa2 := AccAddress{} + return bytes.Compare(aa.Bytes(), aa2.Bytes()) == 0 +} + +// Marshal returns the raw address bytes. It is needed for protobuf +// compatibility. +func (aa AccAddress) Marshal() ([]byte, error) { + return aa, nil +} + +// Unmarshal sets the address to the given data. It is needed for protobuf +// compatibility. +func (aa *AccAddress) Unmarshal(data []byte) error { + *aa = data return nil } -// Marshals to JSON using Bech32 -func (bz AccAddress) MarshalJSON() ([]byte, error) { - return json.Marshal(bz.String()) +// MarshalJSON marshals to JSON using Bech32. +func (aa AccAddress) MarshalJSON() ([]byte, error) { + return json.Marshal(aa.String()) } -// Unmarshals from JSON assuming Bech32 encoding -func (bz *AccAddress) UnmarshalJSON(data []byte) error { +// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding. +func (aa *AccAddress) UnmarshalJSON(data []byte) error { var s string err := json.Unmarshal(data, &s) if err != nil { return nil } - bz2, err := AccAddressFromBech32(s) + aa2, err := AccAddressFromBech32(s) if err != nil { return err } - *bz = bz2 + + *aa = aa2 return nil } -// Allow it to fulfill various interfaces in light-client, etc... -func (bz AccAddress) Bytes() []byte { - return bz +// Bytes returns the raw address bytes. +func (aa AccAddress) Bytes() []byte { + return aa } -func (bz AccAddress) String() string { - bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixAccAddr, bz.Bytes()) +// String implements the Stringer interface. +func (aa AccAddress) String() string { + bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixAccAddr, aa.Bytes()) if err != nil { panic(err) } + return bech32Addr } -// For Printf / Sprintf, returns bech32 when using %s -func (bz AccAddress) Format(s fmt.State, verb rune) { +// Format implements the fmt.Formatter interface. +func (aa AccAddress) Format(s fmt.State, verb rune) { switch verb { case 's': - s.Write([]byte(fmt.Sprintf("%s", bz.String()))) + s.Write([]byte(fmt.Sprintf("%s", aa.String()))) case 'p': - s.Write([]byte(fmt.Sprintf("%p", bz))) + s.Write([]byte(fmt.Sprintf("%p", aa))) default: - s.Write([]byte(fmt.Sprintf("%X", []byte(bz)))) + s.Write([]byte(fmt.Sprintf("%X", []byte(aa)))) } } -// Returns boolean for whether two AccAddresses are Equal -func (bz AccAddress) Equals(bz2 AccAddress) bool { - if bz.Empty() && bz2.Empty() { - return true - } - return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 -} +// ---------------------------------------------------------------------------- +// validator owner +// ---------------------------------------------------------------------------- -// Returns boolean for whether an AccAddress is empty -func (bz AccAddress) Empty() bool { - if bz == nil { - return true - } - bz2 := AccAddress{} - return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 -} - -//__________________________________________________________ - -// AccAddress a wrapper around bytes meant to represent a validator address -// (from over ABCI). When marshaled to a string or json, it uses bech32 +// ValAddress defines a wrapper around bytes meant to present a validator's +// operator. When marshaled to a string or JSON, it uses Bech32. type ValAddress []byte -// create a ValAddress from a hex string +// ValAddressFromHex creates a ValAddress from a hex string. func ValAddressFromHex(address string) (addr ValAddress, err error) { if len(address) == 0 { - return addr, errors.New("decoding bech32 address failed: must provide an address") + return addr, errors.New("decoding Bech32 address failed: must provide an address") } + bz, err := hex.DecodeString(address) if err != nil { return nil, err } + return ValAddress(bz), nil } -// create a ValAddress from a bech32 string +// ValAddressFromBech32 creates a ValAddress from a Bech32 string. func ValAddressFromBech32(address string) (addr ValAddress, err error) { bz, err := GetFromBech32(address, Bech32PrefixValAddr) if err != nil { return nil, err } + return ValAddress(bz), nil } -// Marshal needed for protobuf compatibility -func (bz ValAddress) Marshal() ([]byte, error) { - return bz, nil +// Returns boolean for whether two ValAddresses are Equal +func (va ValAddress) Equals(va2 ValAddress) bool { + if va.Empty() && va2.Empty() { + return true + } + + return bytes.Compare(va.Bytes(), va2.Bytes()) == 0 } -// Unmarshal needed for protobuf compatibility -func (bz *ValAddress) Unmarshal(data []byte) error { - *bz = data +// Returns boolean for whether an AccAddress is empty +func (va ValAddress) Empty() bool { + if va == nil { + return true + } + + va2 := ValAddress{} + return bytes.Compare(va.Bytes(), va2.Bytes()) == 0 +} + +// Marshal returns the raw address bytes. It is needed for protobuf +// compatibility. +func (va ValAddress) Marshal() ([]byte, error) { + return va, nil +} + +// Unmarshal sets the address to the given data. It is needed for protobuf +// compatibility. +func (va *ValAddress) Unmarshal(data []byte) error { + *va = data return nil } -// Marshals to JSON using Bech32 -func (bz ValAddress) MarshalJSON() ([]byte, error) { - return json.Marshal(bz.String()) +// MarshalJSON marshals to JSON using Bech32. +func (va ValAddress) MarshalJSON() ([]byte, error) { + return json.Marshal(va.String()) } -// Unmarshals from JSON assuming Bech32 encoding -func (bz *ValAddress) UnmarshalJSON(data []byte) error { +// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding. +func (va *ValAddress) UnmarshalJSON(data []byte) error { var s string + err := json.Unmarshal(data, &s) if err != nil { return nil } - bz2, err := ValAddressFromBech32(s) + va2, err := ValAddressFromBech32(s) if err != nil { return err } - *bz = bz2 + + *va = va2 return nil } -// Allow it to fulfill various interfaces in light-client, etc... -func (bz ValAddress) Bytes() []byte { - return bz +// Bytes returns the raw address bytes. +func (va ValAddress) Bytes() []byte { + return va } -func (bz ValAddress) String() string { - bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixValAddr, bz.Bytes()) +// String implements the Stringer interface. +func (va ValAddress) String() string { + bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixValAddr, va.Bytes()) if err != nil { panic(err) } + return bech32Addr } -// For Printf / Sprintf, returns bech32 when using %s -func (bz ValAddress) Format(s fmt.State, verb rune) { +// Format implements the fmt.Formatter interface. +func (va ValAddress) Format(s fmt.State, verb rune) { switch verb { case 's': - s.Write([]byte(fmt.Sprintf("%s", bz.String()))) + s.Write([]byte(fmt.Sprintf("%s", va.String()))) case 'p': - s.Write([]byte(fmt.Sprintf("%p", bz))) + s.Write([]byte(fmt.Sprintf("%p", va))) default: - s.Write([]byte(fmt.Sprintf("%X", []byte(bz)))) + s.Write([]byte(fmt.Sprintf("%X", []byte(va)))) } } -// Returns boolean for whether two ValAddresses are Equal -func (bz ValAddress) Equals(bz2 ValAddress) bool { - if bz.Empty() && bz2.Empty() { +// ---------------------------------------------------------------------------- +// consensus node +// ---------------------------------------------------------------------------- + +// ConsAddress defines a wrapper around bytes meant to present a consensus node. +// When marshaled to a string or JSON, it uses Bech32. +type ConsAddress []byte + +// ConsAddressFromHex creates a ConsAddress from a hex string. +func ConsAddressFromHex(address string) (addr ConsAddress, err error) { + if len(address) == 0 { + return addr, errors.New("decoding Bech32 address failed: must provide an address") + } + + bz, err := hex.DecodeString(address) + if err != nil { + return nil, err + } + + return ConsAddress(bz), nil +} + +// ConsAddressFromBech32 creates a ConsAddress from a Bech32 string. +func ConsAddressFromBech32(address string) (addr ConsAddress, err error) { + bz, err := GetFromBech32(address, Bech32PrefixConsAddr) + if err != nil { + return nil, err + } + + return ConsAddress(bz), nil +} + +// Returns boolean for whether two ConsAddress are Equal +func (ca ConsAddress) Equals(ca2 ConsAddress) bool { + if ca.Empty() && ca2.Empty() { return true } - return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 + + return bytes.Compare(ca.Bytes(), ca2.Bytes()) == 0 } -// Returns boolean for whether an AccAddress is empty -func (bz ValAddress) Empty() bool { - if bz == nil { +// Returns boolean for whether an ConsAddress is empty +func (ca ConsAddress) Empty() bool { + if ca == nil { return true } - bz2 := ValAddress{} - return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 + + ca2 := ConsAddress{} + return bytes.Compare(ca.Bytes(), ca2.Bytes()) == 0 } -// Bech32ifyAccPub takes AccountPubKey and returns the bech32 encoded string +// Marshal returns the raw address bytes. It is needed for protobuf +// compatibility. +func (ca ConsAddress) Marshal() ([]byte, error) { + return ca, nil +} + +// Unmarshal sets the address to the given data. It is needed for protobuf +// compatibility. +func (ca *ConsAddress) Unmarshal(data []byte) error { + *ca = data + return nil +} + +// MarshalJSON marshals to JSON using Bech32. +func (ca ConsAddress) MarshalJSON() ([]byte, error) { + return json.Marshal(ca.String()) +} + +// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding. +func (ca *ConsAddress) UnmarshalJSON(data []byte) error { + var s string + + err := json.Unmarshal(data, &s) + if err != nil { + return nil + } + + ca2, err := ConsAddressFromBech32(s) + if err != nil { + return err + } + + *ca = ca2 + return nil +} + +// Bytes returns the raw address bytes. +func (ca ConsAddress) Bytes() []byte { + return ca +} + +// String implements the Stringer interface. +func (ca ConsAddress) String() string { + bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixConsAddr, ca.Bytes()) + if err != nil { + panic(err) + } + + return bech32Addr +} + +// Format implements the fmt.Formatter interface. +func (ca ConsAddress) Format(s fmt.State, verb rune) { + switch verb { + case 's': + s.Write([]byte(fmt.Sprintf("%s", ca.String()))) + case 'p': + s.Write([]byte(fmt.Sprintf("%p", ca))) + default: + s.Write([]byte(fmt.Sprintf("%X", []byte(ca)))) + } +} + +// ---------------------------------------------------------------------------- +// auxiliary +// ---------------------------------------------------------------------------- + +// Bech32ifyAccPub returns a Bech32 encoded string containing the +// Bech32PrefixAccPub prefix for a given account PubKey. func Bech32ifyAccPub(pub crypto.PubKey) (string, error) { return bech32.ConvertAndEncode(Bech32PrefixAccPub, pub.Bytes()) } -// MustBech32ifyAccPub panics on bech32-encoding failure +// MustBech32ifyAccPub returns the result of Bech32ifyAccPub panicing on failure. func MustBech32ifyAccPub(pub crypto.PubKey) string { enc, err := Bech32ifyAccPub(pub) if err != nil { panic(err) } + return enc } -// Bech32ifyValPub returns the bech32 encoded string for a validator pubkey +// Bech32ifyValPub returns a Bech32 encoded string containing the +// Bech32PrefixValPub prefix for a given validator operator's PubKey. func Bech32ifyValPub(pub crypto.PubKey) (string, error) { return bech32.ConvertAndEncode(Bech32PrefixValPub, pub.Bytes()) } -// MustBech32ifyValPub panics on bech32-encoding failure +// MustBech32ifyValPub returns the result of Bech32ifyValPub panicing on failure. func MustBech32ifyValPub(pub crypto.PubKey) string { enc, err := Bech32ifyValPub(pub) if err != nil { panic(err) } + return enc } -// create a Pubkey from a string -func GetAccPubKeyBech32(address string) (pk crypto.PubKey, err error) { - bz, err := GetFromBech32(address, Bech32PrefixAccPub) +// Bech32ifyConsPub returns a Bech32 encoded string containing the +// Bech32PrefixConsPub prefixfor a given consensus node's PubKey. +func Bech32ifyConsPub(pub crypto.PubKey) (string, error) { + return bech32.ConvertAndEncode(Bech32PrefixConsPub, pub.Bytes()) +} + +// MustBech32ifyConsPub returns the result of Bech32ifyConsPub panicing on +// failure. +func MustBech32ifyConsPub(pub crypto.PubKey) string { + enc, err := Bech32ifyConsPub(pub) + if err != nil { + panic(err) + } + + return enc +} + +// GetAccPubKeyBech32 creates a PubKey for an account with a given public key +// string using the Bech32 Bech32PrefixAccPub prefix. +func GetAccPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) { + bz, err := GetFromBech32(pubkey, Bech32PrefixAccPub) if err != nil { return nil, err } @@ -270,16 +441,19 @@ func GetAccPubKeyBech32(address string) (pk crypto.PubKey, err error) { return pk, nil } -// create an Pubkey from a string, panics on error -func MustGetAccPubKeyBech32(address string) (pk crypto.PubKey) { - pk, err := GetAccPubKeyBech32(address) +// MustGetAccPubKeyBech32 returns the result of GetAccPubKeyBech32 panicing on +// failure. +func MustGetAccPubKeyBech32(pubkey string) (pk crypto.PubKey) { + pk, err := GetAccPubKeyBech32(pubkey) if err != nil { panic(err) } + return pk } -// decode a validator public key into a PubKey +// GetValPubKeyBech32 creates a PubKey for a validator's operator with a given +// public key string using the Bech32 Bech32PrefixValPub prefix. func GetValPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) { bz, err := GetFromBech32(pubkey, Bech32PrefixValPub) if err != nil { @@ -294,27 +468,57 @@ func GetValPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) { return pk, nil } -// create an Pubkey from a string, panics on error -func MustGetValPubKeyBech32(address string) (pk crypto.PubKey) { - pk, err := GetValPubKeyBech32(address) +// MustGetValPubKeyBech32 returns the result of GetValPubKeyBech32 panicing on +// failure. +func MustGetValPubKeyBech32(pubkey string) (pk crypto.PubKey) { + pk, err := GetValPubKeyBech32(pubkey) if err != nil { panic(err) } + return pk } -// decode a bytestring from a bech32-encoded string +// GetConsPubKeyBech32 creates a PubKey for a consensus node with a given public +// key string using the Bech32 Bech32PrefixConsPub prefix. +func GetConsPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) { + bz, err := GetFromBech32(pubkey, Bech32PrefixConsPub) + if err != nil { + return nil, err + } + + pk, err = cryptoAmino.PubKeyFromBytes(bz) + if err != nil { + return nil, err + } + + return pk, nil +} + +// MustGetConsPubKeyBech32 returns the result of GetConsPubKeyBech32 panicing on +// failure. +func MustGetConsPubKeyBech32(pubkey string) (pk crypto.PubKey) { + pk, err := GetConsPubKeyBech32(pubkey) + if err != nil { + panic(err) + } + + return pk +} + +// GetFromBech32 decodes a bytestring from a Bech32 encoded string. func GetFromBech32(bech32str, prefix string) ([]byte, error) { if len(bech32str) == 0 { - return nil, errors.New("decoding bech32 address failed: must provide an address") + return nil, errors.New("decoding Bech32 address failed: must provide an address") } + hrp, bz, err := bech32.DecodeAndConvert(bech32str) if err != nil { return nil, err } if hrp != prefix { - return nil, fmt.Errorf("invalid bech32 prefix. Expected %s, Got %s", prefix, hrp) + return nil, fmt.Errorf("invalid Bech32 prefix; expected %s, got %s", prefix, hrp) } return bz, nil diff --git a/types/account_test.go b/types/account_test.go index aa222ee7e9..e2ec36876c 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/types" ) -var invalidstrs = []string{ +var invalidStrs = []string{ "", "hello, world!", "0xAA", @@ -21,6 +21,8 @@ var invalidstrs = []string{ types.Bech32PrefixAccPub + "1234", types.Bech32PrefixValAddr + "5678", types.Bech32PrefixValPub + "BBAB", + types.Bech32PrefixConsAddr + "FF04", + types.Bech32PrefixConsPub + "6789", } func testMarshal(t *testing.T, original interface{}, res interface{}, marshal func() ([]byte, error), unmarshal func([]byte) error) { @@ -37,27 +39,38 @@ func TestRandBech32PubkeyConsistency(t *testing.T) { for i := 0; i < 1000; i++ { rand.Read(pub[:]) - mustbech32accpub := types.MustBech32ifyAccPub(pub) - bech32accpub, err := types.Bech32ifyAccPub(pub) + mustBech32AccPub := types.MustBech32ifyAccPub(pub) + bech32AccPub, err := types.Bech32ifyAccPub(pub) require.Nil(t, err) - require.Equal(t, bech32accpub, mustbech32accpub) + require.Equal(t, bech32AccPub, mustBech32AccPub) - mustbech32valpub := types.MustBech32ifyValPub(pub) - bech32valpub, err := types.Bech32ifyValPub(pub) + mustBech32ValPub := types.MustBech32ifyValPub(pub) + bech32ValPub, err := types.Bech32ifyValPub(pub) require.Nil(t, err) - require.Equal(t, bech32valpub, mustbech32valpub) + require.Equal(t, bech32ValPub, mustBech32ValPub) - mustaccpub := types.MustGetAccPubKeyBech32(bech32accpub) - accpub, err := types.GetAccPubKeyBech32(bech32accpub) + mustBech32ConsPub := types.MustBech32ifyConsPub(pub) + bech32ConsPub, err := types.Bech32ifyConsPub(pub) require.Nil(t, err) - require.Equal(t, accpub, mustaccpub) + require.Equal(t, bech32ConsPub, mustBech32ConsPub) - mustvalpub := types.MustGetValPubKeyBech32(bech32valpub) - valpub, err := types.GetValPubKeyBech32(bech32valpub) + mustAccPub := types.MustGetAccPubKeyBech32(bech32AccPub) + accPub, err := types.GetAccPubKeyBech32(bech32AccPub) require.Nil(t, err) - require.Equal(t, valpub, mustvalpub) + require.Equal(t, accPub, mustAccPub) - require.Equal(t, valpub, accpub) + mustValPub := types.MustGetValPubKeyBech32(bech32ValPub) + valPub, err := types.GetValPubKeyBech32(bech32ValPub) + require.Nil(t, err) + require.Equal(t, valPub, mustValPub) + + mustConsPub := types.MustGetConsPubKeyBech32(bech32ConsPub) + consPub, err := types.GetConsPubKeyBech32(bech32ConsPub) + require.Nil(t, err) + require.Equal(t, consPub, mustConsPub) + + require.Equal(t, valPub, accPub) + require.Equal(t, valPub, consPub) } } @@ -84,7 +97,7 @@ func TestRandBech32AccAddrConsistency(t *testing.T) { require.Equal(t, acc, res) } - for _, str := range invalidstrs { + for _, str := range invalidStrs { _, err := types.AccAddressFromHex(str) require.NotNil(t, err) @@ -119,7 +132,7 @@ func TestValAddr(t *testing.T) { require.Equal(t, acc, res) } - for _, str := range invalidstrs { + for _, str := range invalidStrs { _, err := types.ValAddressFromHex(str) require.NotNil(t, err) @@ -130,3 +143,38 @@ func TestValAddr(t *testing.T) { require.NotNil(t, err) } } + +func TestConsAddress(t *testing.T) { + var pub ed25519.PubKeyEd25519 + + for i := 0; i < 20; i++ { + rand.Read(pub[:]) + + acc := types.ConsAddress(pub.Address()) + res := types.ConsAddress{} + + testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON) + testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal) + + str := acc.String() + res, err := types.ConsAddressFromBech32(str) + require.Nil(t, err) + require.Equal(t, acc, res) + + str = hex.EncodeToString(acc) + res, err = types.ConsAddressFromHex(str) + require.Nil(t, err) + require.Equal(t, acc, res) + } + + for _, str := range invalidStrs { + _, err := types.ConsAddressFromHex(str) + require.NotNil(t, err) + + _, err = types.ConsAddressFromBech32(str) + require.NotNil(t, err) + + err = (*types.ConsAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\"")) + require.NotNil(t, err) + } +} diff --git a/types/stake.go b/types/stake.go index d872277256..f411251775 100644 --- a/types/stake.go +++ b/types/stake.go @@ -40,7 +40,7 @@ type Validator interface { GetJailed() bool // whether the validator is jailed GetMoniker() string // moniker of the validator GetStatus() BondStatus // status of the validator - GetOperator() AccAddress // owner AccAddress to receive/return validators coins + GetOperator() ValAddress // owner address to receive/return validators coins GetPubKey() crypto.PubKey // validation pubkey GetPower() Dec // validation power GetTokens() Dec // validation tokens @@ -67,7 +67,7 @@ type ValidatorSet interface { IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) - Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress + Validator(Context, ValAddress) Validator // get a particular validator by operator ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey TotalPower(Context) Dec // total power of the validator set @@ -82,7 +82,7 @@ type ValidatorSet interface { // delegation bond for a delegated proof of stake system type Delegation interface { GetDelegator() AccAddress // delegator AccAddress for the bond - GetValidator() AccAddress // validator owner AccAddress for the bond + GetValidator() ValAddress // validator operator address GetBondShares() Dec // amount of validator's shares } diff --git a/x/bank/msgs_test.go b/x/bank/msgs_test.go index ac16b1d0b1..e082bdac42 100644 --- a/x/bank/msgs_test.go +++ b/x/bank/msgs_test.go @@ -187,7 +187,7 @@ func TestMsgSendGetSignBytes(t *testing.T) { } res := msg.GetSignBytes() - expected := `{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}` + expected := `{"inputs":[{"address":"cosmos1d9h8qat57ljhcm","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmos1da6hgur4wsmpnjyg","coins":[{"amount":"10","denom":"atom"}]}]}` require.Equal(t, expected, string(res)) } @@ -257,7 +257,7 @@ func TestMsgIssueGetSignBytes(t *testing.T) { } res := msg.GetSignBytes() - expected := `{"banker":"cosmosaccaddr1d9h8qat5e4ehc5","outputs":[{"address":"cosmosaccaddr1d3hkzm3dveex7mfdvfsku6cwsauqd","coins":[{"amount":"10","denom":"atom"}]}]}` + expected := `{"banker":"cosmos1d9h8qat57ljhcm","outputs":[{"address":"cosmos1d3hkzm3dveex7mfdvfsku6cjngpcj","coins":[{"amount":"10","denom":"atom"}]}]}` require.Equal(t, expected, string(res)) } diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 9dd241aabd..710ecb1dba 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -178,12 +178,17 @@ func TestSlashing(t *testing.T) { govHandler := NewHandler(keeper) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{25, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7}) initTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx) - val0Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[0]).GetPower().Quo(initTotalPower) - val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(initTotalPower) - val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[2]).GetPower().Quo(initTotalPower) + val0Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(initTotalPower) + val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(initTotalPower) + val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[2])).GetPower().Quo(initTotalPower) newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 15)}) @@ -209,9 +214,9 @@ func TestSlashing(t *testing.T) { require.False(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult())) endTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx) - val0End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[0]).GetPower().Quo(endTotalPower) - val1End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(endTotalPower) - val2End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[2]).GetPower().Quo(endTotalPower) + val0End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(endTotalPower) + val1End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(endTotalPower) + val2End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[2])).GetPower().Quo(endTotalPower) require.True(t, val0End.GTE(val0Initial)) require.True(t, val1End.LT(val1Initial)) diff --git a/x/gov/handler.go b/x/gov/handler.go index 4fa3887296..6424bb0a10 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -114,8 +114,8 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { resTags.AppendTag(tags.Action, tags.ActionProposalDropped) resTags.AppendTag(tags.ProposalID, proposalIDBytes) - logger.Info("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted", - inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit()) + logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted", + inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit())) } // Check if earliest Active Proposal ended voting period yet @@ -143,8 +143,8 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { activeProposal.SetTallyResult(tallyResults) keeper.SetProposal(ctx, activeProposal) - logger.Info("Proposal %d - \"%s\" - tallied, passed: %v", - activeProposal.GetProposalID(), activeProposal.GetTitle(), passes) + logger.Info(fmt.Sprintf("Proposal %d - \"%s\" - tallied, passed: %v", + activeProposal.GetProposalID(), activeProposal.GetTitle(), passes)) for _, valAddr := range nonVotingVals { val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) diff --git a/x/gov/tally.go b/x/gov/tally.go index b6c9ee2a14..a756eaf926 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -6,14 +6,14 @@ import ( // validatorGovInfo used for tallying type validatorGovInfo struct { - Address sdk.AccAddress // sdk.AccAddress of the validator owner + Address sdk.ValAddress // address of the validator operator Power sdk.Dec // Power of a Validator DelegatorShares sdk.Dec // Total outstanding delegator shares Minus sdk.Dec // Minus of validator, used to compute validator's voting power Vote VoteOption // Vote of the validator } -func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) { +func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.ValAddress) { results := make(map[VoteOption]sdk.Dec) results[OptionYes] = sdk.ZeroDec() results[OptionAbstain] = sdk.ZeroDec() @@ -43,15 +43,18 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall // if validator, just record it in the map // if delegator tally voting power - if val, ok := currValidators[vote.Voter.String()]; ok { + valAddrStr := sdk.ValAddress(vote.Voter).String() + if val, ok := currValidators[valAddrStr]; ok { val.Vote = vote.Option - currValidators[vote.Voter.String()] = val + currValidators[valAddrStr] = val } else { keeper.ds.IterateDelegations(ctx, vote.Voter, func(index int64, delegation sdk.Delegation) (stop bool) { - if val, ok := currValidators[delegation.GetValidator().String()]; ok { + valAddrStr := delegation.GetValidator().String() + + if val, ok := currValidators[valAddrStr]; ok { val.Minus = val.Minus.Add(delegation.GetBondShares()) - currValidators[delegation.GetValidator().String()] = val + currValidators[valAddrStr] = val delegatorShare := delegation.GetBondShares().Quo(val.DelegatorShares) votingPower := val.Power.Mul(delegatorShare) @@ -59,6 +62,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall results[vote.Option] = results[vote.Option].Add(votingPower) totalVotingPower = totalVotingPower.Add(votingPower) } + return false }) } @@ -66,13 +70,15 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall keeper.deleteVote(ctx, vote.ProposalID, vote.Voter) } - // Iterate over the validators again to tally their voting power and see who didn't vote - nonVoting = []sdk.AccAddress{} + // iterate over the validators again to tally their voting power and see + // who didn't vote + nonVoting = []sdk.ValAddress{} for _, val := range currValidators { if val.Vote == OptionEmpty { nonVoting = append(nonVoting, val.Address) continue } + sharesAfterMinus := val.DelegatorShares.Sub(val.Minus) percentAfterMinus := sharesAfterMinus.Quo(val.DelegatorShares) votingPower := val.Power.Mul(percentAfterMinus) @@ -104,7 +110,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall } // If more than 1/2 of non-abstaining voters vote No, proposal fails - SortAddresses(nonVoting) + SortValAddresses(nonVoting) return false, tallyResults, nonVoting } diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 157f594401..24740731f0 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -17,7 +17,7 @@ var ( pubkeys = []crypto.PubKey{ed25519.GenPrivKey().PubKey(), ed25519.GenPrivKey().PubKey(), ed25519.GenPrivKey().PubKey()} ) -func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, addrs []sdk.AccAddress, coinAmt []int64) { +func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, addrs []sdk.ValAddress, coinAmt []int64) { require.True(t, len(addrs) <= len(pubkeys), "Not enough pubkeys specified at top of file.") dummyDescription := stake.NewDescription("T", "E", "S", "T") for i := 0; i < len(addrs); i++ { @@ -33,7 +33,12 @@ func TestTallyNoOneVotes(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:2], []int64{5, 5}) + valAddrs := make([]sdk.ValAddress, len(addrs[:2])) + for i, addr := range addrs[:2] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 5}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -52,7 +57,12 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:2], []int64{5, 5}) + valAddrs := make([]sdk.ValAddress, len(addrs[:2])) + for i, addr := range addrs[:2] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 5}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -76,7 +86,12 @@ func TestTallyOnlyValidators51No(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:2], []int64{5, 6}) + valAddrs := make([]sdk.ValAddress, len(addrs[:2])) + for i, addr := range addrs[:2] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -99,7 +114,12 @@ func TestTallyOnlyValidators51Yes(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{6, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{6, 6, 7}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -125,7 +145,12 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{6, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{6, 6, 7}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -151,7 +176,12 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{6, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{6, 6, 7}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -177,7 +207,12 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{6, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{6, 6, 7}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -203,7 +238,12 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{6, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{6, 6, 7}) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() @@ -219,7 +259,7 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) { require.False(t, passes) require.Equal(t, 1, len(nonVoting)) - require.Equal(t, addrs[0], nonVoting[0]) + require.Equal(t, sdk.ValAddress(addrs[0]), nonVoting[0]) require.False(t, tallyResults.Equals(EmptyTallyResult())) } @@ -229,9 +269,14 @@ func TestTallyDelgatorOverride(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{5, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } - delegator1Msg := stake.NewMsgDelegate(addrs[3], addrs[2], sdk.NewInt64Coin("steak", 30)) + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7}) + + delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 30)) stakeHandler(ctx, delegator1Msg) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) @@ -260,9 +305,14 @@ func TestTallyDelgatorInherit(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{5, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } - delegator1Msg := stake.NewMsgDelegate(addrs[3], addrs[2], sdk.NewInt64Coin("steak", 30)) + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7}) + + delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 30)) stakeHandler(ctx, delegator1Msg) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) @@ -290,11 +340,16 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{5, 6, 7}) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } - delegator1Msg := stake.NewMsgDelegate(addrs[3], addrs[2], sdk.NewInt64Coin("steak", 10)) + createValidators(t, stakeHandler, ctx, valAddrs, []int64{5, 6, 7}) + + delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg) - delegator1Msg2 := stake.NewMsgDelegate(addrs[3], addrs[1], sdk.NewInt64Coin("steak", 10)) + delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg2) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) @@ -324,16 +379,26 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { stakeHandler := stake.NewHandler(sk) dummyDescription := stake.NewDescription("T", "E", "S", "T") - val1CreateMsg := stake.NewMsgCreateValidator(addrs[0], ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 25), dummyDescription) + + val1CreateMsg := stake.NewMsgCreateValidator( + sdk.ValAddress(addrs[0]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 25), dummyDescription, + ) stakeHandler(ctx, val1CreateMsg) - val2CreateMsg := stake.NewMsgCreateValidator(addrs[1], ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 6), dummyDescription) + + val2CreateMsg := stake.NewMsgCreateValidator( + sdk.ValAddress(addrs[1]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 6), dummyDescription, + ) stakeHandler(ctx, val2CreateMsg) - val3CreateMsg := stake.NewMsgCreateValidator(addrs[2], ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 7), dummyDescription) + + val3CreateMsg := stake.NewMsgCreateValidator( + sdk.ValAddress(addrs[2]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 7), dummyDescription, + ) stakeHandler(ctx, val3CreateMsg) - delegator1Msg := stake.NewMsgDelegate(addrs[3], addrs[2], sdk.NewInt64Coin("steak", 10)) + delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg) - delegator1Msg2 := stake.NewMsgDelegate(addrs[3], addrs[1], sdk.NewInt64Coin("steak", 10)) + + delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg2) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) @@ -360,13 +425,20 @@ func TestTallyJailedValidator(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - createValidators(t, stakeHandler, ctx, addrs[:3], []int64{25, 6, 7}) - delegator1Msg := stake.NewMsgDelegate(addrs[3], addrs[2], sdk.NewInt64Coin("steak", 10)) + valAddrs := make([]sdk.ValAddress, len(addrs[:3])) + for i, addr := range addrs[:3] { + valAddrs[i] = sdk.ValAddress(addr) + } + + createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7}) + + delegator1Msg := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[2]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg) - delegator1Msg2 := stake.NewMsgDelegate(addrs[3], addrs[1], sdk.NewInt64Coin("steak", 10)) + + delegator1Msg2 := stake.NewMsgDelegate(addrs[3], sdk.ValAddress(addrs[1]), sdk.NewInt64Coin("steak", 10)) stakeHandler(ctx, delegator1Msg2) - val2, found := sk.GetValidator(ctx, addrs[1]) + val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) sk.Jail(ctx, val2.PubKey) diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 5e7977b50c..502cfbbf04 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -77,6 +77,20 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk } } +// TODO: Remove once address interface has been implemented (ref: #2186) +func SortValAddresses(addrs []sdk.ValAddress) { + var byteAddrs [][]byte + for _, addr := range addrs { + byteAddrs = append(byteAddrs, addr.Bytes()) + } + + SortByteArrays(byteAddrs) + + for i, byteAddr := range byteAddrs { + addrs[i] = byteAddr + } +} + // Sorts Addresses func SortAddresses(addrs []sdk.AccAddress) { var byteAddrs [][]byte diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 86d350a84b..f9ec0833fa 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -73,7 +73,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer { func checkValidator(t *testing.T, mapp *mock.App, keeper stake.Keeper, addr sdk.AccAddress, expFound bool) stake.Validator { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) - validator, found := keeper.GetValidator(ctxCheck, addr1) + validator, found := keeper.GetValidator(ctxCheck, sdk.ValAddress(addr1)) require.Equal(t, expFound, found) return validator } @@ -100,17 +100,17 @@ func TestSlashingMsgs(t *testing.T) { mock.SetGenesis(mapp, accs) description := stake.NewDescription("foo_moniker", "", "", "") createValidatorMsg := stake.NewMsgCreateValidator( - addr1, priv1.PubKey(), bondCoin, description, + sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, ) mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1) mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)}) mapp.BeginBlock(abci.RequestBeginBlock{}) validator := checkValidator(t, mapp, stakeKeeper, addr1, true) - require.Equal(t, addr1, validator.Operator) + require.Equal(t, sdk.ValAddress(addr1), validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) - unjailMsg := MsgUnjail{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())} + unjailMsg := MsgUnjail{ValidatorAddr: sdk.ValAddress(validator.PubKey.Address())} // no signing info yet checkValidatorSigningInfo(t, mapp, keeper, sdk.ValAddress(addr1), false) diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index 0901eef970..9f6d834dda 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -20,7 +20,7 @@ func GetCmdQuerySigningInfo(storeName string, cdc *wire.Codec) *cobra.Command { Short: "Query a validator's signing information", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - pk, err := sdk.GetValPubKeyBech32(args[0]) + pk, err := sdk.GetConsPubKeyBech32(args[0]) if err != nil { return err } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index 2fdd65c6c3..4234e52ce8 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -27,12 +27,12 @@ func GetCmdUnjail(cdc *wire.Codec) *cobra.Command { WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - validatorAddr, err := cliCtx.GetFromAddress() + valAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - msg := slashing.NewMsgUnjail(validatorAddr) + msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr)) return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, diff --git a/x/slashing/client/rest/query.go b/x/slashing/client/rest/query.go index 5509ed1a8d..291679375b 100644 --- a/x/slashing/client/rest/query.go +++ b/x/slashing/client/rest/query.go @@ -23,7 +23,7 @@ func signingInfoHandlerFn(cliCtx context.CLIContext, storeName string, cdc *wire return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - pk, err := sdk.GetValPubKeyBech32(vars["validator"]) + pk, err := sdk.GetConsPubKeyBech32(vars["validator"]) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 26412ebc00..c7efdc97e9 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -56,13 +56,13 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI return } - validatorAddr, err := sdk.AccAddressFromBech32(m.ValidatorAddr) + valAddr, err := sdk.ValAddressFromBech32(m.ValidatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), validatorAddr) { + if !bytes.Equal(info.GetPubKey().Address(), valAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own validator address") return } @@ -75,7 +75,7 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI Gas: m.Gas, } - msg := slashing.NewMsgUnjail(validatorAddr) + msg := slashing.NewMsgUnjail(valAddr) if m.Gas == 0 { newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 4408d3c09d..8e3b719f49 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -15,15 +15,15 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { slh := NewHandler(keeper) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - msg := newTestMsgCreateValidator(addr, val, amt) + msg := newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt) got := stake.NewHandler(sk)(ctx, msg) require.True(t, got.IsOK()) stake.EndBlocker(ctx, sk) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) // assert non-jailed validator can't be unjailed - got = slh(ctx, NewMsgUnjail(addr)) + got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) require.False(t, got.IsOK(), "allowed unjail of non-jailed validator") require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotJailed), got.Code) } diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 808c82014e..3bdb043a82 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -26,12 +26,12 @@ func TestHandleDoubleSign(t *testing.T) { ctx, ck, sk, _, keeper := createTestInput(t) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) // handle a signature to set signing info keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) @@ -40,16 +40,22 @@ func TestHandleDoubleSign(t *testing.T) { keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed - require.True(t, sk.Validator(ctx, addr).GetJailed()) + require.True(t, sk.Validator(ctx, sdk.ValAddress(addr)).GetJailed()) // unjail to measure power sk.Unjail(ctx, val) // power should be reduced - require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + require.Equal( + t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), + sk.Validator(ctx, sdk.ValAddress(addr)).GetPower(), + ) ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))}) // double sign past max age keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) - require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) + require.Equal( + t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), + sk.Validator(ctx, sdk.ValAddress(addr)).GetPower(), + ) } // Test a validator through uptime, downtime, revocation, @@ -62,12 +68,12 @@ func TestHandleAbsentValidator(t *testing.T) { addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) slh := NewHandler(keeper) - got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) + got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) require.False(t, found) require.Equal(t, int64(0), info.StartHeight) @@ -117,12 +123,12 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, sdk.Unbonded, validator.GetStatus()) // unrevocation should fail prior to jail expiration - got = slh(ctx, NewMsgUnjail(addr)) + got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) require.False(t, got.IsOK()) // unrevocation should succeed after jail expiration ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.DowntimeUnbondDuration(ctx))}) - got = slh(ctx, NewMsgUnjail(addr)) + got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr))) require.True(t, got.IsOK()) // validator should be rebonded now @@ -172,12 +178,12 @@ func TestHandleNewValidator(t *testing.T) { ctx, ck, sk, _, keeper := createTestInput(t) addr, val, amt := addrs[0], pks[0], int64(100) sh := stake.NewHandler(sk) - got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt))) + got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, sdk.NewInt(amt))) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}}) - require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower()) + require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, sdk.ValAddress(addr)).GetPower()) // 1000 first blocks not a validator ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1) @@ -210,7 +216,7 @@ func TestHandleAlreadyJailed(t *testing.T) { amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) - got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) + got := sh(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) diff --git a/x/slashing/msg.go b/x/slashing/msg.go index e22eca7bdd..7791012185 100644 --- a/x/slashing/msg.go +++ b/x/slashing/msg.go @@ -15,18 +15,20 @@ var _ sdk.Msg = &MsgUnjail{} // MsgUnjail - struct for unjailing jailed validator type MsgUnjail struct { - ValidatorAddr sdk.AccAddress `json:"address"` // address of the validator owner + ValidatorAddr sdk.ValAddress `json:"address"` // address of the validator owner } -func NewMsgUnjail(validatorAddr sdk.AccAddress) MsgUnjail { +func NewMsgUnjail(validatorAddr sdk.ValAddress) MsgUnjail { return MsgUnjail{ ValidatorAddr: validatorAddr, } } //nolint -func (msg MsgUnjail) Type() string { return MsgType } -func (msg MsgUnjail) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.ValidatorAddr} } +func (msg MsgUnjail) Type() string { return MsgType } +func (msg MsgUnjail) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.ValidatorAddr)} +} // get the bytes for the message signer to sign on func (msg MsgUnjail) GetSignBytes() []byte { diff --git a/x/slashing/msg_test.go b/x/slashing/msg_test.go index ef2e673c86..ff8619041e 100644 --- a/x/slashing/msg_test.go +++ b/x/slashing/msg_test.go @@ -10,7 +10,7 @@ import ( func TestMsgUnjailGetSignBytes(t *testing.T) { addr := sdk.AccAddress("abcd") - msg := NewMsgUnjail(addr) + msg := NewMsgUnjail(sdk.ValAddress(addr)) bytes := msg.GetSignBytes() - require.Equal(t, string(bytes), `{"address":"cosmosaccaddr1v93xxeqhyqz5v"}`) + require.Equal(t, string(bytes), `{"address":"cosmosval1v93xxeq7xkcrf"}`) } diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index e4900889e3..dc7f63ba64 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -19,7 +19,7 @@ import ( func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { key := simulation.RandomKey(r, keys) - address := sdk.AccAddress(key.PubKey().Address()) + address := sdk.ValAddress(key.PubKey().Address()) msg := slashing.NewMsgUnjail(address) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 50c501d7e3..1053823786 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -99,10 +99,10 @@ func testAddr(addr string) sdk.AccAddress { return res } -func newTestMsgCreateValidator(address sdk.AccAddress, pubKey crypto.PubKey, amt sdk.Int) stake.MsgCreateValidator { +func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt sdk.Int) stake.MsgCreateValidator { return stake.MsgCreateValidator{ Description: stake.Description{}, - DelegatorAddr: address, + DelegatorAddr: sdk.AccAddress(address), ValidatorAddr: address, PubKey: pubKey, Delegation: sdk.Coin{"steak", amt}, diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 78d2695494..9eb956e671 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -17,12 +17,12 @@ func TestBeginBlocker(t *testing.T) { addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100) // bond the validator - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, pk, amt)) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(sdk.ValAddress(addr), pk, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, sdk.ValAddress(addr)).GetPower())) val := abci.Validator{ Address: pk.Address(), diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 65c64fdef2..587e90b465 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -79,7 +79,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer { //__________________________________________________________________________________________ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper, - addr sdk.AccAddress, expFound bool) Validator { + addr sdk.ValAddress, expFound bool) Validator { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) validator, found := keeper.GetValidator(ctxCheck, addr) @@ -89,8 +89,8 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper, } func checkDelegation( - t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr, - validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Dec, + t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr sdk.AccAddress, + validatorAddr sdk.ValAddress, expFound bool, expShares sdk.Dec, ) { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) @@ -128,55 +128,57 @@ func TestStakeMsgs(t *testing.T) { // create validator description := NewDescription("foo_moniker", "", "", "") createValidatorMsg := NewMsgCreateValidator( - addr1, priv1.PubKey(), bondCoin, description, + sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, ) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1) mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Minus(bondCoin)}) mApp.BeginBlock(abci.RequestBeginBlock{}) - validator := checkValidator(t, mApp, keeper, addr1, true) - require.Equal(t, addr1, validator.Operator) + validator := checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true) + require.Equal(t, sdk.ValAddress(addr1), validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) // addr1 create validator on behalf of addr2 - createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description) + createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf( + addr1, sdk.ValAddress(addr2), priv2.PubKey(), bondCoin, description, + ) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsgOnBehalfOf}, []int64{0, 1}, []int64{1, 0}, true, priv1, priv2) mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Minus(bondCoin).Minus(bondCoin)}) mApp.BeginBlock(abci.RequestBeginBlock{}) - validator = checkValidator(t, mApp, keeper, addr2, true) - require.Equal(t, addr2, validator.Operator) + validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr2), true) + require.Equal(t, sdk.ValAddress(addr2), validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) // check the bond that should have been created as well - checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10)) + checkDelegation(t, mApp, keeper, addr1, sdk.ValAddress(addr1), true, sdk.NewDec(10)) // edit the validator description = NewDescription("bar_moniker", "", "", "") - editValidatorMsg := NewMsgEditValidator(addr1, description) + editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []int64{0}, []int64{2}, true, priv1) - validator = checkValidator(t, mApp, keeper, addr1, true) + validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true) require.Equal(t, description, validator.Description) // delegate mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin}) - delegateMsg := NewMsgDelegate(addr2, addr1, bondCoin) + delegateMsg := NewMsgDelegate(addr2, sdk.ValAddress(addr1), bondCoin) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2) mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) - checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewDec(10)) + checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), true, sdk.NewDec(10)) // begin unbonding - beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewDec(10)) + beginUnbondingMsg := NewMsgBeginUnbonding(addr2, sdk.ValAddress(addr1), sdk.NewDec(10)) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2) // delegation should exist anymore - checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Dec{}) + checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), false, sdk.Dec{}) // balance should be the same because bonding not yet complete mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index d58ea39381..9a017fb590 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -17,11 +17,11 @@ import ( // GetCmdQueryValidator implements the validator query command. func GetCmdQueryValidator(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "validator [owner-addr]", + Use: "validator [operator-addr]", Short: "Query a validator", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - addr, err := sdk.AccAddressFromBech32(args[0]) + addr, err := sdk.ValAddressFromBech32(args[0]) if err != nil { return err } @@ -120,7 +120,7 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { Use: "delegation", Short: "Query a delegation based on address and validator address", RunE: func(cmd *cobra.Command, args []string) error { - valAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidator)) + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) if err != nil { return err } @@ -222,7 +222,7 @@ func GetCmdQueryUnbondingDelegation(storeName string, cdc *wire.Codec) *cobra.Co Use: "unbonding-delegation", Short: "Query an unbonding-delegation record based on delegator and validator address", RunE: func(cmd *cobra.Command, args []string) error { - valAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidator)) + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) if err != nil { return err } @@ -321,12 +321,12 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { Use: "redelegation", Short: "Query a redelegation record based on delegator and a source and destination validator address", RunE: func(cmd *cobra.Command, args []string) error { - valSrcAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) + valSrcAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) if err != nil { return err } - valDstAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) + valDstAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) if err != nil { return err } diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 9f04f2ed2d..defc2b1e23 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -40,7 +40,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { return err } - validatorAddr, err := cliCtx.GetFromAddress() + valAddr, err := cliCtx.GetFromAddress() if err != nil { return err } @@ -50,7 +50,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { return fmt.Errorf("must use --pubkey flag") } - pk, err := sdk.GetValPubKeyBech32(pkStr) + pk, err := sdk.GetConsPubKeyBech32(pkStr) if err != nil { return err } @@ -68,14 +68,14 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command { var msg sdk.Msg if viper.GetString(FlagAddressDelegator) != "" { - delegatorAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator)) + delAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator)) if err != nil { return err } - msg = stake.NewMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, amount, description) + msg = stake.NewMsgCreateValidatorOnBehalfOf(delAddr, sdk.ValAddress(valAddr), pk, amount, description) } else { - msg = stake.NewMsgCreateValidator(validatorAddr, pk, amount, description) + msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description) } // build and sign the transaction, then broadcast to Tendermint @@ -103,7 +103,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - validatorAddr, err := cliCtx.GetFromAddress() + valAddr, err := cliCtx.GetFromAddress() if err != nil { return err } @@ -114,7 +114,8 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command { Website: viper.GetString(FlagWebsite), Details: viper.GetString(FlagDetails), } - msg := stake.NewMsgEditValidator(validatorAddr, description) + + msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -143,17 +144,17 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command { return err } - delegatorAddr, err := cliCtx.GetFromAddress() + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - validatorAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidator)) + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) if err != nil { return err } - msg := stake.NewMsgDelegate(delegatorAddr, validatorAddr, amount) + msg := stake.NewMsgDelegate(delAddr, valAddr, amount) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -195,17 +196,18 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) var err error - delegatorAddr, err := cliCtx.GetFromAddress() + + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - validatorSrcAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) + valSrcAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) if err != nil { return err } - validatorDstAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) + valDstAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) if err != nil { return err } @@ -215,13 +217,13 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { sharesPercentStr := viper.GetString(FlagSharesPercent) sharesAmount, err := getShares( storeName, cdc, sharesAmountStr, sharesPercentStr, - delegatorAddr, validatorSrcAddr, + delAddr, valSrcAddr, ) if err != nil { return err } - msg := stake.NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr, validatorDstAddr, sharesAmount) + msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -238,7 +240,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { // TODO: Make this pass gocyclo linting func getShares( storeName string, cdc *wire.Codec, sharesAmountStr, - sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress, + sharesPercentStr string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, ) (sharesAmount sdk.Dec, err error) { switch { case sharesAmountStr != "" && sharesPercentStr != "": @@ -264,7 +266,7 @@ func getShares( } // make a query to get the existing delegation shares - key := stake.GetDelegationKey(delegatorAddr, validatorAddr) + key := stake.GetDelegationKey(delAddr, valAddr) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) @@ -294,22 +296,22 @@ func GetCmdCompleteRedelegate(cdc *wire.Codec) *cobra.Command { WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - delegatorAddr, err := cliCtx.GetFromAddress() + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - validatorSrcAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) + valSrcAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) if err != nil { return err } - validatorDstAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) + valDstAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorDst)) if err != nil { return err } - msg := stake.NewMsgCompleteRedelegate(delegatorAddr, validatorSrcAddr, validatorDstAddr) + msg := stake.NewMsgCompleteRedelegate(delAddr, valSrcAddr, valDstAddr) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -349,12 +351,12 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - delegatorAddr, err := cliCtx.GetFromAddress() + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - validatorAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidator)) + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) if err != nil { return err } @@ -364,13 +366,13 @@ func GetCmdBeginUnbonding(storeName string, cdc *wire.Codec) *cobra.Command { sharesPercentStr := viper.GetString(FlagSharesPercent) sharesAmount, err := getShares( storeName, cdc, sharesAmountStr, sharesPercentStr, - delegatorAddr, validatorAddr, + delAddr, valAddr, ) if err != nil { return err } - msg := stake.NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sharesAmount) + msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) @@ -395,17 +397,17 @@ func GetCmdCompleteUnbonding(cdc *wire.Codec) *cobra.Command { WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - delegatorAddr, err := cliCtx.GetFromAddress() + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - validatorAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidator)) + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) if err != nil { return err } - msg := stake.NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) + msg := stake.NewMsgCompleteUnbonding(delAddr, valAddr) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index a040c7541c..bf929387dd 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -87,7 +87,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Cod // defines a delegation without type Rat for shares type DelegationWithoutRat struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` Shares string `json:"shares"` Height int64 `json:"height"` } @@ -103,14 +103,14 @@ type DelegationSummary struct { func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var validatorAddr sdk.AccAddress + var valAddr sdk.ValAddress var delegationSummary = DelegationSummary{} // read parameters vars := mux.Vars(r) bech32delegator := vars["delegatorAddr"] - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + delAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) @@ -126,10 +126,10 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler } for _, validator := range validators { - validatorAddr = validator.Operator + valAddr = validator.Operator // Delegations - delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delegatorAddr, validatorAddr) + delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delAddr, valAddr) if err != nil { w.WriteHeader(statusCode) w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error()))) @@ -140,7 +140,7 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler } // Undelegations - unbondingDelegation, statusCode, errMsg, err := getDelegatorUndelegations(cliCtx, cdc, delegatorAddr, validatorAddr) + unbondingDelegation, statusCode, errMsg, err := getDelegatorUndelegations(cliCtx, cdc, delAddr, valAddr) if err != nil { w.WriteHeader(statusCode) w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error()))) @@ -153,7 +153,7 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler // Redelegations // only querying redelegations to a validator as this should give us already all relegations // if we also would put in redelegations from, we would have every redelegation double - redelegations, statusCode, errMsg, err := getDelegatorRedelegations(cliCtx, cdc, delegatorAddr, validatorAddr) + redelegations, statusCode, errMsg, err := getDelegatorRedelegations(cliCtx, cdc, delAddr, valAddr) if err != nil { w.WriteHeader(statusCode) w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error()))) @@ -259,22 +259,21 @@ func unbondingDelegationsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) h bech32delegator := vars["delegatorAddr"] bech32validator := vars["validatorAddr"] - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + delAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } - validatorAddr, err := sdk.AccAddressFromBech32(bech32validator) + valAddr, err := sdk.ValAddressFromBech32(bech32validator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } - validatorAddrAcc := sdk.AccAddress(validatorAddr) - key := stake.GetUBDKey(delegatorAddr, validatorAddrAcc) + key := stake.GetUBDKey(delAddr, valAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { @@ -318,22 +317,21 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle bech32delegator := vars["delegatorAddr"] bech32validator := vars["validatorAddr"] - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + delAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } - validatorAddr, err := sdk.AccAddressFromBech32(bech32validator) + valAddr, err := sdk.ValAddressFromBech32(bech32validator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } - validatorAddrAcc := sdk.AccAddress(validatorAddr) - key := stake.GetDelegationKey(delegatorAddr, validatorAddrAcc) + key := stake.GetDelegationKey(delAddr, valAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { @@ -377,7 +375,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var validatorAccAddr sdk.AccAddress + var valAddr sdk.ValAddress var bondedValidators []types.BechValidator // read parameters @@ -412,9 +410,9 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) ht for _, validator := range validators { // get all transactions from the delegator to val and append - validatorAccAddr = validator.Operator + valAddr = validator.Operator - validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, validatorAccAddr) + validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, valAddr) if errRes != nil { w.WriteHeader(statusCode) w.Write([]byte(fmt.Sprintf("%s%s", errMsg, errRes.Error()))) @@ -444,8 +442,8 @@ func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) htt bech32delegator := vars["delegatorAddr"] bech32validator := vars["validatorAddr"] - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - validatorAccAddr, err := sdk.AccAddressFromBech32(bech32validator) + delAddr, err := sdk.AccAddressFromBech32(bech32delegator) + valAddr, err := sdk.ValAddressFromBech32(bech32validator) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("Error: %s", err.Error()))) @@ -454,7 +452,7 @@ func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) htt // Check if there if the delegator is bonded or redelegated to the validator - validator, statusCode, errMsg, err := getDelegatorValidator(cliCtx, cdc, delegatorAddr, validatorAccAddr) + validator, statusCode, errMsg, err := getDelegatorValidator(cliCtx, cdc, delAddr, valAddr) if err != nil { w.WriteHeader(statusCode) w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error()))) @@ -516,14 +514,15 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler // read parameters vars := mux.Vars(r) bech32validatorAddr := vars["addr"] - valAddress, err := sdk.AccAddressFromBech32(bech32validatorAddr) + + valAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("error: %s", err.Error()))) return } - key := stake.GetValidatorKey(valAddress) + key := stake.GetValidatorKey(valAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { @@ -538,7 +537,7 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler return } - validator, err := types.UnmarshalValidator(cdc, valAddress, res) + validator, err := types.UnmarshalValidator(cdc, valAddr, res) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index 3d7d419a3a..24a8c38752 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -104,26 +104,26 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex i := 0 for _, msg := range m.Delegations { - delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) + delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } - validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) + valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { + if !bytes.Equal(info.GetPubKey().Address(), delAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } messages[i] = stake.MsgDelegate{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, Delegation: msg.Delegation, } @@ -131,23 +131,23 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex } for _, msg := range m.BeginRedelegates { - delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) + delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { + if !bytes.Equal(info.GetPubKey().Address(), delAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } - validatorSrcAddr, err := sdk.AccAddressFromBech32(msg.ValidatorSrcAddr) + valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - validatorDstAddr, err := sdk.AccAddressFromBech32(msg.ValidatorDstAddr) + valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return @@ -160,9 +160,9 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex } messages[i] = stake.MsgBeginRedelegate{ - DelegatorAddr: delegatorAddr, - ValidatorSrcAddr: validatorSrcAddr, - ValidatorDstAddr: validatorDstAddr, + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, SharesAmount: shares, } @@ -170,50 +170,51 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex } for _, msg := range m.CompleteRedelegates { - delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) + delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } - validatorSrcAddr, err := sdk.AccAddressFromBech32(msg.ValidatorSrcAddr) - if err != nil { - utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) - return - } - validatorDstAddr, err := sdk.AccAddressFromBech32(msg.ValidatorDstAddr) + valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { + valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddr) + if err != nil { + utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) + return + } + + if !bytes.Equal(info.GetPubKey().Address(), delAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } messages[i] = stake.MsgCompleteRedelegate{ - DelegatorAddr: delegatorAddr, - ValidatorSrcAddr: validatorSrcAddr, - ValidatorDstAddr: validatorDstAddr, + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, } i++ } for _, msg := range m.BeginUnbondings { - delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) + delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { + if !bytes.Equal(info.GetPubKey().Address(), delAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } - validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) + valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return @@ -226,8 +227,8 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex } messages[i] = stake.MsgBeginUnbonding{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, SharesAmount: shares, } @@ -235,26 +236,26 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex } for _, msg := range m.CompleteUnbondings { - delegatorAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) + delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())) return } - validatorAddr, err := sdk.AccAddressFromBech32(msg.ValidatorAddr) + valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddr) if err != nil { utils.WriteErrorResponse(&w, http.StatusInternalServerError, fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())) return } - if !bytes.Equal(info.GetPubKey().Address(), delegatorAddr) { + if !bytes.Equal(info.GetPubKey().Address(), delAddr) { utils.WriteErrorResponse(&w, http.StatusUnauthorized, "Must use own delegator address") return } messages[i] = stake.MsgCompleteUnbonding{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, } i++ diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 96588f73b5..171ded2b35 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -24,10 +24,10 @@ func contains(stringSlice []string, txType string) bool { return false } -func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( +func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( bech32Validator types.BechValidator, httpStatusCode int, errMsg string, err error) { - key := stake.GetDelegationKey(delegatorAddr, validatorAddr) + key := stake.GetDelegationKey(delAddr, valAddr) res, err := cliCtx.QueryStore(key, storeName) if err != nil { return types.BechValidator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err @@ -36,7 +36,7 @@ func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegator return types.BechValidator{}, http.StatusNoContent, "", nil } - key = stake.GetValidatorKey(validatorAddr) + key = stake.GetValidatorKey(valAddr) res, err = cliCtx.QueryStore(key, storeName) if err != nil { return types.BechValidator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err @@ -44,7 +44,7 @@ func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegator if len(res) == 0 { return types.BechValidator{}, http.StatusNoContent, "", nil } - validator, err := types.UnmarshalValidator(cdc, validatorAddr, res) + validator, err := types.UnmarshalValidator(cdc, valAddr, res) if err != nil { return types.BechValidator{}, http.StatusBadRequest, "", err } @@ -56,9 +56,11 @@ func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegator return bech32Validator, http.StatusOK, "", nil } -func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( +func getDelegatorDelegations( + cliCtx context.CLIContext, cdc *wire.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( outputDelegation DelegationWithoutRat, httpStatusCode int, errMsg string, err error) { - delegationKey := stake.GetDelegationKey(delegatorAddr, validatorAddr) + + delegationKey := stake.GetDelegationKey(delAddr, valAddr) marshalledDelegation, err := cliCtx.QueryStore(delegationKey, storeName) if err != nil { return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err @@ -83,9 +85,11 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat return outputDelegation, http.StatusOK, "", nil } -func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( +func getDelegatorUndelegations( + cliCtx context.CLIContext, cdc *wire.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( unbonds types.UnbondingDelegation, httpStatusCode int, errMsg string, err error) { - undelegationKey := stake.GetUBDKey(delegatorAddr, validatorAddr) + + undelegationKey := stake.GetUBDKey(delAddr, valAddr) marshalledUnbondingDelegation, err := cliCtx.QueryStore(undelegationKey, storeName) if err != nil { return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't query unbonding-delegation. Error: ", err @@ -102,10 +106,11 @@ func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg return unbondingDelegation, http.StatusOK, "", nil } -func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( +func getDelegatorRedelegations( + cliCtx context.CLIContext, cdc *wire.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( regelegations types.Redelegation, httpStatusCode int, errMsg string, err error) { - key := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr) + key := stake.GetREDsByDelToValDstIndexKey(delAddr, valAddr) marshalledRedelegations, err := cliCtx.QueryStore(key, storeName) if err != nil { return types.Redelegation{}, http.StatusInternalServerError, "couldn't query redelegation. Error: ", err diff --git a/x/stake/genesis_test.go b/x/stake/genesis_test.go index 9cdbe19826..ddd29f6f84 100644 --- a/x/stake/genesis_test.go +++ b/x/stake/genesis_test.go @@ -23,8 +23,8 @@ func TestInitGenesis(t *testing.T) { var delegations []Delegation validators := []Validator{ - NewValidator(keep.Addrs[0], keep.PKs[0], Description{Moniker: "hoop"}), - NewValidator(keep.Addrs[1], keep.PKs[1], Description{Moniker: "bloop"}), + NewValidator(sdk.ValAddress(keep.Addrs[0]), keep.PKs[0], Description{Moniker: "hoop"}), + NewValidator(sdk.ValAddress(keep.Addrs[1]), keep.PKs[1], Description{Moniker: "bloop"}), } genesisState := types.NewGenesisState(pool, params, validators, delegations) _, err := InitGenesis(ctx, keeper, genesisState) @@ -43,12 +43,12 @@ func TestInitGenesis(t *testing.T) { require.NoError(t, err) // now make sure the validators are bonded and intra-tx counters are correct - resVal, found := keeper.GetValidator(ctx, keep.Addrs[0]) + resVal, found := keeper.GetValidator(ctx, sdk.ValAddress(keep.Addrs[0])) require.True(t, found) require.Equal(t, sdk.Bonded, resVal.Status) require.Equal(t, int16(0), resVal.BondIntraTxCounter) - resVal, found = keeper.GetValidator(ctx, keep.Addrs[1]) + resVal, found = keeper.GetValidator(ctx, sdk.ValAddress(keep.Addrs[1])) require.True(t, found) require.Equal(t, sdk.Bonded, resVal.Status) require.Equal(t, int16(1), resVal.BondIntraTxCounter) @@ -76,7 +76,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { validators := make([]Validator, size) for i := range validators { - validators[i] = NewValidator(keep.Addrs[i], keep.PKs[i], Description{Moniker: fmt.Sprintf("#%d", i)}) + validators[i] = NewValidator(sdk.ValAddress(keep.Addrs[i]), keep.PKs[i], Description{Moniker: fmt.Sprintf("#%d", i)}) validators[i].Status = sdk.Bonded if i < 100 { diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 6ab54e48c2..f7d01bcfc7 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -16,23 +16,23 @@ import ( //______________________________________________________________________ -func newTestMsgCreateValidator(address sdk.AccAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator { +func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator { return types.NewMsgCreateValidator(address, pubKey, sdk.Coin{"steak", sdk.NewInt(amt)}, Description{}) } -func newTestMsgDelegate(delegatorAddr, validatorAddr sdk.AccAddress, amt int64) MsgDelegate { +func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int64) MsgDelegate { return MsgDelegate{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, Delegation: sdk.Coin{"steak", sdk.NewInt(amt)}, } } -func newTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr sdk.AccAddress, valPubKey crypto.PubKey, amt int64) MsgCreateValidator { +func newTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress, valPubKey crypto.PubKey, amt int64) MsgCreateValidator { return MsgCreateValidator{ Description: Description{}, - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, PubKey: valPubKey, Delegation: sdk.Coin{"steak", sdk.NewInt(amt)}, } @@ -49,7 +49,7 @@ func setInstantUnbondPeriod(keeper keep.Keeper, ctx sdk.Context) types.Params { //______________________________________________________________________ func TestValidatorByPowerIndex(t *testing.T) { - validatorAddr, validatorAddr3 := keep.Addrs[0], keep.Addrs[1] + validatorAddr, validatorAddr3 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]) initBond := int64(1000000) ctx, _, keeper := keep.CreateTestInput(t, false, initBond) @@ -61,7 +61,7 @@ func TestValidatorByPowerIndex(t *testing.T) { require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) // verify the self-delegation exists - bond, found := keeper.GetDelegation(ctx, validatorAddr, validatorAddr) + bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) require.True(t, found) gotBond := bond.Shares.RoundInt64() require.Equal(t, initBond, gotBond, @@ -110,8 +110,8 @@ func TestValidatorByPowerIndex(t *testing.T) { require.Equal(t, power2, power3) // unbond self-delegation - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000)) - msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) + msgBeginUnbonding := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(1000000)) + msgCompleteUnbonding := NewMsgCompleteUnbonding(sdk.AccAddress(validatorAddr), validatorAddr) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper) @@ -126,7 +126,7 @@ func TestValidatorByPowerIndex(t *testing.T) { func TestDuplicatesMsgCreateValidator(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - addr1, addr2 := keep.Addrs[0], keep.Addrs[1] + addr1, addr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]) pk1, pk2 := keep.PKs[0], keep.PKs[1] msgCreateValidator1 := newTestMsgCreateValidator(addr1, pk1, 10) @@ -170,7 +170,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr := keep.Addrs[0] + validatorAddr := sdk.ValAddress(keep.Addrs[0]) delegatorAddr := keep.Addrs[1] pk := keep.PKs[0] msgCreateValidatorOnBehalfOf := newTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, 10) @@ -199,7 +199,7 @@ func TestIncrementsMsgDelegate(t *testing.T) { params := keeper.GetParams(ctx) bondAmount := int64(10) - validatorAddr, delegatorAddr := keep.Addrs[0], keep.Addrs[1] + validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1] // first create validator msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], bondAmount) @@ -215,7 +215,7 @@ func TestIncrementsMsgDelegate(t *testing.T) { _, found = keeper.GetDelegation(ctx, delegatorAddr, validatorAddr) require.False(t, found) - bond, found := keeper.GetDelegation(ctx, validatorAddr, validatorAddr) + bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) require.True(t, found) require.Equal(t, bondAmount, bond.Shares.RoundInt64()) @@ -271,7 +271,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { denom := params.BondDenom // create validator, delegate - validatorAddr, delegatorAddr := keep.Addrs[0], keep.Addrs[1] + validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1] msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) @@ -367,7 +367,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) { ctx, accMapper, keeper := keep.CreateTestInput(t, false, initBond) params := setInstantUnbondPeriod(keeper, ctx) - validatorAddrs := []sdk.AccAddress{keep.Addrs[0], keep.Addrs[1], keep.Addrs[2]} + validatorAddrs := []sdk.ValAddress{sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), sdk.ValAddress(keep.Addrs[2])} delegatorAddrs := []sdk.AccAddress{keep.Addrs[3], keep.Addrs[4], keep.Addrs[5]} // bond them all @@ -414,7 +414,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) { func TestMultipleMsgDelegate(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr, delegatorAddrs := keep.Addrs[0], keep.Addrs[1:] + validatorAddr, delegatorAddrs := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1:] _ = setInstantUnbondPeriod(keeper, ctx) //first make a validator @@ -451,7 +451,7 @@ func TestMultipleMsgDelegate(t *testing.T) { func TestJailValidator(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr, delegatorAddr := keep.Addrs[0], keep.Addrs[1] + validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1] _ = setInstantUnbondPeriod(keeper, ctx) // create the validator @@ -467,8 +467,8 @@ func TestJailValidator(t *testing.T) { validator, _ := keeper.GetValidator(ctx, validatorAddr) // unbond the validators bond portion - msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10)) - msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) + msgBeginUnbondingValidator := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10)) + msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(sdk.AccAddress(validatorAddr), validatorAddr) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper) require.True(t, got.IsOK(), "expected no error") got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbondingValidator, keeper) @@ -497,7 +497,7 @@ func TestJailValidator(t *testing.T) { func TestUnbondingPeriod(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr := keep.Addrs[0] + validatorAddr := sdk.ValAddress(keep.Addrs[0]) // set the unbonding time params := keeper.GetParams(ctx) @@ -510,12 +510,12 @@ func TestUnbondingPeriod(t *testing.T) { require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // begin unbonding - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10)) + msgBeginUnbonding := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error") // cannot complete unbonding at same time - msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) + msgCompleteUnbonding := NewMsgCompleteUnbonding(sdk.AccAddress(validatorAddr), validatorAddr) got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper) require.True(t, !got.IsOK(), "expected an error") @@ -537,7 +537,7 @@ func TestUnbondingPeriod(t *testing.T) { func TestRedelegationPeriod(t *testing.T) { ctx, AccMapper, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr, validatorAddr2 := keep.Addrs[0], keep.Addrs[1] + validatorAddr, validatorAddr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]) denom := keeper.GetParams(ctx).BondDenom // set the unbonding time @@ -549,32 +549,32 @@ func TestRedelegationPeriod(t *testing.T) { msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10) // initial balance - amt1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins().AmountOf(denom) + amt1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // balance should have been subtracted after creation - amt2 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins().AmountOf(denom) + amt2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom) require.Equal(t, amt1.Sub(sdk.NewInt(10)).Int64(), amt2.Int64(), "expected coins to be subtracted") msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10) got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") - bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins() + bal1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins() // begin redelegate - msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10)) + msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, got.IsOK(), "expected no error, %v", got) // origin account should not lose tokens as with a regular delegation - bal2 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins() + bal2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins() require.Equal(t, bal1, bal2) // cannot complete redelegation at same time - msgCompleteRedelegate := NewMsgCompleteRedelegate(validatorAddr, validatorAddr, validatorAddr2) + msgCompleteRedelegate := NewMsgCompleteRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2) got = handleMsgCompleteRedelegate(ctx, msgCompleteRedelegate, keeper) require.True(t, !got.IsOK(), "expected an error") @@ -596,7 +596,9 @@ func TestRedelegationPeriod(t *testing.T) { func TestTransitiveRedelegation(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr, validatorAddr2, validatorAddr3 := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] + validatorAddr := sdk.ValAddress(keep.Addrs[0]) + validatorAddr2 := sdk.ValAddress(keep.Addrs[1]) + validatorAddr3 := sdk.ValAddress(keep.Addrs[2]) // set the unbonding time params := keeper.GetParams(ctx) @@ -617,17 +619,17 @@ func TestTransitiveRedelegation(t *testing.T) { require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // begin redelegate - msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10)) + msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, got.IsOK(), "expected no error, %v", got) // cannot redelegation to next validator while first delegation exists - msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewDec(10)) + msgBeginRedelegate = NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr2, validatorAddr3, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate) // complete first redelegation - msgCompleteRedelegate := NewMsgCompleteRedelegate(validatorAddr, validatorAddr, validatorAddr2) + msgCompleteRedelegate := NewMsgCompleteRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2) got = handleMsgCompleteRedelegate(ctx, msgCompleteRedelegate, keeper) require.True(t, got.IsOK(), "expected no error") @@ -638,7 +640,9 @@ func TestTransitiveRedelegation(t *testing.T) { func TestUnbondingWhenExcessValidators(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr1, validatorAddr2, validatorAddr3 := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] + validatorAddr1 := sdk.ValAddress(keep.Addrs[0]) + validatorAddr2 := sdk.ValAddress(keep.Addrs[1]) + validatorAddr3 := sdk.ValAddress(keep.Addrs[2]) // set the unbonding time params := keeper.GetParams(ctx) @@ -663,7 +667,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx))) // unbond the valdator-2 - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30)) + msgBeginUnbonding := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr2), validatorAddr2, sdk.NewDec(30)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -679,7 +683,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { func TestJoiningAsCliffValidator(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr1, validatorAddr2 := keep.Addrs[0], keep.Addrs[1] + validatorAddr1, validatorAddr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]) // make sure that the cliff validator is nil to begin with cliffVal := keeper.GetCliffValidator(ctx) @@ -712,7 +716,7 @@ func TestJoiningAsCliffValidator(t *testing.T) { func TestJoiningToCreateFirstCliffValidator(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr1, validatorAddr2 := keep.Addrs[0], keep.Addrs[1] + validatorAddr1, validatorAddr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]) // make sure that the cliff validator is nil to begin with cliffVal := keeper.GetCliffValidator(ctx) @@ -745,7 +749,9 @@ func TestJoiningToCreateFirstCliffValidator(t *testing.T) { func TestCliffValidator(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - validatorAddr1, validatorAddr2, validatorAddr3 := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] + validatorAddr1 := sdk.ValAddress(keep.Addrs[0]) + validatorAddr2 := sdk.ValAddress(keep.Addrs[1]) + validatorAddr3 := sdk.ValAddress(keep.Addrs[2]) // make sure that the cliff validator is nil to begin with cliffVal := keeper.GetCliffValidator(ctx) @@ -785,7 +791,7 @@ func TestCliffValidator(t *testing.T) { require.Equal(t, validatorAddr2.Bytes(), cliffVal) // unbond valdator-2 - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30)) + msgBeginUnbonding := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr2), validatorAddr2, sdk.NewDec(30)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -798,7 +804,7 @@ func TestCliffValidator(t *testing.T) { require.Equal(t, validatorAddr3.Bytes(), cliffVal) // unbond valdator-1 - msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50)) + msgBeginUnbonding = NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr1), validatorAddr1, sdk.NewDec(50)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -813,7 +819,7 @@ func TestCliffValidator(t *testing.T) { func TestBondUnbondRedelegateSlashTwice(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - valA, valB, del := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] + valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2] msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index a6e48517c9..9f7a402fc2 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -9,10 +9,11 @@ import ( // load a delegation func (k Keeper) GetDelegation(ctx sdk.Context, - delegatorAddr, validatorAddr sdk.AccAddress) (delegation types.Delegation, found bool) { + delAddr sdk.AccAddress, valAddr sdk.ValAddress) ( + delegation types.Delegation, found bool) { store := ctx.KVStore(k.storeKey) - key := GetDelegationKey(delegatorAddr, validatorAddr) + key := GetDelegationKey(delAddr, valAddr) value := store.Get(key) if value == nil { return delegation, false @@ -79,10 +80,10 @@ func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { // load a unbonding delegation func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, - DelegatorAddr, ValidatorAddr sdk.AccAddress) (ubd types.UnbondingDelegation, found bool) { + delAddr sdk.AccAddress, valAddr sdk.ValAddress) (ubd types.UnbondingDelegation, found bool) { store := ctx.KVStore(k.storeKey) - key := GetUBDKey(DelegatorAddr, ValidatorAddr) + key := GetUBDKey(delAddr, valAddr) value := store.Get(key) if value == nil { return ubd, false @@ -93,7 +94,7 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context, } // load all unbonding delegations from a particular validator -func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.AccAddress) (ubds []types.UnbondingDelegation) { +func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (ubds []types.UnbondingDelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr)) for { @@ -147,10 +148,10 @@ func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDe // load a redelegation func (k Keeper) GetRedelegation(ctx sdk.Context, - DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr sdk.AccAddress) (red types.Redelegation, found bool) { + delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (red types.Redelegation, found bool) { store := ctx.KVStore(k.storeKey) - key := GetREDKey(DelegatorAddr, ValidatorSrcAddr, ValidatorDstAddr) + key := GetREDKey(delAddr, valSrcAddr, valDstAddr) value := store.Get(key) if value == nil { return red, false @@ -161,7 +162,7 @@ func (k Keeper) GetRedelegation(ctx sdk.Context, } // load all redelegations from a particular validator -func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.AccAddress) (reds []types.Redelegation) { +func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (reds []types.Redelegation) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr)) for { @@ -180,10 +181,10 @@ func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.AccAd // has a redelegation func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, - DelegatorAddr, ValidatorDstAddr sdk.AccAddress) bool { + delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool { store := ctx.KVStore(k.storeKey) - prefix := GetREDsByDelToValDstIndexKey(DelegatorAddr, ValidatorDstAddr) + prefix := GetREDsByDelToValDstIndexKey(delAddr, valDstAddr) iterator := sdk.KVStorePrefixIterator(store, prefix) //smallest to largest found := false @@ -217,14 +218,14 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { //_____________________________________________________________________________________ // Perform a delegation, set/update everything necessary within the store. -func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin, +func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Coin, validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { // Get or create the delegator delegation - delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Operator) + delegation, found := k.GetDelegation(ctx, delAddr, validator.Operator) if !found { delegation = types.Delegation{ - DelegatorAddr: delegatorAddr, + DelegatorAddr: delAddr, ValidatorAddr: validator.Operator, Shares: sdk.ZeroDec(), } @@ -253,11 +254,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt } // unbond the the delegation return -func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, +func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares sdk.Dec) (amount sdk.Dec, err sdk.Error) { // check if delegation has any shares in it unbond - delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr) + delegation, found := k.GetDelegation(ctx, delAddr, valAddr) if !found { err = types.ErrNoDelegatorForAddress(k.Codespace()) return @@ -270,7 +271,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr } // get validator - validator, found := k.GetValidator(ctx, validatorAddr) + validator, found := k.GetValidator(ctx, valAddr) if !found { err = types.ErrNoValidatorFound(k.Codespace()) return @@ -312,15 +313,16 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr //______________________________________________________________________________________________________ // complete unbonding an unbonding record -func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error { +func (k Keeper) BeginUnbonding(ctx sdk.Context, + delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) sdk.Error { // TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402 - _, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) + _, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr) if found { return types.ErrExistingUnbondingDelegation(k.Codespace()) } - returnAmount, err := k.unbond(ctx, delegatorAddr, validatorAddr, sharesAmount) + returnAmount, err := k.unbond(ctx, delAddr, valAddr, sharesAmount) if err != nil { return err } @@ -331,8 +333,8 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk balance := sdk.Coin{params.BondDenom, returnAmount.RoundInt()} ubd := types.UnbondingDelegation{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, MinTime: minTime, Balance: balance, InitialBalance: balance, @@ -342,9 +344,9 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk } // complete unbonding an unbonding record -func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress) sdk.Error { +func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) sdk.Error { - ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) + ubd, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr) if !found { return types.ErrNoUnbondingDelegation(k.Codespace()) } @@ -364,26 +366,26 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr } // complete unbonding an unbonding record -func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error { +func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, + valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) sdk.Error { // check if this is a transitive redelegation - if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) { + if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) { return types.ErrTransitiveRedelegation(k.Codespace()) } - returnAmount, err := k.unbond(ctx, delegatorAddr, validatorSrcAddr, sharesAmount) + returnAmount, err := k.unbond(ctx, delAddr, valSrcAddr, sharesAmount) if err != nil { return err } params := k.GetParams(ctx) returnCoin := sdk.Coin{params.BondDenom, returnAmount.RoundInt()} - dstValidator, found := k.GetValidator(ctx, validatorDstAddr) + dstValidator, found := k.GetValidator(ctx, valDstAddr) if !found { return types.ErrBadRedelegationDst(k.Codespace()) } - sharesCreated, err := k.Delegate(ctx, delegatorAddr, returnCoin, dstValidator, false) + sharesCreated, err := k.Delegate(ctx, delAddr, returnCoin, dstValidator, false) if err != nil { return err } @@ -392,9 +394,9 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAd minTime := ctx.BlockHeader().Time.Add(params.UnbondingTime) red := types.Redelegation{ - DelegatorAddr: delegatorAddr, - ValidatorSrcAddr: validatorSrcAddr, - ValidatorDstAddr: validatorDstAddr, + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, MinTime: minTime, SharesDst: sharesCreated, SharesSrc: sharesAmount, @@ -406,9 +408,10 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAd } // complete unbonding an ongoing redelegation -func (k Keeper) CompleteRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) sdk.Error { +func (k Keeper) CompleteRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, + valSrcAddr, valDstAddr sdk.ValAddress) sdk.Error { - red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) + red, found := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr) if !found { return types.ErrNoRedelegation(k.Codespace()) } diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 958de62ed5..d539c35d05 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -36,8 +36,8 @@ const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch // gets the key for the validator with address // VALUE: stake/types.Validator -func GetValidatorKey(ownerAddr sdk.AccAddress) []byte { - return append(ValidatorsKey, ownerAddr.Bytes()...) +func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { + return append(ValidatorsKey, operatorAddr.Bytes()...) } // gets the key for the validator with pubkey @@ -48,8 +48,8 @@ func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { // gets the key for the current validator group // VALUE: none (key rearrangement with GetValKeyFromValBondedIndexKey) -func GetValidatorsBondedIndexKey(ownerAddr sdk.AccAddress) []byte { - return append(ValidatorsBondedIndexKey, ownerAddr.Bytes()...) +func GetValidatorsBondedIndexKey(operatorAddr sdk.ValAddress) []byte { + return append(ValidatorsBondedIndexKey, operatorAddr.Bytes()...) } // Get the validator owner address from ValBondedIndexKey @@ -97,37 +97,37 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte { // get the key for the accumulated update validators // VALUE: abci.Validator // note records using these keys should never persist between blocks -func GetTendermintUpdatesKey(ownerAddr sdk.AccAddress) []byte { - return append(TendermintUpdatesKey, ownerAddr.Bytes()...) +func GetTendermintUpdatesKey(operatorAddr sdk.ValAddress) []byte { + return append(TendermintUpdatesKey, operatorAddr.Bytes()...) } //______________________________________________________________________________ // gets the key for delegator bond with validator // VALUE: stake/types.Delegation -func GetDelegationKey(delegatorAddr, validatorAddr sdk.AccAddress) []byte { - return append(GetDelegationsKey(delegatorAddr), validatorAddr.Bytes()...) +func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetDelegationsKey(delAddr), valAddr.Bytes()...) } // gets the prefix for a delegator for all validators -func GetDelegationsKey(delegatorAddr sdk.AccAddress) []byte { - return append(DelegationKey, delegatorAddr.Bytes()...) +func GetDelegationsKey(delAddr sdk.AccAddress) []byte { + return append(DelegationKey, delAddr.Bytes()...) } //______________________________________________________________________________ // gets the key for an unbonding delegation by delegator and validator addr // VALUE: stake/types.UnbondingDelegation -func GetUBDKey(delegatorAddr, validatorAddr sdk.AccAddress) []byte { +func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { return append( - GetUBDsKey(delegatorAddr.Bytes()), - validatorAddr.Bytes()...) + GetUBDsKey(delAddr.Bytes()), + valAddr.Bytes()...) } // gets the index-key for an unbonding delegation, stored by validator-index // VALUE: none (key rearrangement used) -func GetUBDByValIndexKey(delegatorAddr, validatorAddr sdk.AccAddress) []byte { - return append(GetUBDsByValIndexKey(validatorAddr), delegatorAddr.Bytes()...) +func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { + return append(GetUBDsByValIndexKey(valAddr), delAddr.Bytes()...) } // rearranges the ValIndexKey to get the UBDKey @@ -144,42 +144,42 @@ func GetUBDKeyFromValIndexKey(IndexKey []byte) []byte { //______________ // gets the prefix for all unbonding delegations from a delegator -func GetUBDsKey(delegatorAddr sdk.AccAddress) []byte { - return append(UnbondingDelegationKey, delegatorAddr.Bytes()...) +func GetUBDsKey(delAddr sdk.AccAddress) []byte { + return append(UnbondingDelegationKey, delAddr.Bytes()...) } // gets the prefix keyspace for the indexes of unbonding delegations for a validator -func GetUBDsByValIndexKey(validatorAddr sdk.AccAddress) []byte { - return append(UnbondingDelegationByValIndexKey, validatorAddr.Bytes()...) +func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { + return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...) } //________________________________________________________________________________ // gets the key for a redelegation // VALUE: stake/types.RedelegationKey -func GetREDKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) []byte { +func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { return append(append( - GetREDsKey(delegatorAddr.Bytes()), - validatorSrcAddr.Bytes()...), - validatorDstAddr.Bytes()...) + GetREDsKey(delAddr.Bytes()), + valSrcAddr.Bytes()...), + valDstAddr.Bytes()...) } // gets the index-key for a redelegation, stored by source-validator-index // VALUE: none (key rearrangement used) -func GetREDByValSrcIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) []byte { +func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { return append(append( - GetREDsFromValSrcIndexKey(validatorSrcAddr), - delegatorAddr.Bytes()...), - validatorDstAddr.Bytes()...) + GetREDsFromValSrcIndexKey(valSrcAddr), + delAddr.Bytes()...), + valDstAddr.Bytes()...) } // gets the index-key for a redelegation, stored by destination-validator-index // VALUE: none (key rearrangement used) -func GetREDByValDstIndexKey(delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) []byte { +func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { return append(append( - GetREDsToValDstIndexKey(validatorDstAddr), - delegatorAddr.Bytes()...), - validatorSrcAddr.Bytes()...) + GetREDsToValDstIndexKey(valDstAddr), + delAddr.Bytes()...), + valSrcAddr.Bytes()...) } // rearranges the ValSrcIndexKey to get the REDKey @@ -210,24 +210,24 @@ func GetREDKeyFromValDstIndexKey(IndexKey []byte) []byte { //______________ // gets the prefix keyspace for redelegations from a delegator -func GetREDsKey(delegatorAddr sdk.AccAddress) []byte { - return append(RedelegationKey, delegatorAddr.Bytes()...) +func GetREDsKey(delAddr sdk.AccAddress) []byte { + return append(RedelegationKey, delAddr.Bytes()...) } // gets the prefix keyspace for all redelegations redelegating away from a source validator -func GetREDsFromValSrcIndexKey(validatorSrcAddr sdk.AccAddress) []byte { - return append(RedelegationByValSrcIndexKey, validatorSrcAddr.Bytes()...) +func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { + return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...) } // gets the prefix keyspace for all redelegations redelegating towards a destination validator -func GetREDsToValDstIndexKey(validatorDstAddr sdk.AccAddress) []byte { - return append(RedelegationByValDstIndexKey, validatorDstAddr.Bytes()...) +func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { + return append(RedelegationByValDstIndexKey, valDstAddr.Bytes()...) } // gets the prefix keyspace for all redelegations redelegating towards a destination validator // from a particular delegator -func GetREDsByDelToValDstIndexKey(delegatorAddr, validatorDstAddr sdk.AccAddress) []byte { +func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { return append( - GetREDsToValDstIndexKey(validatorDstAddr), - delegatorAddr.Bytes()...) + GetREDsToValDstIndexKey(valDstAddr), + delAddr.Bytes()...) } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index aeec44fae9..480df701b1 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -51,7 +51,7 @@ func (k Keeper) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, va } // get the sdk.validator for a particular address -func (k Keeper) Validator(ctx sdk.Context, address sdk.AccAddress) sdk.Validator { +func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) sdk.Validator { val, found := k.GetValidator(ctx, address) if !found { return nil @@ -86,7 +86,7 @@ func (k Keeper) GetValidatorSet() sdk.ValidatorSet { } // get the delegation for a particular set of delegator and validator addresses -func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.AccAddress) sdk.Delegation { +func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.ValAddress) sdk.Delegation { bond, ok := k.GetDelegation(ctx, addrDel, addrVal) if !ok { return nil diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index 0470c28988..b84ce9d93a 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -33,12 +33,12 @@ var ( Addrs[0], Addrs[1], } - addrVals = []sdk.AccAddress{ - Addrs[2], - Addrs[3], - Addrs[4], - Addrs[5], - Addrs[6], + addrVals = []sdk.ValAddress{ + sdk.ValAddress(Addrs[2]), + sdk.ValAddress(Addrs[3]), + sdk.ValAddress(Addrs[4]), + sdk.ValAddress(Addrs[5]), + sdk.ValAddress(Addrs[6]), } ) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index e933a6d236..cb225df6cc 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -12,7 +12,7 @@ import ( ) // get a single validator -func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.AccAddress) (validator types.Validator, found bool) { +func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) value := store.Get(GetValidatorKey(addr)) if value == nil { @@ -223,7 +223,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type store.Set(GetTendermintUpdatesKey(validator.Operator), bz) if cliffPower != nil { - cliffAddr := sdk.AccAddress(k.GetCliffValidator(ctx)) + cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx)) if bytes.Equal(cliffAddr, validator.Operator) { k.updateCliffValidator(ctx, validator) } @@ -273,7 +273,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) - cliffAddr := sdk.AccAddress(k.GetCliffValidator(ctx)) + cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx)) oldCliffVal, found := k.GetValidator(ctx, cliffAddr) if !found { @@ -621,7 +621,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. } // remove the validator record and associated indexes -func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.AccAddress) { +func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 9e92ca33e7..e4a2663ae6 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -109,7 +109,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { validators := make([]types.Validator, numVals) for i := 0; i < len(validators); i++ { moniker := fmt.Sprintf("val#%d", int64(i)) - val := types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) + val := types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{Moniker: moniker}) val.BondHeight = int64(i) val.BondIntraTxCounter = int16(i) val, pool, _ = val.AddTokensFromDel(pool, sdk.NewInt(int64((i+1)*10))) @@ -129,7 +129,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // require the cliff validator has changed cliffVal := validators[numVals-maxVals-1] - require.Equal(t, cliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, cliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // require the cliff validator power has changed cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -172,7 +172,7 @@ func TestCliffValidatorChange(t *testing.T) { validators := make([]types.Validator, numVals) for i := 0; i < len(validators); i++ { moniker := fmt.Sprintf("val#%d", int64(i)) - val := types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) + val := types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{Moniker: moniker}) val.BondHeight = int64(i) val.BondIntraTxCounter = int16(i) val, pool, _ = val.AddTokensFromDel(pool, sdk.NewInt(int64((i+1)*10))) @@ -190,7 +190,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert new cliff validator to be set to the second lowest bonded validator by power newCliffVal := validators[numVals-maxVals+1] - require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -203,7 +203,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert cliff validator has not change but increased in power cliffPower = keeper.GetCliffValidatorPower(ctx) - require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) // add enough power to cliff validator to be equal in rank to next validator @@ -213,7 +213,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert new cliff validator due to power rank construction newCliffVal = validators[numVals-maxVals+2] - require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.ValAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower = keeper.GetCliffValidatorPower(ctx) @@ -329,7 +329,7 @@ func GetValidatorSortingUnmixed(t *testing.T) { n := len(amts) var validators [5]types.Validator for i, amt := range amts { - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i].Status = sdk.Bonded validators[i].Tokens = sdk.NewDec(amt) validators[i].DelegatorShares = sdk.NewDec(amt) @@ -412,7 +412,7 @@ func GetValidatorSortingMixed(t *testing.T) { n := len(amts) var validators [5]types.Validator for i, amt := range amts { - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i].DelegatorShares = sdk.NewDec(amt) } @@ -431,15 +431,15 @@ func GetValidatorSortingMixed(t *testing.T) { for i := range amts { keeper.UpdateValidator(ctx, validators[i]) } - val0, found := keeper.GetValidator(ctx, Addrs[0]) + val0, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[0])) require.True(t, found) - val1, found := keeper.GetValidator(ctx, Addrs[1]) + val1, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[1])) require.True(t, found) - val2, found := keeper.GetValidator(ctx, Addrs[2]) + val2, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[2])) require.True(t, found) - val3, found := keeper.GetValidator(ctx, Addrs[3]) + val3, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[3])) require.True(t, found) - val4, found := keeper.GetValidator(ctx, Addrs[4]) + val4, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[4])) require.True(t, found) require.Equal(t, sdk.Unbonded, val0.Status) require.Equal(t, sdk.Unbonded, val1.Status) @@ -479,7 +479,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { for i, amt := range amts { pool := keeper.GetPool(ctx) moniker := fmt.Sprintf("val#%d", int64(i)) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{Moniker: moniker}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) validators[i] = keeper.UpdateValidator(ctx, validators[i]) @@ -553,9 +553,9 @@ func TestValidatorBondHeight(t *testing.T) { // initialize some validators into the state var validators [3]types.Validator - validators[0] = types.NewValidator(Addrs[0], PKs[0], types.Description{}) - validators[1] = types.NewValidator(Addrs[1], PKs[1], types.Description{}) - validators[2] = types.NewValidator(Addrs[2], PKs[2], types.Description{}) + validators[0] = types.NewValidator(sdk.ValAddress(Addrs[0]), PKs[0], types.Description{}) + validators[1] = types.NewValidator(sdk.ValAddress(Addrs[1]), PKs[1], types.Description{}) + validators[2] = types.NewValidator(sdk.ValAddress(Addrs[2]), PKs[2], types.Description{}) validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(200)) validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(100)) @@ -600,7 +600,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { var validators [5]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validators[i]) @@ -639,7 +639,7 @@ func TestClearTendermintUpdates(t *testing.T) { validators := make([]types.Validator, len(amts)) for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validators[i]) @@ -659,7 +659,7 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -698,7 +698,7 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) { var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -721,7 +721,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -749,7 +749,7 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -780,7 +780,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { var validators [5]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -823,7 +823,7 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) { var validators [5]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } @@ -861,7 +861,7 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { var validators [2]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) } diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 4280e70c13..97ed112c01 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -26,8 +26,8 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation } key := simulation.RandomKey(r, keys) pubkey := key.PubKey() - address := sdk.AccAddress(pubkey.Address()) - amount := m.GetAccount(ctx, address).GetCoins().AmountOf(denom) + address := sdk.ValAddress(pubkey.Address()) + amount := m.GetAccount(ctx, sdk.AccAddress(address)).GetCoins().AmountOf(denom) if amount.GT(sdk.ZeroInt()) { amount = simulation.RandomAmount(r, amount) } @@ -37,7 +37,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation msg := stake.MsgCreateValidator{ Description: description, ValidatorAddr: address, - DelegatorAddr: address, + DelegatorAddr: sdk.AccAddress(address), PubKey: pubkey, Delegation: sdk.NewCoin(denom, amount), } @@ -65,7 +65,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { } key := simulation.RandomKey(r, keys) pubkey := key.PubKey() - address := sdk.AccAddress(pubkey.Address()) + address := sdk.ValAddress(pubkey.Address()) msg := stake.MsgEditValidator{ Description: description, ValidatorAddr: address, @@ -87,7 +87,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) @@ -119,7 +119,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) @@ -150,7 +150,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) + validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) msg := stake.MsgCompleteUnbonding{ @@ -174,9 +174,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) - sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address()) + sourceValidatorAddress := sdk.ValAddress(sourceValidatorKey.PubKey().Address()) destValidatorKey := simulation.RandomKey(r, keys) - destValidatorAddress := sdk.AccAddress(destValidatorKey.PubKey().Address()) + destValidatorAddress := sdk.ValAddress(destValidatorKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) // TODO @@ -209,9 +209,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) - validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) + validatorSrcAddress := sdk.ValAddress(validatorSrcKey.PubKey().Address()) validatorDstKey := simulation.RandomKey(r, keys) - validatorDstAddress := sdk.AccAddress(validatorDstKey.PubKey().Address()) + validatorDstAddress := sdk.ValAddress(validatorDstKey.PubKey().Address()) delegatorKey := simulation.RandomKey(r, keys) delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) msg := stake.MsgCompleteRedelegate{ diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index e3227c3ed1..5a2274c3ae 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -14,7 +14,7 @@ import ( // pubKey. type Delegation struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` Shares sdk.Dec `json:"shares"` Height int64 `json:"height"` // Last height bond updated } @@ -56,8 +56,9 @@ func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) (delegation Delegat err = fmt.Errorf("%v", ErrBadDelegationAddr(DefaultCodespace).Data()) return } + delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) - valAddr := sdk.AccAddress(addrs[sdk.AddrLen:]) + valAddr := sdk.ValAddress(addrs[sdk.AddrLen:]) return Delegation{ DelegatorAddr: delAddr, @@ -80,7 +81,7 @@ var _ sdk.Delegation = Delegation{} // nolint - for sdk.Delegation func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } -func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr } +func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr } func (d Delegation) GetBondShares() sdk.Dec { return d.Shares } // HumanReadableString returns a human readable string representation of a @@ -99,7 +100,7 @@ func (d Delegation) HumanReadableString() (string, error) { // UnbondingDelegation reflects a delegation's passive unbonding queue. type UnbondingDelegation struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // delegator - ValidatorAddr sdk.AccAddress `json:"validator_addr"` // validator unbonding from owner addr + ValidatorAddr sdk.ValAddress `json:"validator_addr"` // validator unbonding from operator addr CreationHeight int64 `json:"creation_height"` // height which the unbonding took place MinTime time.Time `json:"min_time"` // unix time for unbonding completion InitialBalance sdk.Coin `json:"initial_balance"` // atoms initially scheduled to receive at completion @@ -147,7 +148,7 @@ func UnmarshalUBD(cdc *wire.Codec, key, value []byte) (ubd UnbondingDelegation, return } delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) - valAddr := sdk.AccAddress(addrs[sdk.AddrLen:]) + valAddr := sdk.ValAddress(addrs[sdk.AddrLen:]) return UnbondingDelegation{ DelegatorAddr: delAddr, @@ -184,8 +185,8 @@ func (d UnbondingDelegation) HumanReadableString() (string, error) { // Redelegation reflects a delegation's passive re-delegation queue. type Redelegation struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // delegator - ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` // validator redelegation source owner addr - ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` // validator redelegation destination owner addr + ValidatorSrcAddr sdk.ValAddress `json:"validator_src_addr"` // validator redelegation source operator addr + ValidatorDstAddr sdk.ValAddress `json:"validator_dst_addr"` // validator redelegation destination operator addr CreationHeight int64 `json:"creation_height"` // height which the redelegation took place MinTime time.Time `json:"min_time"` // unix time for redelegation completion InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started @@ -239,8 +240,8 @@ func UnmarshalRED(cdc *wire.Codec, key, value []byte) (red Redelegation, err err return } delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) - valSrcAddr := sdk.AccAddress(addrs[sdk.AddrLen : 2*sdk.AddrLen]) - valDstAddr := sdk.AccAddress(addrs[2*sdk.AddrLen:]) + valSrcAddr := sdk.ValAddress(addrs[sdk.AddrLen : 2*sdk.AddrLen]) + valDstAddr := sdk.ValAddress(addrs[2*sdk.AddrLen:]) return Redelegation{ DelegatorAddr: delAddr, diff --git a/x/stake/types/delegation_test.go b/x/stake/types/delegation_test.go index 5624b71015..8e0dda7e24 100644 --- a/x/stake/types/delegation_test.go +++ b/x/stake/types/delegation_test.go @@ -10,12 +10,12 @@ import ( func TestDelegationEqual(t *testing.T) { d1 := Delegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, Shares: sdk.NewDec(100), } d2 := Delegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, Shares: sdk.NewDec(100), } @@ -23,7 +23,7 @@ func TestDelegationEqual(t *testing.T) { ok := d1.Equal(d2) require.True(t, ok) - d2.ValidatorAddr = addr3 + d2.ValidatorAddr = sdk.ValAddress(addr3) d2.Shares = sdk.NewDec(200) ok = d1.Equal(d2) @@ -32,7 +32,7 @@ func TestDelegationEqual(t *testing.T) { func TestDelegationHumanReadableString(t *testing.T) { d := Delegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, Shares: sdk.NewDec(100), } @@ -46,18 +46,18 @@ func TestDelegationHumanReadableString(t *testing.T) { func TestUnbondingDelegationEqual(t *testing.T) { ud1 := UnbondingDelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, } ud2 := UnbondingDelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, } ok := ud1.Equal(ud2) require.True(t, ok) - ud2.ValidatorAddr = addr3 + ud2.ValidatorAddr = sdk.ValAddress(addr3) ud2.MinTime = time.Unix(20*20*2, 0) ok = ud1.Equal(ud2) @@ -66,7 +66,7 @@ func TestUnbondingDelegationEqual(t *testing.T) { func TestUnbondingDelegationHumanReadableString(t *testing.T) { ud := UnbondingDelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorAddr: addr2, } @@ -79,12 +79,12 @@ func TestUnbondingDelegationHumanReadableString(t *testing.T) { func TestRedelegationEqual(t *testing.T) { r1 := Redelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorSrcAddr: addr2, ValidatorDstAddr: addr3, } r2 := Redelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorSrcAddr: addr2, ValidatorDstAddr: addr3, } @@ -102,7 +102,7 @@ func TestRedelegationEqual(t *testing.T) { func TestRedelegationHumanReadableString(t *testing.T) { r := Redelegation{ - DelegatorAddr: addr1, + DelegatorAddr: sdk.AccAddress(addr1), ValidatorSrcAddr: addr2, ValidatorDstAddr: addr3, SharesDst: sdk.NewDec(10), diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 282000294b..71a8c86314 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -1,7 +1,7 @@ package types import ( - "reflect" + "bytes" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/tendermint/tendermint/crypto" @@ -21,30 +21,27 @@ var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{} type MsgCreateValidator struct { Description DelegatorAddr sdk.AccAddress `json:"delegator_address"` - ValidatorAddr sdk.AccAddress `json:"validator_address"` + ValidatorAddr sdk.ValAddress `json:"validator_address"` PubKey crypto.PubKey `json:"pubkey"` Delegation sdk.Coin `json:"delegation"` } // Default way to create validator. Delegator address and validator address are the same -func NewMsgCreateValidator(validatorAddr sdk.AccAddress, pubkey crypto.PubKey, +func NewMsgCreateValidator(valAddr sdk.ValAddress, pubkey crypto.PubKey, selfDelegation sdk.Coin, description Description) MsgCreateValidator { - return MsgCreateValidator{ - Description: description, - DelegatorAddr: validatorAddr, - ValidatorAddr: validatorAddr, - PubKey: pubkey, - Delegation: selfDelegation, - } + + return NewMsgCreateValidatorOnBehalfOf( + sdk.AccAddress(valAddr), valAddr, pubkey, selfDelegation, description, + ) } // Creates validator msg by delegator address on behalf of validator address -func NewMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr sdk.AccAddress, pubkey crypto.PubKey, - delegation sdk.Coin, description Description) MsgCreateValidator { +func NewMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress, + pubkey crypto.PubKey, delegation sdk.Coin, description Description) MsgCreateValidator { return MsgCreateValidator{ Description: description, - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, PubKey: pubkey, Delegation: delegation, } @@ -57,9 +54,11 @@ func (msg MsgCreateValidator) Type() string { return MsgType } func (msg MsgCreateValidator) GetSigners() []sdk.AccAddress { // delegator is first signer so delegator pays fees addrs := []sdk.AccAddress{msg.DelegatorAddr} - if !reflect.DeepEqual(msg.DelegatorAddr, msg.ValidatorAddr) { - // if validator addr is not same as delegator addr, validator must sign msg as well - addrs = append(addrs, msg.ValidatorAddr) + + if !bytes.Equal(msg.DelegatorAddr.Bytes(), msg.ValidatorAddr.Bytes()) { + // if validator addr is not same as delegator addr, validator must sign + // msg as well + addrs = append(addrs, sdk.AccAddress(msg.ValidatorAddr)) } return addrs } @@ -69,13 +68,13 @@ func (msg MsgCreateValidator) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(struct { Description DelegatorAddr sdk.AccAddress `json:"delegator_address"` - ValidatorAddr sdk.AccAddress `json:"validator_address"` + ValidatorAddr sdk.ValAddress `json:"validator_address"` PubKey string `json:"pubkey"` Delegation sdk.Coin `json:"delegation"` }{ Description: msg.Description, ValidatorAddr: msg.ValidatorAddr, - PubKey: sdk.MustBech32ifyValPub(msg.PubKey), + PubKey: sdk.MustBech32ifyConsPub(msg.PubKey), Delegation: msg.Delegation, }) if err != nil { @@ -107,27 +106,27 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error { // MsgEditValidator - struct for editing a validator type MsgEditValidator struct { Description - ValidatorAddr sdk.AccAddress `json:"address"` + ValidatorAddr sdk.ValAddress `json:"address"` } -func NewMsgEditValidator(validatorAddr sdk.AccAddress, description Description) MsgEditValidator { +func NewMsgEditValidator(valAddr sdk.ValAddress, description Description) MsgEditValidator { return MsgEditValidator{ Description: description, - ValidatorAddr: validatorAddr, + ValidatorAddr: valAddr, } } //nolint func (msg MsgEditValidator) Type() string { return MsgType } func (msg MsgEditValidator) GetSigners() []sdk.AccAddress { - return []sdk.AccAddress{msg.ValidatorAddr} + return []sdk.AccAddress{sdk.AccAddress(msg.ValidatorAddr)} } // get the bytes for the message signer to sign on func (msg MsgEditValidator) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(struct { Description - ValidatorAddr sdk.AccAddress `json:"address"` + ValidatorAddr sdk.ValAddress `json:"address"` }{ Description: msg.Description, ValidatorAddr: msg.ValidatorAddr, @@ -155,14 +154,14 @@ func (msg MsgEditValidator) ValidateBasic() sdk.Error { // MsgDelegate - struct for bonding transactions type MsgDelegate struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` Delegation sdk.Coin `json:"delegation"` } -func NewMsgDelegate(delegatorAddr, validatorAddr sdk.AccAddress, delegation sdk.Coin) MsgDelegate { +func NewMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, delegation sdk.Coin) MsgDelegate { return MsgDelegate{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, Delegation: delegation, } } @@ -201,18 +200,18 @@ func (msg MsgDelegate) ValidateBasic() sdk.Error { // MsgDelegate - struct for bonding transactions type MsgBeginRedelegate struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` - ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` + ValidatorSrcAddr sdk.ValAddress `json:"validator_src_addr"` + ValidatorDstAddr sdk.ValAddress `json:"validator_dst_addr"` SharesAmount sdk.Dec `json:"shares_amount"` } -func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate { +func NewMsgBeginRedelegate(delAddr sdk.AccAddress, valSrcAddr, + valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) MsgBeginRedelegate { return MsgBeginRedelegate{ - DelegatorAddr: delegatorAddr, - ValidatorSrcAddr: validatorSrcAddr, - ValidatorDstAddr: validatorDstAddr, + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, SharesAmount: sharesAmount, } } @@ -227,8 +226,8 @@ func (msg MsgBeginRedelegate) GetSigners() []sdk.AccAddress { func (msg MsgBeginRedelegate) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` - ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` + ValidatorSrcAddr sdk.ValAddress `json:"validator_src_addr"` + ValidatorDstAddr sdk.ValAddress `json:"validator_dst_addr"` SharesAmount string `json:"shares"` }{ DelegatorAddr: msg.DelegatorAddr, @@ -262,17 +261,15 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error { // MsgDelegate - struct for bonding transactions type MsgCompleteRedelegate struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorSrcAddr sdk.AccAddress `json:"validator_source_addr"` - ValidatorDstAddr sdk.AccAddress `json:"validator_destination_addr"` + ValidatorSrcAddr sdk.ValAddress `json:"validator_source_addr"` + ValidatorDstAddr sdk.ValAddress `json:"validator_destination_addr"` } -func NewMsgCompleteRedelegate(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.AccAddress) MsgCompleteRedelegate { - +func NewMsgCompleteRedelegate(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) MsgCompleteRedelegate { return MsgCompleteRedelegate{ - DelegatorAddr: delegatorAddr, - ValidatorSrcAddr: validatorSrcAddr, - ValidatorDstAddr: validatorDstAddr, + DelegatorAddr: delAddr, + ValidatorSrcAddr: valSrcAddr, + ValidatorDstAddr: valDstAddr, } } @@ -310,14 +307,14 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error { // MsgBeginUnbonding - struct for unbonding transactions type MsgBeginUnbonding struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` SharesAmount sdk.Dec `json:"shares_amount"` } -func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginUnbonding { +func NewMsgBeginUnbonding(delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) MsgBeginUnbonding { return MsgBeginUnbonding{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, SharesAmount: sharesAmount, } } @@ -330,7 +327,7 @@ func (msg MsgBeginUnbonding) GetSigners() []sdk.AccAddress { return []sdk.AccAdd func (msg MsgBeginUnbonding) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` SharesAmount string `json:"shares_amount"` }{ DelegatorAddr: msg.DelegatorAddr, @@ -360,13 +357,13 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error { // MsgCompleteUnbonding - struct for unbonding transactions type MsgCompleteUnbonding struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - ValidatorAddr sdk.AccAddress `json:"validator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` } -func NewMsgCompleteUnbonding(delegatorAddr, validatorAddr sdk.AccAddress) MsgCompleteUnbonding { +func NewMsgCompleteUnbonding(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgCompleteUnbonding { return MsgCompleteUnbonding{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, } } diff --git a/x/stake/types/msg_test.go b/x/stake/types/msg_test.go index 2be34fb207..eb66c04220 100644 --- a/x/stake/types/msg_test.go +++ b/x/stake/types/msg_test.go @@ -19,7 +19,7 @@ var ( func TestMsgCreateValidator(t *testing.T) { tests := []struct { name, moniker, identity, website, details string - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress pubkey crypto.PubKey bond sdk.Coin expectPass bool @@ -49,7 +49,7 @@ func TestMsgCreateValidator(t *testing.T) { func TestMsgEditValidator(t *testing.T) { tests := []struct { name, moniker, identity, website, details string - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress expectPass bool }{ {"basic good", "a", "b", "c", "d", addr1, true}, @@ -74,20 +74,20 @@ func TestMsgCreateValidatorOnBehalfOf(t *testing.T) { tests := []struct { name, moniker, identity, website, details string delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress validatorPubKey crypto.PubKey bond sdk.Coin expectPass bool }{ - {"basic good", "a", "b", "c", "d", addr1, addr2, pk2, coinPos, true}, - {"partial description", "", "", "c", "", addr1, addr2, pk2, coinPos, true}, - {"empty description", "", "", "", "", addr1, addr2, pk2, coinPos, false}, - {"empty delegator address", "a", "b", "c", "d", emptyAddr, addr2, pk2, coinPos, false}, - {"empty validator address", "a", "b", "c", "d", addr1, emptyAddr, pk2, coinPos, false}, - {"empty pubkey", "a", "b", "c", "d", addr1, addr2, emptyPubkey, coinPos, true}, - {"empty bond", "a", "b", "c", "d", addr1, addr2, pk2, coinZero, false}, - {"negative bond", "a", "b", "c", "d", addr1, addr2, pk2, coinNeg, false}, - {"negative bond", "a", "b", "c", "d", addr1, addr2, pk2, coinNeg, false}, + {"basic good", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, + {"partial description", "", "", "c", "", sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, + {"empty description", "", "", "", "", sdk.AccAddress(addr1), addr2, pk2, coinPos, false}, + {"empty delegator address", "a", "b", "c", "d", sdk.AccAddress(emptyAddr), addr2, pk2, coinPos, false}, + {"empty validator address", "a", "b", "c", "d", sdk.AccAddress(addr1), emptyAddr, pk2, coinPos, false}, + {"empty pubkey", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, emptyPubkey, coinPos, true}, + {"empty bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinZero, false}, + {"negative bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, + {"negative bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, } for _, tc := range tests { @@ -102,11 +102,11 @@ func TestMsgCreateValidatorOnBehalfOf(t *testing.T) { msg := NewMsgCreateValidator(addr1, pk1, coinPos, Description{}) addrs := msg.GetSigners() - require.Equal(t, []sdk.AccAddress{addr1}, addrs, "Signers on default msg is wrong") + require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr1)}, addrs, "Signers on default msg is wrong") - msg = NewMsgCreateValidatorOnBehalfOf(addr2, addr1, pk1, coinPos, Description{}) + msg = NewMsgCreateValidatorOnBehalfOf(sdk.AccAddress(addr2), addr1, pk1, coinPos, Description{}) addrs = msg.GetSigners() - require.Equal(t, []sdk.AccAddress{addr2, addr1}, addrs, "Signers for onbehalfof msg is wrong") + require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr2), sdk.AccAddress(addr1)}, addrs, "Signers for onbehalfof msg is wrong") } // test ValidateBasic for MsgDelegate @@ -114,16 +114,16 @@ func TestMsgDelegate(t *testing.T) { tests := []struct { name string delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress bond sdk.Coin expectPass bool }{ - {"basic good", addr1, addr2, coinPos, true}, - {"self bond", addr1, addr1, coinPos, true}, - {"empty delegator", emptyAddr, addr1, coinPos, false}, - {"empty validator", addr1, emptyAddr, coinPos, false}, - {"empty bond", addr1, addr2, coinZero, false}, - {"negative bond", addr1, addr2, coinNeg, false}, + {"basic good", sdk.AccAddress(addr1), addr2, coinPos, true}, + {"self bond", sdk.AccAddress(addr1), addr1, coinPos, true}, + {"empty delegator", sdk.AccAddress(emptyAddr), addr1, coinPos, false}, + {"empty validator", sdk.AccAddress(addr1), emptyAddr, coinPos, false}, + {"empty bond", sdk.AccAddress(addr1), addr2, coinZero, false}, + {"negative bond", sdk.AccAddress(addr1), addr2, coinNeg, false}, } for _, tc := range tests { @@ -141,17 +141,17 @@ func TestMsgBeginRedelegate(t *testing.T) { tests := []struct { name string delegatorAddr sdk.AccAddress - validatorSrcAddr sdk.AccAddress - validatorDstAddr sdk.AccAddress + validatorSrcAddr sdk.ValAddress + validatorDstAddr sdk.ValAddress sharesAmount sdk.Dec expectPass bool }{ - {"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true}, - {"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false}, - {"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false}, - {"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false}, - {"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false}, - {"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false}, + {"regular", sdk.AccAddress(addr1), addr2, addr3, sdk.NewDecWithPrec(1, 1), true}, + {"negative decimal", sdk.AccAddress(addr1), addr2, addr3, sdk.NewDecWithPrec(-1, 1), false}, + {"zero amount", sdk.AccAddress(addr1), addr2, addr3, sdk.ZeroDec(), false}, + {"empty delegator", sdk.AccAddress(emptyAddr), addr1, addr3, sdk.NewDecWithPrec(1, 1), false}, + {"empty source validator", sdk.AccAddress(addr1), emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false}, + {"empty destination validator", sdk.AccAddress(addr1), addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false}, } for _, tc := range tests { @@ -169,14 +169,14 @@ func TestMsgCompleteRedelegate(t *testing.T) { tests := []struct { name string delegatorAddr sdk.AccAddress - validatorSrcAddr sdk.AccAddress - validatorDstAddr sdk.AccAddress + validatorSrcAddr sdk.ValAddress + validatorDstAddr sdk.ValAddress expectPass bool }{ - {"regular", addr1, addr2, addr3, true}, - {"empty delegator", emptyAddr, addr1, addr3, false}, - {"empty source validator", addr1, emptyAddr, addr3, false}, - {"empty destination validator", addr1, addr2, emptyAddr, false}, + {"regular", sdk.AccAddress(addr1), addr2, addr3, true}, + {"empty delegator", sdk.AccAddress(emptyAddr), addr1, addr3, false}, + {"empty source validator", sdk.AccAddress(addr1), emptyAddr, addr3, false}, + {"empty destination validator", sdk.AccAddress(addr1), addr2, emptyAddr, false}, } for _, tc := range tests { @@ -194,15 +194,15 @@ func TestMsgBeginUnbonding(t *testing.T) { tests := []struct { name string delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress sharesAmount sdk.Dec expectPass bool }{ - {"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true}, - {"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false}, - {"zero amount", addr1, addr2, sdk.ZeroDec(), false}, - {"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false}, - {"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false}, + {"regular", sdk.AccAddress(addr1), addr2, sdk.NewDecWithPrec(1, 1), true}, + {"negative decimal", sdk.AccAddress(addr1), addr2, sdk.NewDecWithPrec(-1, 1), false}, + {"zero amount", sdk.AccAddress(addr1), addr2, sdk.ZeroDec(), false}, + {"empty delegator", sdk.AccAddress(emptyAddr), addr1, sdk.NewDecWithPrec(1, 1), false}, + {"empty validator", sdk.AccAddress(addr1), emptyAddr, sdk.NewDecWithPrec(1, 1), false}, } for _, tc := range tests { @@ -220,12 +220,12 @@ func TestMsgCompleteUnbonding(t *testing.T) { tests := []struct { name string delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress expectPass bool }{ - {"regular", addr1, addr2, true}, - {"empty delegator", emptyAddr, addr1, false}, - {"empty validator", addr1, emptyAddr, false}, + {"regular", sdk.AccAddress(addr1), addr2, true}, + {"empty delegator", sdk.AccAddress(emptyAddr), addr1, false}, + {"empty validator", sdk.AccAddress(addr1), emptyAddr, false}, } for _, tc := range tests { diff --git a/x/stake/types/test_utils.go b/x/stake/types/test_utils.go index 02c4d4fca9..b9d77ce9f5 100644 --- a/x/stake/types/test_utils.go +++ b/x/stake/types/test_utils.go @@ -10,10 +10,10 @@ var ( pk1 = ed25519.GenPrivKey().PubKey() pk2 = ed25519.GenPrivKey().PubKey() pk3 = ed25519.GenPrivKey().PubKey() - addr1 = sdk.AccAddress(pk1.Address()) - addr2 = sdk.AccAddress(pk2.Address()) - addr3 = sdk.AccAddress(pk3.Address()) + addr1 = sdk.ValAddress(pk1.Address()) + addr2 = sdk.ValAddress(pk2.Address()) + addr3 = sdk.ValAddress(pk3.Address()) - emptyAddr sdk.AccAddress + emptyAddr sdk.ValAddress emptyPubkey crypto.PubKey ) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 9d04357528..2cb952db28 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -20,7 +20,7 @@ import ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Validator struct { - Operator sdk.AccAddress `json:"operator"` // sender of BondTx - UnbondTx returns here + Operator sdk.ValAddress `json:"operator"` // sender of BondTx - UnbondTx returns here PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? @@ -43,7 +43,7 @@ type Validator struct { } // NewValidator - initialize a new validator -func NewValidator(operator sdk.AccAddress, pubKey crypto.PubKey, description Description) Validator { +func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Description) Validator { return Validator{ Operator: operator, PubKey: pubKey, @@ -147,14 +147,14 @@ func UnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) (validator // validator. An error is returned if the operator or the operator's public key // cannot be converted to Bech32 format. func (v Validator) HumanReadableString() (string, error) { - bechVal, err := sdk.Bech32ifyValPub(v.PubKey) + bechConsPubKey, err := sdk.Bech32ifyConsPub(v.PubKey) if err != nil { return "", err } resp := "Validator \n" resp += fmt.Sprintf("Operator: %s\n", v.Operator) - resp += fmt.Sprintf("Validator: %s\n", bechVal) + resp += fmt.Sprintf("Validator: %s\n", bechConsPubKey) resp += fmt.Sprintf("Jailed: %v\n", v.Jailed) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String()) @@ -175,7 +175,7 @@ func (v Validator) HumanReadableString() (string, error) { // validator struct for bech output type BechValidator struct { - Operator sdk.AccAddress `json:"operator"` // in bech32 + Operator sdk.ValAddress `json:"operator"` // in bech32 PubKey string `json:"pub_key"` // in bech32 Jailed bool `json:"jailed"` // has the validator been jailed from bonded status? @@ -199,14 +199,14 @@ type BechValidator struct { // get the bech validator from the the regular validator func (v Validator) Bech32Validator() (BechValidator, error) { - bechValPubkey, err := sdk.Bech32ifyValPub(v.PubKey) + bechConsPubKey, err := sdk.Bech32ifyConsPub(v.PubKey) if err != nil { return BechValidator{}, err } return BechValidator{ Operator: v.Operator, - PubKey: bechValPubkey, + PubKey: bechConsPubKey, Jailed: v.Jailed, Status: v.Status, @@ -432,7 +432,7 @@ var _ sdk.Validator = Validator{} func (v Validator) GetJailed() bool { return v.Jailed } func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOperator() sdk.AccAddress { return v.Operator } +func (v Validator) GetOperator() sdk.ValAddress { return v.Operator } func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } From df3345249074edefd15fd168d157fa7db85d192e Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Fri, 31 Aug 2018 00:10:51 -0400 Subject: [PATCH 46/47] Merge PR #2176: Ensure Legacy Validator Delegation Invariants * Test and allow jailed validator to self-bond * Implement TestJailedValidatorDelegations * Restructure TestJailedValidatorDelegations * Add Delegation to Validator type and update handleMsgUnjail accordingly * Update ErrMissingSelfDelegation error message * Update democoin mock validator set impl * Update pending log * Add comment to ValidatorSet --- PENDING.md | 1 + examples/democoin/mock/validator.go | 5 ++ types/stake.go | 4 ++ x/slashing/errors.go | 14 ++++- x/slashing/handler.go | 15 +++-- x/slashing/handler_test.go | 60 +++++++++++++++++++ x/slashing/test_common.go | 11 +++- x/stake/handler.go | 8 ++- x/stake/handler_test.go | 91 +++++++++++++++++++++++++++++ x/stake/keeper/delegation.go | 3 +- 10 files changed, 199 insertions(+), 13 deletions(-) diff --git a/PENDING.md b/PENDING.md index 832f25e8f4..3843be5fd5 100644 --- a/PENDING.md +++ b/PENDING.md @@ -73,6 +73,7 @@ IMPROVEMENTS * Gaia * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) + * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index f937e45dcc..3e552d44ad 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -135,3 +135,8 @@ func (vs *ValidatorSet) Jail(ctx sdk.Context, pubkey crypto.PubKey) { func (vs *ValidatorSet) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { panic("not implemented") } + +// Implements sdk.ValidatorSet +func (vs *ValidatorSet) Delegation(ctx sdk.Context, addrDel, addrVal sdk.AccAddress) sdk.Delegation { + panic("not implemented") +} diff --git a/types/stake.go b/types/stake.go index f411251775..71386959e4 100644 --- a/types/stake.go +++ b/types/stake.go @@ -75,6 +75,10 @@ type ValidatorSet interface { Slash(Context, crypto.PubKey, int64, int64, Dec) Jail(Context, crypto.PubKey) // jail a validator Unjail(Context, crypto.PubKey) // unjail a validator + + // Delegation allows for getting a particular delegation for a given validator + // and delegator outside the scope of the staking module. + Delegation(Context, AccAddress, AccAddress) Delegation } //_______________________________________________________________________________ diff --git a/x/slashing/errors.go b/x/slashing/errors.go index 4573d5e145..77cb2d28e3 100644 --- a/x/slashing/errors.go +++ b/x/slashing/errors.go @@ -12,20 +12,28 @@ const ( // Default slashing codespace DefaultCodespace sdk.CodespaceType = 10 - CodeInvalidValidator CodeType = 101 - CodeValidatorJailed CodeType = 102 - CodeValidatorNotJailed CodeType = 103 + CodeInvalidValidator CodeType = 101 + CodeValidatorJailed CodeType = 102 + CodeValidatorNotJailed CodeType = 103 + CodeMissingSelfDelegation CodeType = 104 ) func ErrNoValidatorForAddress(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "that address is not associated with any known validator") } + func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") } + func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeValidatorJailed, "validator still jailed, cannot yet be unjailed") } + func ErrValidatorNotJailed(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeValidatorNotJailed, "validator not jailed, cannot be unjailed") } + +func ErrMissingSelfDelegation(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeMissingSelfDelegation, "validator has no self-delegation; cannot be unjailed") +} diff --git a/x/slashing/handler.go b/x/slashing/handler.go index d79ea73c2d..94cfa41ff7 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -19,35 +19,38 @@ func NewHandler(k Keeper) sdk.Handler { // Validators must submit a transaction to unjail itself after // having been jailed (and thus unbonded) for downtime func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { - - // Validator must exist validator := k.validatorSet.Validator(ctx, msg.ValidatorAddr) if validator == nil { return ErrNoValidatorForAddress(k.codespace).Result() } + // cannot be unjailed if no self-delegation exists + selfDel := k.validatorSet.Delegation(ctx, msg.ValidatorAddr, msg.ValidatorAddr) + if selfDel == nil { + return ErrMissingSelfDelegation(k.codespace).Result() + } + if !validator.GetJailed() { return ErrValidatorNotJailed(k.codespace).Result() } addr := sdk.ValAddress(validator.GetPubKey().Address()) - // Signing info must exist info, found := k.getValidatorSigningInfo(ctx, addr) if !found { return ErrNoValidatorForAddress(k.codespace).Result() } - // Cannot be unjailed until out of jail + // cannot be unjailed until out of jail if ctx.BlockHeader().Time.Before(info.JailedUntil) { return ErrValidatorJailed(k.codespace).Result() } - // Update the starting height (so the validator can't be immediately jailed again) + // update the starting height so the validator can't be immediately jailed + // again info.StartHeight = ctx.BlockHeight() k.setValidatorSigningInfo(ctx, addr, info) - // Unjail the validator k.validatorSet.Unjail(ctx, validator.GetPubKey()) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 8e3b719f49..cb764ec696 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -2,6 +2,7 @@ package slashing import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -27,3 +28,62 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { require.False(t, got.IsOK(), "allowed unjail of non-jailed validator") require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotJailed), got.Code) } + +func TestJailedValidatorDelegations(t *testing.T) { + ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t) + + stakeParams := stakeKeeper.GetParams(ctx) + stakeParams.UnbondingTime = 0 + stakeKeeper.SetParams(ctx, stakeParams) + + // create a validator + amount := int64(10) + valAddr, valPubKey, bondAmount := addrs[0], pks[0], sdk.NewInt(amount) + msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) + got := stake.NewHandler(stakeKeeper)(ctx, msgCreateVal) + require.True(t, got.IsOK(), "expected create validator msg to be ok, got: %v", got) + + // set dummy signing info + newInfo := ValidatorSigningInfo{ + StartHeight: int64(0), + IndexOffset: int64(0), + JailedUntil: time.Unix(0, 0), + SignedBlocksCounter: int64(0), + } + slashingKeeper.setValidatorSigningInfo(ctx, sdk.ValAddress(valAddr), newInfo) + + // delegate tokens to the validator + delAddr := addrs[1] + msgDelegate := newTestMsgDelegate(delAddr, valAddr, bondAmount) + got = stake.NewHandler(stakeKeeper)(ctx, msgDelegate) + require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + + unbondShares := sdk.NewDec(10) + + // unbond validator total self-delegations (which should jail the validator) + msgBeginUnbonding := stake.NewMsgBeginUnbonding(valAddr, valAddr, unbondShares) + got = stake.NewHandler(stakeKeeper)(ctx, msgBeginUnbonding) + require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got: %v", got) + + msgCompleteUnbonding := stake.NewMsgCompleteUnbonding(valAddr, valAddr) + got = stake.NewHandler(stakeKeeper)(ctx, msgCompleteUnbonding) + require.True(t, got.IsOK(), "expected complete unbonding validator msg to be ok, got: %v", got) + + // verify validator still exists and is jailed + validator, found := stakeKeeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.True(t, validator.GetJailed()) + + // verify the validator cannot unjail itself + got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) + require.False(t, got.IsOK(), "expected jailed validator to not be able to unjail, got: %v", got) + + // self-delegate to validator + msgSelfDelegate := newTestMsgDelegate(valAddr, valAddr, bondAmount) + got = stake.NewHandler(stakeKeeper)(ctx, msgSelfDelegate) + require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) + + // verify the validator can now unjail itself + got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) + require.True(t, got.IsOK(), "expected jailed validator to be able to unjail, got: %v", got) +} diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 1053823786..d051a8cbc5 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "os" "testing" + "time" "github.com/stretchr/testify/require" @@ -61,7 +62,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) err := ms.LoadLatestVersion() require.Nil(t, err) - ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewTMLogger(os.Stdout)) + ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout)) cdc := createTestCodec() accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount) ck := bank.NewKeeper(accountMapper) @@ -108,3 +109,11 @@ func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt Delegation: sdk.Coin{"steak", amt}, } } + +func newTestMsgDelegate(delAddr, valAddr sdk.AccAddress, delAmount sdk.Int) stake.MsgDelegate { + return stake.MsgDelegate{ + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, + Delegation: sdk.Coin{"steak", delAmount}, + } +} diff --git a/x/stake/handler.go b/x/stake/handler.go index c8be6a835a..4b478fffd7 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,6 +1,7 @@ package stake import ( + "bytes" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -128,17 +129,19 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe } func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result { - validator, found := k.GetValidator(ctx, msg.ValidatorAddr) if !found { return ErrNoValidatorFound(k.Codespace()).Result() } + if msg.Delegation.Denom != k.GetParams(ctx).BondDenom { return ErrBadDenom(k.Codespace()).Result() } - if validator.Jailed { + + if validator.Jailed && !bytes.Equal(validator.Operator, msg.DelegatorAddr) { return ErrValidatorJailed(k.Codespace()).Result() } + _, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true) if err != nil { return err.Result() @@ -149,6 +152,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) tags.Delegator, []byte(msg.DelegatorAddr.String()), tags.DstValidator, []byte(msg.ValidatorAddr.String()), ) + return sdk.Result{ Tags: tags, } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index f7d01bcfc7..a5b70e054d 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -193,6 +193,97 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { require.False(t, got.IsOK(), "%v", got) } +func TestLegacyValidatorDelegations(t *testing.T) { + ctx, _, keeper := keep.CreateTestInput(t, false, int64(1000)) + setInstantUnbondPeriod(keeper, ctx) + + bondAmount := int64(10) + valAddr, valPubKey := keep.Addrs[0], keep.PKs[0] + delAddr := keep.Addrs[1] + + // create validator + msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) + got := handleMsgCreateValidator(ctx, msgCreateVal, keeper) + require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got) + + // verify the validator exists and has the correct attributes + validator, found := keeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.Equal(t, sdk.Bonded, validator.Status) + require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt64()) + require.Equal(t, bondAmount, validator.BondedTokens().RoundInt64()) + + // delegate tokens to the validator + msgDelegate := newTestMsgDelegate(delAddr, valAddr, bondAmount) + got = handleMsgDelegate(ctx, msgDelegate, keeper) + require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + + // verify validator bonded shares + validator, found = keeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.Equal(t, bondAmount*2, validator.DelegatorShares.RoundInt64()) + require.Equal(t, bondAmount*2, validator.BondedTokens().RoundInt64()) + + // unbond validator total self-delegations (which should jail the validator) + unbondShares := sdk.NewDec(10) + msgBeginUnbonding := NewMsgBeginUnbonding(valAddr, valAddr, unbondShares) + msgCompleteUnbonding := NewMsgCompleteUnbonding(valAddr, valAddr) + + got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) + require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got) + + got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper) + require.True(t, got.IsOK(), "expected complete unbonding validator msg to be ok, got %v", got) + + // verify the validator record still exists, is jailed, and has correct tokens + validator, found = keeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.True(t, validator.Jailed) + require.Equal(t, sdk.NewDec(10), validator.Tokens) + + // verify delegation still exists + bond, found := keeper.GetDelegation(ctx, delAddr, valAddr) + require.True(t, found) + require.Equal(t, bondAmount, bond.Shares.RoundInt64()) + require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt64()) + + // verify a delegator cannot create a new delegation to the now jailed validator + msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) + got = handleMsgDelegate(ctx, msgDelegate, keeper) + require.False(t, got.IsOK(), "expected delegation to not be ok, got %v", got) + + // verify the validator can still self-delegate + msgSelfDelegate := newTestMsgDelegate(valAddr, valAddr, bondAmount) + got = handleMsgDelegate(ctx, msgSelfDelegate, keeper) + require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) + + // verify validator bonded shares + validator, found = keeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.Equal(t, bondAmount*2, validator.DelegatorShares.RoundInt64()) + require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64()) + + // unjail the validator now that is has non-zero self-delegated shares + keeper.Unjail(ctx, valPubKey) + + // verify the validator can now accept delegations + msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) + got = handleMsgDelegate(ctx, msgDelegate, keeper) + require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + + // verify validator bonded shares + validator, found = keeper.GetValidator(ctx, valAddr) + require.True(t, found) + require.Equal(t, bondAmount*3, validator.DelegatorShares.RoundInt64()) + require.Equal(t, bondAmount*3, validator.Tokens.RoundInt64()) + + // verify new delegation + bond, found = keeper.GetDelegation(ctx, delAddr, valAddr) + require.True(t, found) + require.Equal(t, bondAmount*2, bond.Shares.RoundInt64()) + require.Equal(t, bondAmount*3, validator.DelegatorShares.RoundInt64()) +} + func TestIncrementsMsgDelegate(t *testing.T) { initBond := int64(1000) ctx, accMapper, keeper := keep.CreateTestInput(t, false, initBond) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 9f7a402fc2..2c997b4633 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -288,6 +288,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA if bytes.Equal(delegation.DelegatorAddr, validator.Operator) && validator.Jailed == false { validator.Jailed = true } + k.RemoveDelegation(ctx, delegation) } else { // Update height @@ -307,7 +308,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.Operator) } - return + return amount, nil } //______________________________________________________________________________________________________ From ee0434e5a7d724f5a14056b8fd96d5327dbaf93c Mon Sep 17 00:00:00 2001 From: Rigel <rigel.rozanski@gmail.com> Date: Fri, 31 Aug 2018 00:55:33 -0400 Subject: [PATCH 47/47] Revert "Merge PR #2176: Ensure Legacy Validator Delegation Invariants" (#2197) This reverts commit df3345249074edefd15fd168d157fa7db85d192e. --- PENDING.md | 1 - examples/democoin/mock/validator.go | 5 -- types/stake.go | 4 -- x/slashing/errors.go | 14 +---- x/slashing/handler.go | 15 ++--- x/slashing/handler_test.go | 60 ------------------- x/slashing/test_common.go | 11 +--- x/stake/handler.go | 8 +-- x/stake/handler_test.go | 91 ----------------------------- x/stake/keeper/delegation.go | 3 +- 10 files changed, 13 insertions(+), 199 deletions(-) diff --git a/PENDING.md b/PENDING.md index 3843be5fd5..832f25e8f4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -73,7 +73,6 @@ IMPROVEMENTS * Gaia * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) - * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 3e552d44ad..f937e45dcc 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -135,8 +135,3 @@ func (vs *ValidatorSet) Jail(ctx sdk.Context, pubkey crypto.PubKey) { func (vs *ValidatorSet) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { panic("not implemented") } - -// Implements sdk.ValidatorSet -func (vs *ValidatorSet) Delegation(ctx sdk.Context, addrDel, addrVal sdk.AccAddress) sdk.Delegation { - panic("not implemented") -} diff --git a/types/stake.go b/types/stake.go index 71386959e4..f411251775 100644 --- a/types/stake.go +++ b/types/stake.go @@ -75,10 +75,6 @@ type ValidatorSet interface { Slash(Context, crypto.PubKey, int64, int64, Dec) Jail(Context, crypto.PubKey) // jail a validator Unjail(Context, crypto.PubKey) // unjail a validator - - // Delegation allows for getting a particular delegation for a given validator - // and delegator outside the scope of the staking module. - Delegation(Context, AccAddress, AccAddress) Delegation } //_______________________________________________________________________________ diff --git a/x/slashing/errors.go b/x/slashing/errors.go index 77cb2d28e3..4573d5e145 100644 --- a/x/slashing/errors.go +++ b/x/slashing/errors.go @@ -12,28 +12,20 @@ const ( // Default slashing codespace DefaultCodespace sdk.CodespaceType = 10 - CodeInvalidValidator CodeType = 101 - CodeValidatorJailed CodeType = 102 - CodeValidatorNotJailed CodeType = 103 - CodeMissingSelfDelegation CodeType = 104 + CodeInvalidValidator CodeType = 101 + CodeValidatorJailed CodeType = 102 + CodeValidatorNotJailed CodeType = 103 ) func ErrNoValidatorForAddress(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "that address is not associated with any known validator") } - func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") } - func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeValidatorJailed, "validator still jailed, cannot yet be unjailed") } - func ErrValidatorNotJailed(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeValidatorNotJailed, "validator not jailed, cannot be unjailed") } - -func ErrMissingSelfDelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeMissingSelfDelegation, "validator has no self-delegation; cannot be unjailed") -} diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 94cfa41ff7..d79ea73c2d 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -19,38 +19,35 @@ func NewHandler(k Keeper) sdk.Handler { // Validators must submit a transaction to unjail itself after // having been jailed (and thus unbonded) for downtime func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { + + // Validator must exist validator := k.validatorSet.Validator(ctx, msg.ValidatorAddr) if validator == nil { return ErrNoValidatorForAddress(k.codespace).Result() } - // cannot be unjailed if no self-delegation exists - selfDel := k.validatorSet.Delegation(ctx, msg.ValidatorAddr, msg.ValidatorAddr) - if selfDel == nil { - return ErrMissingSelfDelegation(k.codespace).Result() - } - if !validator.GetJailed() { return ErrValidatorNotJailed(k.codespace).Result() } addr := sdk.ValAddress(validator.GetPubKey().Address()) + // Signing info must exist info, found := k.getValidatorSigningInfo(ctx, addr) if !found { return ErrNoValidatorForAddress(k.codespace).Result() } - // cannot be unjailed until out of jail + // Cannot be unjailed until out of jail if ctx.BlockHeader().Time.Before(info.JailedUntil) { return ErrValidatorJailed(k.codespace).Result() } - // update the starting height so the validator can't be immediately jailed - // again + // Update the starting height (so the validator can't be immediately jailed again) info.StartHeight = ctx.BlockHeight() k.setValidatorSigningInfo(ctx, addr, info) + // Unjail the validator k.validatorSet.Unjail(ctx, validator.GetPubKey()) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index cb764ec696..8e3b719f49 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -2,7 +2,6 @@ package slashing import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -28,62 +27,3 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { require.False(t, got.IsOK(), "allowed unjail of non-jailed validator") require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeValidatorNotJailed), got.Code) } - -func TestJailedValidatorDelegations(t *testing.T) { - ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t) - - stakeParams := stakeKeeper.GetParams(ctx) - stakeParams.UnbondingTime = 0 - stakeKeeper.SetParams(ctx, stakeParams) - - // create a validator - amount := int64(10) - valAddr, valPubKey, bondAmount := addrs[0], pks[0], sdk.NewInt(amount) - msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) - got := stake.NewHandler(stakeKeeper)(ctx, msgCreateVal) - require.True(t, got.IsOK(), "expected create validator msg to be ok, got: %v", got) - - // set dummy signing info - newInfo := ValidatorSigningInfo{ - StartHeight: int64(0), - IndexOffset: int64(0), - JailedUntil: time.Unix(0, 0), - SignedBlocksCounter: int64(0), - } - slashingKeeper.setValidatorSigningInfo(ctx, sdk.ValAddress(valAddr), newInfo) - - // delegate tokens to the validator - delAddr := addrs[1] - msgDelegate := newTestMsgDelegate(delAddr, valAddr, bondAmount) - got = stake.NewHandler(stakeKeeper)(ctx, msgDelegate) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) - - unbondShares := sdk.NewDec(10) - - // unbond validator total self-delegations (which should jail the validator) - msgBeginUnbonding := stake.NewMsgBeginUnbonding(valAddr, valAddr, unbondShares) - got = stake.NewHandler(stakeKeeper)(ctx, msgBeginUnbonding) - require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got: %v", got) - - msgCompleteUnbonding := stake.NewMsgCompleteUnbonding(valAddr, valAddr) - got = stake.NewHandler(stakeKeeper)(ctx, msgCompleteUnbonding) - require.True(t, got.IsOK(), "expected complete unbonding validator msg to be ok, got: %v", got) - - // verify validator still exists and is jailed - validator, found := stakeKeeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.True(t, validator.GetJailed()) - - // verify the validator cannot unjail itself - got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) - require.False(t, got.IsOK(), "expected jailed validator to not be able to unjail, got: %v", got) - - // self-delegate to validator - msgSelfDelegate := newTestMsgDelegate(valAddr, valAddr, bondAmount) - got = stake.NewHandler(stakeKeeper)(ctx, msgSelfDelegate) - require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) - - // verify the validator can now unjail itself - got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) - require.True(t, got.IsOK(), "expected jailed validator to be able to unjail, got: %v", got) -} diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index d051a8cbc5..1053823786 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "os" "testing" - "time" "github.com/stretchr/testify/require" @@ -62,7 +61,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) err := ms.LoadLatestVersion() require.Nil(t, err) - ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout)) + ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewTMLogger(os.Stdout)) cdc := createTestCodec() accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount) ck := bank.NewKeeper(accountMapper) @@ -109,11 +108,3 @@ func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt Delegation: sdk.Coin{"steak", amt}, } } - -func newTestMsgDelegate(delAddr, valAddr sdk.AccAddress, delAmount sdk.Int) stake.MsgDelegate { - return stake.MsgDelegate{ - DelegatorAddr: delAddr, - ValidatorAddr: valAddr, - Delegation: sdk.Coin{"steak", delAmount}, - } -} diff --git a/x/stake/handler.go b/x/stake/handler.go index 4b478fffd7..c8be6a835a 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,7 +1,6 @@ package stake import ( - "bytes" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -129,19 +128,17 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe } func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result { + validator, found := k.GetValidator(ctx, msg.ValidatorAddr) if !found { return ErrNoValidatorFound(k.Codespace()).Result() } - if msg.Delegation.Denom != k.GetParams(ctx).BondDenom { return ErrBadDenom(k.Codespace()).Result() } - - if validator.Jailed && !bytes.Equal(validator.Operator, msg.DelegatorAddr) { + if validator.Jailed { return ErrValidatorJailed(k.Codespace()).Result() } - _, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true) if err != nil { return err.Result() @@ -152,7 +149,6 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) tags.Delegator, []byte(msg.DelegatorAddr.String()), tags.DstValidator, []byte(msg.ValidatorAddr.String()), ) - return sdk.Result{ Tags: tags, } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index a5b70e054d..f7d01bcfc7 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -193,97 +193,6 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { require.False(t, got.IsOK(), "%v", got) } -func TestLegacyValidatorDelegations(t *testing.T) { - ctx, _, keeper := keep.CreateTestInput(t, false, int64(1000)) - setInstantUnbondPeriod(keeper, ctx) - - bondAmount := int64(10) - valAddr, valPubKey := keep.Addrs[0], keep.PKs[0] - delAddr := keep.Addrs[1] - - // create validator - msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) - got := handleMsgCreateValidator(ctx, msgCreateVal, keeper) - require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got) - - // verify the validator exists and has the correct attributes - validator, found := keeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.Equal(t, sdk.Bonded, validator.Status) - require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt64()) - require.Equal(t, bondAmount, validator.BondedTokens().RoundInt64()) - - // delegate tokens to the validator - msgDelegate := newTestMsgDelegate(delAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) - - // verify validator bonded shares - validator, found = keeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.Equal(t, bondAmount*2, validator.DelegatorShares.RoundInt64()) - require.Equal(t, bondAmount*2, validator.BondedTokens().RoundInt64()) - - // unbond validator total self-delegations (which should jail the validator) - unbondShares := sdk.NewDec(10) - msgBeginUnbonding := NewMsgBeginUnbonding(valAddr, valAddr, unbondShares) - msgCompleteUnbonding := NewMsgCompleteUnbonding(valAddr, valAddr) - - got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) - require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got) - - got = handleMsgCompleteUnbonding(ctx, msgCompleteUnbonding, keeper) - require.True(t, got.IsOK(), "expected complete unbonding validator msg to be ok, got %v", got) - - // verify the validator record still exists, is jailed, and has correct tokens - validator, found = keeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.True(t, validator.Jailed) - require.Equal(t, sdk.NewDec(10), validator.Tokens) - - // verify delegation still exists - bond, found := keeper.GetDelegation(ctx, delAddr, valAddr) - require.True(t, found) - require.Equal(t, bondAmount, bond.Shares.RoundInt64()) - require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt64()) - - // verify a delegator cannot create a new delegation to the now jailed validator - msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.False(t, got.IsOK(), "expected delegation to not be ok, got %v", got) - - // verify the validator can still self-delegate - msgSelfDelegate := newTestMsgDelegate(valAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgSelfDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) - - // verify validator bonded shares - validator, found = keeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.Equal(t, bondAmount*2, validator.DelegatorShares.RoundInt64()) - require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64()) - - // unjail the validator now that is has non-zero self-delegated shares - keeper.Unjail(ctx, valPubKey) - - // verify the validator can now accept delegations - msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) - - // verify validator bonded shares - validator, found = keeper.GetValidator(ctx, valAddr) - require.True(t, found) - require.Equal(t, bondAmount*3, validator.DelegatorShares.RoundInt64()) - require.Equal(t, bondAmount*3, validator.Tokens.RoundInt64()) - - // verify new delegation - bond, found = keeper.GetDelegation(ctx, delAddr, valAddr) - require.True(t, found) - require.Equal(t, bondAmount*2, bond.Shares.RoundInt64()) - require.Equal(t, bondAmount*3, validator.DelegatorShares.RoundInt64()) -} - func TestIncrementsMsgDelegate(t *testing.T) { initBond := int64(1000) ctx, accMapper, keeper := keep.CreateTestInput(t, false, initBond) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 2c997b4633..9f7a402fc2 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -288,7 +288,6 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA if bytes.Equal(delegation.DelegatorAddr, validator.Operator) && validator.Jailed == false { validator.Jailed = true } - k.RemoveDelegation(ctx, delegation) } else { // Update height @@ -308,7 +307,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.Operator) } - return amount, nil + return } //______________________________________________________________________________________________________