Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
34c89f73
Unverified
Commit
34c89f73
authored
Jun 15, 2020
by
vipwzw
Committed by
GitHub
Jun 15, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #852 from caopingcp/issue774_tendermint
tendermint add aggregate signature
parents
4b5cd0a0
b23f5c28
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1635 additions
and
351 deletions
+1635
-351
go.mod
go.mod
+1
-0
go.sum
go.sum
+16
-0
chain33.test.toml
plugin/consensus/tendermint/chain33.test.toml
+19
-3
consensus_state.go
plugin/consensus/tendermint/consensus_state.go
+202
-10
node.go
plugin/consensus/tendermint/node.go
+35
-11
node_test.go
plugin/consensus/tendermint/node_test.go
+5
-5
peer_set.go
plugin/consensus/tendermint/peer_set.go
+56
-63
secret_connection.go
plugin/consensus/tendermint/secret_connection.go
+13
-11
state.go
plugin/consensus/tendermint/state.go
+1
-1
store.go
plugin/consensus/tendermint/store.go
+4
-0
tendermint.go
plugin/consensus/tendermint/tendermint.go
+50
-25
tendermint_test.go
plugin/consensus/tendermint/tendermint_test.go
+2
-3
nonePerf.go
plugin/consensus/tendermint/tools/nonePerf.go
+1
-1
block.go
plugin/consensus/tendermint/types/block.go
+40
-14
const.go
plugin/consensus/tendermint/types/const.go
+25
-1
height_vote_set.go
plugin/consensus/tendermint/types/height_vote_set.go
+24
-0
params.go
plugin/consensus/tendermint/types/params.go
+1
-1
priv_validator.go
plugin/consensus/tendermint/types/priv_validator.go
+4
-5
round_state.go
plugin/consensus/tendermint/types/round_state.go
+29
-3
signable.go
plugin/consensus/tendermint/types/signable.go
+106
-5
validator_set.go
plugin/consensus/tendermint/types/validator_set.go
+26
-5
vote_set.go
plugin/consensus/tendermint/types/vote_set.go
+154
-4
bls.go
plugin/crypto/bls/bls.go
+308
-0
bls_test.go
plugin/crypto/bls/bls_test.go
+185
-0
init.go
plugin/crypto/init/init.go
+1
-0
valnode.go
plugin/dapp/valnode/commands/valnode.go
+15
-6
exec.go
plugin/dapp/valnode/executor/exec.go
+12
-1
tendermint.proto
plugin/dapp/valnode/proto/tendermint.proto
+58
-44
tendermint.pb.go
plugin/dapp/valnode/types/tendermint.pb.go
+242
-129
No files found.
go.mod
View file @
34c89f73
...
...
@@ -23,6 +23,7 @@ require (
github.com/miguelmota/go-solidity-sha3 v0.1.0
github.com/mr-tron/base58 v1.1.3
github.com/pborman/uuid v1.2.0
github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/common v0.4.1
...
...
go.sum
View file @
34c89f73
...
...
@@ -79,6 +79,7 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
...
...
@@ -128,6 +129,7 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlespiau/covertool v0.0.0-20180314162135-b0c4c6d0583a/go.mod h1:/eQMcW3eA1bzKx23ZYI2H3tXPdJB5JWYTHzoUPBvQY4=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
...
...
@@ -192,6 +194,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/pprof v0.0.0-20190309163659-77426154d546/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
...
...
@@ -219,6 +222,7 @@ github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOo
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
...
...
@@ -430,6 +434,7 @@ github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKU
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mmcloughlin/avo v0.0.0-20190318053554-7a0eb66183da/go.mod h1:lf5GMZxA5kz8dnCweJuER5Rmbx6dDu6qvw0fO3uYKK8=
github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
...
...
@@ -493,6 +498,8 @@ github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844 h1:Yflyn+XFLEu7RPzxovgEVLP6Es8JLJrHqdXunpm2ak4=
github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
...
...
@@ -574,6 +581,7 @@ github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8/go.mod h1:XxO4hdhhrzAd+
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
...
...
@@ -610,6 +618,8 @@ go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4=
go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
...
...
@@ -617,6 +627,7 @@ golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
...
...
@@ -641,6 +652,7 @@ golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190326090315-15845e8f865b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
...
...
@@ -666,6 +678,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
...
...
@@ -685,9 +698,11 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190106171756-3ef68632349c/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190325223049-1d95b17f1b04/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
...
...
@@ -739,3 +754,4 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
plugin/consensus/tendermint/chain33.test.toml
View file @
34c89f73
...
...
@@ -43,6 +43,8 @@ dbPath="datadir/addrbook"
dbCache
=
4
grpcLogFile
=
"grpc33.log"
[p2p.sub.dht]
channel
=
123
[rpc]
jrpcBindAddr
=
"localhost:8801"
...
...
@@ -73,6 +75,7 @@ powLimitBits = "0x1f2fffff"
[consensus.sub.tendermint]
genesis
=
"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
genesisAmount
=
100000000
genesisBlockTime
=
1514533394
timeoutTxAvail
=
1000
timeoutPropose
=
1000
...
...
@@ -86,14 +89,21 @@ skipTimeoutCommit=false
createEmptyBlocks
=
true
createEmptyBlocksInterval
=
1
validatorNodes
=[
"127.0.0.1:46656"
,
"127.0.0.2:46656"
]
fastSync
=
false
# Propose阶段是否预执行区块
preExec
=
false
# 签名算法,支持"secp256k1","ed25519","sm2","bls",默认为"ed25519"
signName
=
"ed25519"
# 是否使用聚合签名,签名算法需支持该特性,比如"bls"
useAggregateSignature
=
false
[store]
name
=
"
mavl
"
name
=
"
kvmvcc
"
driver
=
"leveldb"
dbPath
=
"datadir/
mavltree
"
dbPath
=
"datadir/
kvmvcc
"
dbCache
=
128
[store.sub.
mavl
]
[store.sub.
kvmvcc
]
enableMavlPrefix
=
false
enableMVCC
=
false
...
...
@@ -126,3 +136,9 @@ signType="auth_ecdsa"
superManager
=[
"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
,
]
[metrics]
#是否使能发送metrics数据的发送
enableMetrics
=
false
#数据保存模式
dataEmitMode
=
"influxdb"
plugin/consensus/tendermint/consensus_state.go
View file @
34c89f73
...
...
@@ -31,6 +31,7 @@ var (
ErrInvalidProposalSignature
=
errors
.
New
(
"Error invalid proposal signature"
)
ErrInvalidProposalPOLRound
=
errors
.
New
(
"Error invalid proposal POL round"
)
ErrAddingVote
=
errors
.
New
(
"Error adding vote"
)
ErrAddingAggVote
=
errors
.
New
(
"Error adding aggregate vote"
)
ErrVoteHeightMismatch
=
errors
.
New
(
"Error vote height mismatch"
)
)
...
...
@@ -85,6 +86,7 @@ type ConsensusState struct {
setProposal
func
(
proposal
*
tmtypes
.
Proposal
)
error
broadcastChannel
chan
<-
MsgInfo
unicastChannel
chan
<-
MsgInfo
ourID
ID
status
uint32
// 0-stop, 1-start
quit
chan
struct
{}
...
...
@@ -131,6 +133,11 @@ func (cs *ConsensusState) SetBroadcastChannel(broadcastChannel chan<- MsgInfo) {
cs
.
broadcastChannel
=
broadcastChannel
}
// SetBroadcastChannel method
func
(
cs
*
ConsensusState
)
SetUnicastChannel
(
unicastChannel
chan
<-
MsgInfo
)
{
cs
.
unicastChannel
=
unicastChannel
}
// IsRunning method
func
(
cs
*
ConsensusState
)
IsRunning
()
bool
{
return
atomic
.
LoadUint32
(
&
cs
.
status
)
==
1
...
...
@@ -162,6 +169,15 @@ func (cs *ConsensusState) GetValidators() (int64, []*ttypes.Validator) {
return
cs
.
state
.
LastBlockHeight
,
cs
.
state
.
Validators
.
Copy
()
.
Validators
}
// GetPrivValidator returns the private validator account for signing votes.
func
(
cs
*
ConsensusState
)
GetPrivValidator
()
ttypes
.
PrivValidator
{
cs
.
mtx
.
Lock
()
defer
cs
.
mtx
.
Unlock
()
pv
:=
cs
.
privValidator
return
pv
}
// SetPrivValidator sets the private validator account for signing votes.
func
(
cs
*
ConsensusState
)
SetPrivValidator
(
priv
ttypes
.
PrivValidator
)
{
cs
.
mtx
.
Lock
()
...
...
@@ -264,6 +280,13 @@ func (cs *ConsensusState) reconstructLastCommit(state State) {
panic
(
fmt
.
Sprintf
(
"Failed to reconstruct LastCommit: %v"
,
err
))
}
}
if
seenCommit
.
AggVote
!=
nil
{
aggVote
:=
&
ttypes
.
AggVote
{
AggVote
:
seenCommit
.
AggVote
}
added
,
err
:=
lastPrecommits
.
AddAggVote
(
aggVote
)
if
!
added
||
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"Failed to reconstruct LastCommit: %v"
,
err
))
}
}
if
!
lastPrecommits
.
HasTwoThirdsMajority
()
{
panic
(
"Failed to reconstruct LastCommit: Does not have +2/3 maj"
)
}
...
...
@@ -429,6 +452,8 @@ func (cs *ConsensusState) handleMsg(mi MsgInfo) {
// TODO: If rs.Height == vote.Height && rs.Round < vote.Round,
// the peer is sending us CatchupCommit precommits.
// We could make note of this and help filter in broadcastHasVoteMessage().
case
*
tmtypes
.
AggVote
:
err
=
cs
.
tryAddAggVote
(
msg
,
peerID
)
default
:
tendermintlog
.
Error
(
"Unknown msg type"
,
msg
.
String
(),
"peerid"
,
peerID
,
"peerip"
,
peerIP
)
}
...
...
@@ -486,7 +511,7 @@ func (cs *ConsensusState) checkTxsAvailable() {
}
cs
.
txsAvailable
<-
height
case
<-
cs
.
client
.
StopC
()
:
tendermintlog
.
Debug
(
"checkTxsAvailable ex
it"
)
tendermintlog
.
Info
(
"checkTxsAvailable qu
it"
)
return
}
}
...
...
@@ -589,7 +614,7 @@ func (cs *ConsensusState) proposalHeartbeat(height int64, round int) {
ValidatorIndex
:
int32
(
valIndex
),
}
heartbeatMsg
:=
&
ttypes
.
Heartbeat
{
Heartbeat
:
heartbeat
}
err
:=
cs
.
privValidator
.
SignHeartbeat
(
chainID
,
heartbeatMsg
)
err
:=
cs
.
GetPrivValidator
()
.
SignHeartbeat
(
chainID
,
heartbeatMsg
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"SignHeartbeat failed"
,
"err"
,
err
)
continue
...
...
@@ -661,12 +686,22 @@ func (cs *ConsensusState) isProposer() bool {
return
bytes
.
Equal
(
cs
.
Validators
.
GetProposer
()
.
Address
,
cs
.
privValidator
.
GetAddress
())
}
func
(
cs
*
ConsensusState
)
getProposerID
()
ID
{
pub
:=
cs
.
Validators
.
GetProposer
()
.
PubKey
pubkey
,
err
:=
ttypes
.
ConsensusCrypto
.
PubKeyFromBytes
(
pub
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"getProposerID fail"
,
"err"
,
err
)
}
return
GenIDByPubKey
(
pubkey
)
}
func
(
cs
*
ConsensusState
)
defaultDecideProposal
(
height
int64
,
round
int
)
{
var
block
*
ttypes
.
TendermintBlock
// Decide on block
if
cs
.
ValidBlock
!=
nil
{
if
preExec
{
// If there is valid block, PreExec that.
pblockNew
:=
cs
.
client
.
PreExecBlock
(
cs
.
ValidBlock
.
Data
,
false
)
if
pblockNew
==
nil
{
...
...
@@ -674,6 +709,7 @@ func (cs *ConsensusState) defaultDecideProposal(height int64, round int) {
return
}
cs
.
ValidBlock
.
Data
=
pblockNew
}
block
=
cs
.
ValidBlock
}
else
{
// Create a new proposal block from state/txs from the mempool.
...
...
@@ -756,12 +792,14 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock)
}
block
.
Data
.
TxHash
=
merkle
.
CalcMerkleRoot
(
cfg
,
block
.
Data
.
Height
,
block
.
Data
.
Txs
)
if
preExec
{
pblockNew
:=
cs
.
client
.
PreExecBlock
(
block
.
Data
,
false
)
if
pblockNew
==
nil
{
tendermintlog
.
Error
(
"createProposalBlock PreExecBlock fail"
)
return
nil
}
block
.
Data
=
pblockNew
}
return
block
}
...
...
@@ -800,6 +838,11 @@ func (cs *ConsensusState) enterPrevote(height int64, round int) {
cs
.
newStep
()
}()
if
useAggSig
{
// Wait for some more prevotes; enterPrecommit
cs
.
scheduleTimeout
(
cs
.
Prevote
(
round
)
*
2
,
height
,
round
,
ttypes
.
RoundStepPrevoteWait
)
}
tendermintlog
.
Info
(
fmt
.
Sprintf
(
"enterPrevote(%v/%v). Current: %v/%v/%v"
,
height
,
round
,
cs
.
Height
,
cs
.
Round
,
cs
.
Step
),
"cost"
,
types
.
Since
(
cs
.
begCons
))
// Sign and broadcast vote as necessary
...
...
@@ -833,7 +876,7 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
return
}
if
!
cs
.
isProposer
()
{
if
preExec
&&
!
cs
.
isProposer
()
{
// PreExec proposal block
blockCopy
:=
*
cs
.
ProposalBlock
.
Data
blockNew
:=
cs
.
client
.
PreExecBlock
(
&
blockCopy
,
true
)
...
...
@@ -898,6 +941,11 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) {
cs
.
newStep
()
}()
if
useAggSig
{
// Wait for some more precommits; enterNewRound
cs
.
scheduleTimeout
(
cs
.
Precommit
(
round
)
*
2
,
height
,
round
,
ttypes
.
RoundStepPrecommitWait
)
}
blockID
,
ok
:=
cs
.
Votes
.
Prevotes
(
round
)
.
TwoThirdsMajority
()
// If we don't have a polka, we must precommit nil
...
...
@@ -1010,7 +1058,7 @@ func (cs *ConsensusState) enterCommit(height int64, commitRound int) {
blockID
,
ok
:=
cs
.
Votes
.
Precommits
(
commitRound
)
.
TwoThirdsMajority
()
if
!
ok
{
panic
(
"
RunActionCommit()
expects +2/3 precommits"
)
panic
(
"
enterCommit
expects +2/3 precommits"
)
}
// The Locked* fields no longer matter.
...
...
@@ -1114,6 +1162,10 @@ func (cs *ConsensusState) finalizeCommit(height int64) {
tendermintlog
.
Info
(
fmt
.
Sprintf
(
"Not-Proposer reach consensus. Current: %v/%v/%v"
,
cs
.
Height
,
cs
.
Round
,
cs
.
Step
),
"CommitRound"
,
cs
.
CommitRound
,
"tx-len"
,
len
(
commitBlock
.
Txs
),
"cost"
,
types
.
Since
(
cs
.
begCons
),
"proposer-addr"
,
fmt
.
Sprintf
(
"%X"
,
ttypes
.
Fingerprint
(
block
.
TendermintBlock
.
Header
.
ProposerAddr
)))
}
reqblock
,
err
:=
cs
.
client
.
RequestBlock
(
height
)
if
err
==
nil
{
stateCopy
.
LastResultsHash
=
reqblock
.
Hash
(
cs
.
client
.
GetAPI
()
.
GetConfig
())
}
//check whether need update validator nodes
valNodes
,
err
:=
cs
.
client
.
QueryValidatorsByHeight
(
block
.
Header
.
Height
)
...
...
@@ -1278,6 +1330,121 @@ func (cs *ConsensusState) addProposalBlock(proposalBlock *tmtypes.TendermintBloc
return
nil
}
// Attempt to add aggregate vote.
func
(
cs
*
ConsensusState
)
tryAddAggVote
(
aggVoteRaw
*
tmtypes
.
AggVote
,
peerID
string
)
error
{
aggVote
:=
&
ttypes
.
AggVote
{
AggVote
:
aggVoteRaw
}
if
aggVote
.
Height
!=
cs
.
Height
{
tendermintlog
.
Debug
(
"AggVote ignored and not added"
,
"voteHeight"
,
aggVote
.
Height
,
"csHeight"
,
cs
.
Height
,
"peerID"
,
peerID
)
return
ErrVoteHeightMismatch
}
if
cs
.
begCons
.
IsZero
()
{
cs
.
begCons
=
time
.
Now
()
}
height
:=
cs
.
Height
_
,
err
:=
cs
.
Votes
.
AddAggVote
(
aggVote
,
peerID
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"Error attempting to add aggregate vote"
,
"err"
,
err
)
return
ErrAddingAggVote
}
switch
aggVote
.
Type
{
case
uint32
(
ttypes
.
VoteTypePrevote
)
:
prevotes
:=
cs
.
Votes
.
Prevotes
(
int
(
aggVote
.
Round
))
tendermintlog
.
Info
(
"Added aggregate prevote"
,
"aggVote"
,
aggVote
,
"prevotes"
,
prevotes
.
StringShort
())
// If +2/3 prevotes for a block or nil for *any* round:
if
blockID
,
ok
:=
prevotes
.
TwoThirdsMajority
();
ok
{
// There was a polka!
// If we're locked but this is a recent polka, unlock.
// If it matches our ProposalBlock, update the ValidBlock
// Unlock if `cs.LockedRound < vote.Round <= cs.Round`
// NOTE: If vote.Round > cs.Round, we'll deal with it when we get to vote.Round
if
(
cs
.
LockedBlock
!=
nil
)
&&
(
cs
.
LockedRound
<
int
(
aggVote
.
Round
))
&&
(
int
(
aggVote
.
Round
)
<=
cs
.
Round
)
&&
!
cs
.
LockedBlock
.
HashesTo
(
blockID
.
Hash
)
{
tendermintlog
.
Info
(
"Unlocking because of POL."
,
"lockedRound"
,
cs
.
LockedRound
,
"POLRound"
,
aggVote
.
Round
)
cs
.
LockedRound
=
-
1
cs
.
LockedBlock
=
nil
}
// Update Valid* if we can.
// NOTE: our proposal block may be nil or not what received a polka..
if
len
(
blockID
.
Hash
)
!=
0
&&
(
cs
.
ValidRound
<
int
(
aggVote
.
Round
))
&&
(
int
(
aggVote
.
Round
)
==
cs
.
Round
)
{
if
cs
.
ProposalBlock
.
HashesTo
(
blockID
.
Hash
)
{
tendermintlog
.
Info
(
"Updating ValidBlock because of POL."
,
"validRound"
,
cs
.
ValidRound
,
"POLRound"
,
aggVote
.
Round
)
cs
.
ValidRound
=
int
(
aggVote
.
Round
)
cs
.
ValidBlock
=
cs
.
ProposalBlock
}
else
{
tendermintlog
.
Info
(
"Valid block we don't know about. Set ProposalBlock=nil"
,
"proposal"
,
fmt
.
Sprintf
(
"%X"
,
cs
.
ProposalBlock
.
Hash
()),
"blockId"
,
fmt
.
Sprintf
(
"%X"
,
blockID
.
Hash
))
// We're getting the wrong block.
cs
.
ProposalBlock
=
nil
}
cs
.
ProposalBlockHash
=
blockID
.
Hash
validBlockMsg
:=
&
tmtypes
.
ValidBlockMsg
{
Height
:
aggVote
.
Height
,
Round
:
aggVote
.
Round
,
Blockhash
:
cs
.
ProposalBlockHash
,
IsCommit
:
false
,
}
cs
.
broadcastChannel
<-
MsgInfo
{
TypeID
:
ttypes
.
ValidBlockID
,
Msg
:
validBlockMsg
,
PeerID
:
cs
.
ourID
,
PeerIP
:
""
}
}
}
// If +2/3 prevotes for *anything* for this or future round:
switch
{
case
cs
.
Round
<
int
(
aggVote
.
Round
)
&&
prevotes
.
HasTwoThirdsAny
()
:
// Round-skip if there is any 2/3+ of votes ahead of us
cs
.
enterNewRound
(
height
,
int
(
aggVote
.
Round
))
case
cs
.
Round
==
int
(
aggVote
.
Round
)
&&
ttypes
.
RoundStepPrevote
<=
cs
.
Step
:
// current round
blockID
,
ok
:=
prevotes
.
TwoThirdsMajority
()
if
ok
&&
(
cs
.
isProposalComplete
()
||
len
(
blockID
.
Hash
)
==
0
)
{
cs
.
enterPrecommit
(
height
,
int
(
aggVote
.
Round
))
}
else
if
prevotes
.
HasTwoThirdsAny
()
{
cs
.
enterPrevoteWait
(
height
,
int
(
aggVote
.
Round
))
}
case
cs
.
Proposal
!=
nil
&&
0
<=
cs
.
Proposal
.
POLRound
&&
cs
.
Proposal
.
POLRound
==
aggVote
.
Round
:
// If the proposal is now complete, enter prevote of cs.Round.
if
cs
.
isProposalComplete
()
{
cs
.
enterPrevote
(
height
,
cs
.
Round
)
}
}
case
uint32
(
ttypes
.
VoteTypePrecommit
)
:
precommits
:=
cs
.
Votes
.
Precommits
(
int
(
aggVote
.
Round
))
tendermintlog
.
Info
(
"Added aggregate precommit"
,
"aggVote"
,
aggVote
,
"precommits"
,
precommits
.
StringShort
())
blockID
,
ok
:=
precommits
.
TwoThirdsMajority
()
if
ok
{
// Executed as TwoThirdsMajority could be from a higher round
cs
.
enterNewRound
(
height
,
int
(
aggVote
.
Round
))
cs
.
enterPrecommit
(
height
,
int
(
aggVote
.
Round
))
if
len
(
blockID
.
Hash
)
!=
0
{
cs
.
enterCommit
(
height
,
int
(
aggVote
.
Round
))
if
skipTimeoutCommit
&&
precommits
.
HasAll
()
{
cs
.
enterNewRound
(
cs
.
Height
,
0
)
}
}
else
{
cs
.
enterPrecommitWait
(
height
,
int
(
aggVote
.
Round
))
}
}
else
if
cs
.
Round
<=
int
(
aggVote
.
Round
)
&&
precommits
.
HasTwoThirdsAny
()
{
cs
.
enterNewRound
(
height
,
int
(
aggVote
.
Round
))
cs
.
enterPrecommitWait
(
height
,
int
(
aggVote
.
Round
))
}
default
:
panic
(
fmt
.
Sprintf
(
"Unexpected aggVote type %X"
,
aggVote
.
Type
))
// Should not happen.
}
return
nil
}
// Attempt to add the vote. if its a duplicate signature, dupeout the validator
func
(
cs
*
ConsensusState
)
tryAddVote
(
voteRaw
*
tmtypes
.
Vote
,
peerID
string
,
peerIP
string
)
error
{
vote
:=
&
ttypes
.
Vote
{
Vote
:
voteRaw
}
...
...
@@ -1344,7 +1511,7 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
// Not necessarily a bad peer, but not favourable behaviour.
if
vote
.
Height
!=
cs
.
Height
{
err
=
ErrVoteHeightMismatch
tendermintlog
.
Info
(
"Vote ignored and not added"
,
"voteHeight"
,
vote
.
Height
,
"csHeight"
,
cs
.
Height
,
"peerID"
,
peerID
)
tendermintlog
.
Debug
(
"Vote ignored and not added"
,
"voteHeight"
,
vote
.
Height
,
"csHeight"
,
cs
.
Height
,
"peerID"
,
peerID
)
return
}
...
...
@@ -1426,6 +1593,16 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
case
cs
.
Round
==
int
(
vote
.
Round
)
&&
ttypes
.
RoundStepPrevote
<=
cs
.
Step
:
// current round
blockID
,
ok
:=
prevotes
.
TwoThirdsMajority
()
if
ok
&&
(
cs
.
isProposalComplete
()
||
len
(
blockID
.
Hash
)
==
0
)
{
if
useAggSig
&&
prevotes
.
GetAggVote
()
==
nil
{
err
:=
prevotes
.
SetAggVote
()
if
err
!=
nil
{
tendermintlog
.
Error
(
"prevotes SetAggVote fail"
,
"err"
,
err
)
break
}
aggVoteMsg
:=
prevotes
.
GetAggVote
()
.
AggVote
cs
.
broadcastChannel
<-
MsgInfo
{
TypeID
:
ttypes
.
AggVoteID
,
Msg
:
aggVoteMsg
,
PeerID
:
cs
.
ourID
,
PeerIP
:
""
}
tendermintlog
.
Info
(
"Send aggregate prevote"
,
"aggVote"
,
prevotes
.
GetAggVote
())
}
cs
.
enterPrecommit
(
height
,
int
(
vote
.
Round
))
}
else
if
prevotes
.
HasTwoThirdsAny
()
{
cs
.
enterPrevoteWait
(
height
,
int
(
vote
.
Round
))
...
...
@@ -1447,6 +1624,16 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
cs
.
enterNewRound
(
height
,
int
(
vote
.
Round
))
cs
.
enterPrecommit
(
height
,
int
(
vote
.
Round
))
if
len
(
blockID
.
Hash
)
!=
0
{
if
useAggSig
&&
precommits
.
GetAggVote
()
==
nil
{
err
:=
precommits
.
SetAggVote
()
if
err
!=
nil
{
tendermintlog
.
Error
(
"precommits SetAggVote fail"
,
"err"
,
err
)
break
}
aggVoteMsg
:=
precommits
.
GetAggVote
()
.
AggVote
cs
.
broadcastChannel
<-
MsgInfo
{
TypeID
:
ttypes
.
AggVoteID
,
Msg
:
aggVoteMsg
,
PeerID
:
cs
.
ourID
,
PeerIP
:
""
}
tendermintlog
.
Info
(
"Send aggregate precommit"
,
"aggVote"
,
precommits
.
GetAggVote
())
}
cs
.
enterCommit
(
height
,
int
(
vote
.
Round
))
if
skipTimeoutCommit
&&
precommits
.
HasAll
()
{
cs
.
enterNewRound
(
cs
.
Height
,
0
)
...
...
@@ -1467,7 +1654,6 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
}
func
(
cs
*
ConsensusState
)
signVote
(
voteType
byte
,
hash
[]
byte
)
(
*
ttypes
.
Vote
,
error
)
{
addr
:=
cs
.
privValidator
.
GetAddress
()
valIndex
,
_
:=
cs
.
Validators
.
GetByAddress
(
addr
)
tVote
:=
&
tmtypes
.
Vote
{}
...
...
@@ -1482,11 +1668,10 @@ func (cs *ConsensusState) signVote(voteType byte, hash []byte) (*ttypes.Vote, er
Type
:
uint32
(
voteType
),
BlockID
:
&
tmtypes
.
BlockID
{
Hash
:
hash
},
Signature
:
nil
,
UseAggSig
:
useAggSig
,
},
}
beg
:=
time
.
Now
()
err
:=
cs
.
privValidator
.
SignVote
(
cs
.
state
.
ChainID
,
vote
)
tendermintlog
.
Debug
(
"signVote"
,
"height"
,
cs
.
Height
,
"cost"
,
types
.
Since
(
beg
))
return
vote
,
err
}
...
...
@@ -1498,14 +1683,18 @@ func (cs *ConsensusState) signAddVote(voteType byte, hash []byte) *ttypes.Vote {
}
vote
,
err
:=
cs
.
signVote
(
voteType
,
hash
)
if
err
==
nil
{
// send to self
cs
.
sendInternalMessage
(
MsgInfo
{
TypeID
:
ttypes
.
VoteID
,
Msg
:
vote
.
Vote
,
PeerID
:
cs
.
ourID
,
PeerIP
:
""
})
tendermintlog
.
Info
(
"Signed and pushed vote"
,
"height"
,
cs
.
Height
,
"round"
,
cs
.
Round
,
"vote"
,
vote
,
"err"
,
err
)
if
useAggSig
{
// send to proposer
cs
.
unicastChannel
<-
MsgInfo
{
TypeID
:
ttypes
.
VoteID
,
Msg
:
vote
.
Vote
,
PeerID
:
cs
.
getProposerID
(),
PeerIP
:
""
}
}
tendermintlog
.
Info
(
"Sign and send vote"
,
"height"
,
cs
.
Height
,
"round"
,
cs
.
Round
,
"vote"
,
vote
)
return
vote
}
tendermintlog
.
Error
(
"Error signing vote"
,
"height"
,
cs
.
Height
,
"round"
,
cs
.
Round
,
"vote"
,
vote
,
"err"
,
err
)
return
nil
}
// CompareHRS method
...
...
@@ -1570,6 +1759,9 @@ func (cs *ConsensusState) PeerQueryMaj23Sleep() time.Duration {
// IsProposer method
func
(
cs
*
ConsensusState
)
IsProposer
()
bool
{
cs
.
mtx
.
Lock
()
defer
cs
.
mtx
.
Unlock
()
return
cs
.
isProposer
()
}
...
...
plugin/consensus/tendermint/node.go
View file @
34c89f73
...
...
@@ -25,6 +25,7 @@ const (
tryListenSeconds
=
5
handshakeTimeout
=
20
// * time.Second,
maxSendQueueSize
=
1024
minSendQueueSize
=
10
defaultSendTimeout
=
60
*
time
.
Second
//MaxMsgPacketPayloadSize define
MaxMsgPacketPayloadSize
=
10
*
1024
*
1024
...
...
@@ -57,11 +58,12 @@ func Parallel(tasks ...func()) {
wg
.
Wait
()
}
// Gen
Address
ByPubKey method
func
Gen
AddressByPubKey
(
pubkey
crypto
.
PubKey
)
[]
byte
{
// Gen
ID
ByPubKey method
func
Gen
IDByPubKey
(
pubkey
crypto
.
PubKey
)
ID
{
//must add 3 bytes ahead to make compatibly
typeAddr
:=
append
([]
byte
{
byte
(
0x01
),
byte
(
0x01
),
byte
(
0x20
)},
pubkey
.
Bytes
()
...
)
return
crypto
.
Ripemd160
(
typeAddr
)
typeAddr
:=
append
([]
byte
{
byte
(
0x01
),
byte
(
0x01
),
byte
(
0x20
)},
pubkey
.
Bytes
()[
:
32
]
...
)
address
:=
crypto
.
Ripemd160
(
typeAddr
)
return
ID
(
hex
.
EncodeToString
(
address
))
}
// IP2IPPort struct
...
...
@@ -129,6 +131,7 @@ type Node struct {
state
*
ConsensusState
broadcastChannel
chan
MsgInfo
unicastChannel
chan
MsgInfo
started
uint32
// atomic
stopped
uint32
// atomic
quit
chan
struct
{}
...
...
@@ -136,8 +139,6 @@ type Node struct {
// NewNode method
func
NewNode
(
seeds
[]
string
,
protocol
string
,
lAddr
string
,
privKey
crypto
.
PrivKey
,
network
string
,
version
string
,
state
*
ConsensusState
)
*
Node
{
address
:=
GenAddressByPubKey
(
privKey
.
PubKey
())
node
:=
&
Node
{
peerSet
:
NewPeerSet
(),
seeds
:
seeds
,
...
...
@@ -148,16 +149,18 @@ func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivK
privKey
:
privKey
,
Network
:
network
,
Version
:
version
,
ID
:
ID
(
hex
.
EncodeToString
(
address
)),
ID
:
GenIDByPubKey
(
privKey
.
PubKey
(
)),
dialing
:
NewMutexMap
(),
reconnecting
:
NewMutexMap
(),
broadcastChannel
:
make
(
chan
MsgInfo
,
maxSendQueueSize
),
unicastChannel
:
make
(
chan
MsgInfo
,
minSendQueueSize
),
state
:
state
,
localIPs
:
make
(
map
[
string
]
net
.
IP
),
}
state
.
SetOurID
(
node
.
ID
)
state
.
SetBroadcastChannel
(
node
.
broadcastChannel
)
state
.
SetUnicastChannel
(
node
.
unicastChannel
)
localIPs
:=
getNaiveExternalAddress
(
true
)
if
len
(
localIPs
)
>
0
{
...
...
@@ -179,7 +182,7 @@ func (node *Node) Start() {
if
err
==
nil
{
break
}
else
if
i
<
tryListenSeconds
-
1
{
time
.
Sleep
(
time
.
Second
*
1
)
time
.
Sleep
(
time
.
Second
)
}
}
if
err
!=
nil
{
...
...
@@ -213,6 +216,7 @@ func (node *Node) Start() {
go
node
.
StartConsensusRoutine
()
go
node
.
BroadcastRoutine
()
go
node
.
UnicastRoutine
()
}
}
...
...
@@ -305,13 +309,33 @@ func (node *Node) BroadcastRoutine() {
for
{
msg
,
ok
:=
<-
node
.
broadcastChannel
if
!
ok
{
tendermintlog
.
Debug
(
"broadcastChannel closed"
)
tendermintlog
.
Info
(
"broadcastChannel closed"
)
return
}
node
.
Broadcast
(
msg
)
}
}
// BroadcastRoutine receive to broadcast
func
(
node
*
Node
)
UnicastRoutine
()
{
for
{
msg
,
ok
:=
<-
node
.
unicastChannel
if
!
ok
{
tendermintlog
.
Info
(
"unicastChannel closed"
)
return
}
for
_
,
peer
:=
range
node
.
peerSet
.
List
()
{
if
peer
.
ID
()
==
msg
.
PeerID
{
success
:=
peer
.
Send
(
msg
)
if
!
success
{
tendermintlog
.
Error
(
"send failure in UnicastRoutine"
)
}
break
}
}
}
}
func
(
node
*
Node
)
connectComming
(
inConn
net
.
Conn
)
{
maxPeers
:=
maxNumPeers
if
maxPeers
<=
node
.
peerSet
.
Size
()
{
...
...
@@ -640,7 +664,7 @@ func dial(addr string) (net.Conn, error) {
func
newOutboundPeerConn
(
addr
string
,
ourNodePrivKey
crypto
.
PrivKey
,
onPeerError
func
(
Peer
,
interface
{}),
state
*
ConsensusState
)
(
*
peerConn
,
error
)
{
conn
,
err
:=
dial
(
addr
)
if
err
!=
nil
{
return
&
peerConn
{},
fmt
.
Errorf
(
"
Error creating peer
:%v"
,
err
)
return
&
peerConn
{},
fmt
.
Errorf
(
"
newOutboundPeerConn dial fail
:%v"
,
err
)
}
pc
,
err
:=
newPeerConn
(
conn
,
true
,
true
,
ourNodePrivKey
,
onPeerError
,
state
)
...
...
@@ -684,7 +708,7 @@ func newPeerConn(
// Encrypt connection
conn
,
err
=
MakeSecretConnection
(
conn
,
ourNodePrivKey
)
if
err
!=
nil
{
return
pc
,
fmt
.
Errorf
(
"
Error creating peer
:%v"
,
err
)
return
pc
,
fmt
.
Errorf
(
"
MakeSecretConnection fail
:%v"
,
err
)
}
// Only the information we already have
...
...
plugin/consensus/tendermint/node_test.go
View file @
34c89f73
...
...
@@ -54,17 +54,19 @@ func TestParallel(t *testing.T) {
assert
.
Equal
(
t
,
6
,
sum
)
}
func
TestGen
Address
ByPubKey
(
t
*
testing
.
T
)
{
func
TestGen
ID
ByPubKey
(
t
*
testing
.
T
)
{
tmp
,
err
:=
hex
.
DecodeString
(
privKey
)
assert
.
Nil
(
t
,
err
)
priv
,
err
:=
secureConnCrypto
.
PrivKeyFromBytes
(
tmp
)
assert
.
Nil
(
t
,
err
)
addr
:=
GenAddressByPubKey
(
priv
.
PubKey
())
id
:=
GenIDByPubKey
(
priv
.
PubKey
())
addr
,
err
:=
hex
.
DecodeString
(
string
(
id
))
assert
.
Nil
(
t
,
err
)
strAddr
:=
fmt
.
Sprintf
(
"%X"
,
addr
)
assert
.
Equal
(
t
,
expectAddress
,
strAddr
)
fmt
.
Println
(
"TestGen
Address
ByPubKey ok"
)
fmt
.
Println
(
"TestGen
ID
ByPubKey ok"
)
}
func
TestIP2IPPort
(
t
*
testing
.
T
)
{
...
...
@@ -154,7 +156,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
},
}
ps
:=
pc
.
state
pc
.
waitQuit
.
Add
(
1
)
go
pc
.
updateStateRoutine
()
//NewRoundStepID msg
...
...
@@ -249,7 +250,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
assert
.
NotNil
(
t
,
ps
.
getVoteBitArray
(
3
,
2
,
ttypes
.
VoteTypePrecommit
))
pc
.
quitUpdate
<-
struct
{}{}
pc
.
waitQuit
.
Wait
()
fmt
.
Println
(
"testUpdateStateRoutine ok"
)
}
plugin/consensus/tendermint/peer_set.go
View file @
34c89f73
...
...
@@ -8,13 +8,11 @@ import (
"bufio"
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net"
"reflect"
"runtime/debug"
"sync"
"sync/atomic"
"time"
...
...
@@ -56,8 +54,6 @@ type Peer interface {
Stop
()
SetTransferChannel
(
chan
MsgInfo
)
//Set(string, interface{})
//Get(string) interface{}
}
// PeerConnState struct
...
...
@@ -85,10 +81,8 @@ type peerConn struct {
started
uint32
//atomic
stopped
uint32
// atomic
quitSend
chan
struct
{}
quitUpdate
chan
struct
{}
quitBeat
chan
struct
{}
waitQuit
sync
.
WaitGroup
transferChannel
chan
MsgInfo
...
...
@@ -222,8 +216,7 @@ func (pc *peerConn) ID() ID {
if
len
(
pc
.
id
)
!=
0
{
return
pc
.
id
}
address
:=
GenAddressByPubKey
(
pc
.
conn
.
(
*
SecretConnection
)
.
RemotePubKey
())
pc
.
id
=
ID
(
hex
.
EncodeToString
(
address
))
pc
.
id
=
GenIDByPubKey
(
pc
.
conn
.
(
*
SecretConnection
)
.
RemotePubKey
())
return
pc
.
id
}
...
...
@@ -265,6 +258,11 @@ func (pc *peerConn) SetTransferChannel(transferChannel chan MsgInfo) {
pc
.
transferChannel
=
transferChannel
}
func
(
pc
*
peerConn
)
String
()
string
{
return
fmt
.
Sprintf
(
"PeerConn{outbound:%v persistent:%v ip:%s id:%s started:%v stopped:%v}"
,
pc
.
outbound
,
pc
.
persistent
,
pc
.
ip
.
String
(),
pc
.
id
,
pc
.
started
,
pc
.
stopped
)
}
func
(
pc
*
peerConn
)
CloseConn
()
{
err
:=
pc
.
conn
.
Close
()
// nolint: errcheck
if
err
!=
nil
{
...
...
@@ -358,7 +356,7 @@ func (pc *peerConn) Send(msg MsgInfo) bool {
atomic
.
AddInt32
(
&
pc
.
sendQueueSize
,
1
)
return
true
case
<-
time
.
After
(
defaultSendTimeout
)
:
tendermintlog
.
Error
(
"send msg timeout"
,
"peerip"
,
msg
.
PeerIP
,
"msg"
,
msg
.
Msg
)
tendermintlog
.
Error
(
"send msg timeout"
,
"peerip"
,
msg
.
PeerIP
,
"msg"
,
msg
)
return
false
}
}
...
...
@@ -379,9 +377,25 @@ func (pc *peerConn) TrySend(msg MsgInfo) bool {
// PickSendVote picks a vote and sends it to the peer.
// Returns true if vote was sent.
func
(
pc
*
peerConn
)
PickSendVote
(
votes
ttypes
.
VoteSetReader
)
bool
{
if
vote
,
ok
:=
pc
.
state
.
PickVoteToSend
(
votes
);
ok
{
if
useAggSig
{
if
pc
.
state
.
AggPrecommit
{
time
.
Sleep
(
pc
.
myState
.
PeerGossipSleep
())
return
false
}
aggVote
:=
votes
.
GetAggVote
()
if
aggVote
!=
nil
{
msg
:=
MsgInfo
{
TypeID
:
ttypes
.
AggVoteID
,
Msg
:
aggVote
.
AggVote
,
PeerID
:
pc
.
id
,
PeerIP
:
pc
.
ip
.
String
()}
tendermintlog
.
Debug
(
"Sending aggregate vote message"
,
"msg"
,
msg
)
if
pc
.
Send
(
msg
)
{
pc
.
state
.
SetHasAggPrecommit
(
aggVote
)
time
.
Sleep
(
pc
.
myState
.
PeerGossipSleep
())
return
true
}
}
return
false
}
else
if
vote
,
ok
:=
pc
.
state
.
PickVoteToSend
(
votes
);
ok
{
msg
:=
MsgInfo
{
TypeID
:
ttypes
.
VoteID
,
Msg
:
vote
.
Vote
,
PeerID
:
pc
.
id
,
PeerIP
:
pc
.
ip
.
String
()}
tendermintlog
.
Debug
(
"Sending vote message"
,
"
vote
"
,
msg
)
tendermintlog
.
Debug
(
"Sending vote message"
,
"
msg
"
,
msg
)
if
pc
.
Send
(
msg
)
{
pc
.
state
.
SetHasVote
(
vote
)
return
true
...
...
@@ -406,7 +420,6 @@ func (pc *peerConn) Start() error {
pc
.
pongChannel
=
make
(
chan
struct
{})
pc
.
sendQueue
=
make
(
chan
MsgInfo
,
maxSendQueueSize
)
pc
.
sendBuffer
=
make
([]
byte
,
0
,
MaxMsgPacketPayloadSize
)
pc
.
quitSend
=
make
(
chan
struct
{})
pc
.
quitUpdate
=
make
(
chan
struct
{})
pc
.
quitBeat
=
make
(
chan
struct
{})
pc
.
state
=
&
PeerConnState
{
ip
:
pc
.
ip
,
PeerRoundState
:
ttypes
.
PeerRoundState
{
...
...
@@ -417,7 +430,6 @@ func (pc *peerConn) Start() error {
}}
pc
.
updateStateQueue
=
make
(
chan
MsgInfo
,
maxSendQueueSize
)
pc
.
heartbeatQueue
=
make
(
chan
proto
.
Message
,
100
)
pc
.
waitQuit
.
Add
(
5
)
//heartbeatRoutine, updateStateRoutine,gossipDataRoutine,gossipVotesRoutine,queryMaj23Routine
go
pc
.
sendRoutine
()
go
pc
.
recvRoutine
()
...
...
@@ -434,27 +446,8 @@ func (pc *peerConn) Start() error {
func
(
pc
*
peerConn
)
Stop
()
{
if
atomic
.
CompareAndSwapUint32
(
&
pc
.
stopped
,
0
,
1
)
{
pc
.
quitSend
<-
struct
{}{}
pc
.
quitUpdate
<-
struct
{}{}
pc
.
quitBeat
<-
struct
{}{}
pc
.
waitQuit
.
Wait
()
tendermintlog
.
Info
(
"peerConn stop waitQuit"
,
"peerIP"
,
pc
.
ip
.
String
())
close
(
pc
.
sendQueue
)
pc
.
sendQueue
=
nil
pc
.
transferChannel
=
nil
pc
.
CloseConn
()
tendermintlog
.
Info
(
"peerConn stop finish"
,
"peerIP"
,
pc
.
ip
.
String
())
}
}
// Catch panics, usually caused by remote disconnects.
func
(
pc
*
peerConn
)
_recover
()
{
if
r
:=
recover
();
r
!=
nil
{
stack
:=
debug
.
Stack
()
err
:=
StackError
{
r
,
stack
}
pc
.
stopForError
(
err
)
tendermintlog
.
Info
(
"peerConn close connection"
,
"peerIP"
,
pc
.
ip
.
String
())
}
}
...
...
@@ -468,12 +461,9 @@ func (pc *peerConn) stopForError(r interface{}) {
}
func
(
pc
*
peerConn
)
sendRoutine
()
{
defer
pc
.
_recover
()
FOR_LOOP
:
for
{
select
{
case
<-
pc
.
quitSend
:
break
FOR_LOOP
case
msg
:=
<-
pc
.
sendQueue
:
bytes
,
err
:=
proto
.
Marshal
(
msg
.
Msg
)
if
err
!=
nil
{
...
...
@@ -525,7 +515,6 @@ FOR_LOOP:
}
func
(
pc
*
peerConn
)
recvRoutine
()
{
defer
pc
.
_recover
()
FOR_LOOP
:
for
{
//typeID+msgLen+msg
...
...
@@ -563,7 +552,7 @@ FOR_LOOP:
continue
}
if
pc
.
transferChannel
!=
nil
&&
(
pkt
.
TypeID
==
ttypes
.
ProposalID
||
pkt
.
TypeID
==
ttypes
.
VoteID
||
pkt
.
TypeID
==
ttypes
.
ProposalBlockID
)
{
pkt
.
TypeID
==
ttypes
.
ProposalBlockID
||
pkt
.
TypeID
==
ttypes
.
AggVoteID
)
{
pc
.
transferChannel
<-
MsgInfo
{
pkt
.
TypeID
,
realMsg
.
(
proto
.
Message
),
pc
.
ID
(),
pc
.
ip
.
String
()}
if
pkt
.
TypeID
==
ttypes
.
ProposalID
{
proposal
:=
realMsg
.
(
*
tmtypes
.
Proposal
)
...
...
@@ -577,6 +566,9 @@ FOR_LOOP:
block
:=
&
ttypes
.
TendermintBlock
{
TendermintBlock
:
realMsg
.
(
*
tmtypes
.
TendermintBlock
)}
tendermintlog
.
Debug
(
"Receiving proposal block"
,
"block-height"
,
block
.
Header
.
Height
,
"peerip"
,
pc
.
ip
.
String
())
pc
.
state
.
SetHasProposalBlock
(
block
)
}
else
if
pkt
.
TypeID
==
ttypes
.
AggVoteID
{
aggVote
:=
&
ttypes
.
AggVote
{
AggVote
:
realMsg
.
(
*
tmtypes
.
AggVote
)}
tendermintlog
.
Debug
(
"Receiving aggregate vote"
,
"aggVote-height"
,
aggVote
.
Height
,
"peerip"
,
pc
.
ip
.
String
())
}
}
else
if
pkt
.
TypeID
==
ttypes
.
ProposalHeartbeatID
{
pc
.
heartbeatQueue
<-
realMsg
.
(
*
tmtypes
.
Heartbeat
)
...
...
@@ -591,10 +583,8 @@ FOR_LOOP:
}
}
}
close
(
pc
.
pongChannel
)
close
(
pc
.
heartbeatQueue
)
close
(
pc
.
updateStateQueue
)
pc
.
quitUpdate
<-
struct
{}{}
pc
.
quitBeat
<-
struct
{}{}
tendermintlog
.
Info
(
"peerConn stop recvRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -603,7 +593,6 @@ FOR_LOOP:
for
{
select
{
case
<-
pc
.
quitUpdate
:
pc
.
waitQuit
.
Done
()
break
FOR_LOOP
case
msg
:=
<-
pc
.
updateStateQueue
:
typeID
:=
msg
.
TypeID
...
...
@@ -662,6 +651,7 @@ FOR_LOOP:
}
}
}
close
(
pc
.
updateStateQueue
)
tendermintlog
.
Info
(
"peerConn stop updateStateRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -670,15 +660,17 @@ FOR_LOOP:
for
{
select
{
case
<-
pc
.
quitBeat
:
pc
.
waitQuit
.
Done
()
break
FOR_LOOP
case
heartbeat
:=
<-
pc
.
heartbeatQueue
:
msg
:=
heartbeat
.
(
*
tmtypes
.
Heartbeat
)
msg
,
ok
:=
heartbeat
.
(
*
tmtypes
.
Heartbeat
)
if
ok
{
tendermintlog
.
Debug
(
"Received proposal heartbeat message"
,
"height"
,
msg
.
Height
,
"round"
,
msg
.
Round
,
"sequence"
,
msg
.
Sequence
,
"valIdx"
,
msg
.
ValidatorIndex
,
"valAddr"
,
msg
.
ValidatorAddress
)
}
}
}
close
(
pc
.
heartbeatQueue
)
tendermintlog
.
Info
(
"peerConn stop heartbeatRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -687,7 +679,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop gossipDataRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -789,7 +780,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop gossipVotesRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -806,7 +796,7 @@ OUTER_LOOP:
// If height matches, then send LastCommit, Prevotes, Precommits.
if
rs
.
Height
==
prs
.
Height
{
if
pc
.
gossipVotesForHeight
(
rs
,
&
prs
.
PeerRoundState
)
{
if
!
useAggSig
&&
pc
.
gossipVotesForHeight
(
rs
,
&
prs
.
PeerRoundState
)
{
continue
OUTER_LOOP
}
}
...
...
@@ -914,7 +904,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop queryMaj23Routine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -1003,20 +992,6 @@ OUTER_LOOP:
}
}
// StackError struct
type
StackError
struct
{
Err
interface
{}
Stack
[]
byte
}
func
(
se
StackError
)
String
()
string
{
return
fmt
.
Sprintf
(
"Error: %v
\n
Stack: %s"
,
se
.
Err
,
se
.
Stack
)
}
func
(
se
StackError
)
Error
()
string
{
return
se
.
String
()
}
// GetRoundState returns an atomic snapshot of the PeerRoundState.
// There's no point in mutating it since it won't change PeerState.
func
(
ps
*
PeerConnState
)
GetRoundState
()
*
ttypes
.
PeerRoundState
{
...
...
@@ -1073,6 +1048,23 @@ func (ps *PeerConnState) SetHasProposalBlock(block *ttypes.TendermintBlock) {
ps
.
ProposalBlock
=
true
}
// SetHasAggPrecommit sets the given aggregate precommit as known for the peer.
func
(
ps
*
PeerConnState
)
SetHasAggPrecommit
(
aggVote
*
ttypes
.
AggVote
)
{
ps
.
mtx
.
Lock
()
defer
ps
.
mtx
.
Unlock
()
if
ps
.
Height
!=
aggVote
.
Height
||
ps
.
Round
!=
int
(
aggVote
.
Round
)
{
return
}
if
ps
.
AggPrecommit
{
return
}
tendermintlog
.
Debug
(
"Peer set aggregate precommit"
,
"peerip"
,
ps
.
ip
.
String
(),
"peer-state"
,
fmt
.
Sprintf
(
"%v/%v/%v"
,
ps
.
Height
,
ps
.
Round
,
ps
.
Step
),
"aggVote(H/R)"
,
fmt
.
Sprintf
(
"%v/%v"
,
aggVote
.
Height
,
aggVote
.
Round
))
ps
.
AggPrecommit
=
true
}
// PickVoteToSend picks a vote to send to the peer.
// Returns true if a vote was picked.
// NOTE: `votes` must be the correct Size() for the Height().
...
...
@@ -1266,6 +1258,7 @@ func (ps *PeerConnState) ApplyNewRoundStepMessage(msg *tmtypes.NewRoundStepMsg)
// We'll update the BitArray capacity later.
ps
.
Prevotes
=
nil
ps
.
Precommits
=
nil
ps
.
AggPrecommit
=
false
}
if
psHeight
==
msg
.
Height
&&
psRound
!=
int
(
msg
.
Round
)
&&
int
(
msg
.
Round
)
==
psCatchupCommitRound
{
// Peer caught up to CatchupCommitRound.
...
...
plugin/consensus/tendermint/secret_connection.go
View file @
34c89f73
...
...
@@ -16,12 +16,13 @@ import (
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
"net"
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/plugin/plugin/consensus/tendermint/types"
ttypes
"github.com/33cn/plugin/plugin/consensus/tendermint/types"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/secretbox"
"golang.org/x/crypto/ripemd160"
...
...
@@ -33,7 +34,6 @@ const (
dataMaxSize
=
1024
totalFrameSize
=
dataMaxSize
+
dataLenSize
sealedFrameSize
=
totalFrameSize
+
secretbox
.
Overhead
authSigMsgSize
=
(
32
)
+
(
64
)
)
// fixed size (length prefixed) byte arrays
// SecretConnection Implements net.Conn
...
...
@@ -62,7 +62,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
// (see DJB's Curve25519 paper: http://cr.yp.to/ecdh/curve25519-20060209.pdf)
remEphPub
,
err
:=
shareEphPubKey
(
conn
,
locEphPub
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
fmt
.
Errorf
(
"shareEphPubKey: %v"
,
err
)
}
// Compute common shared secret.
...
...
@@ -96,7 +96,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
// Share (in secret) each other's pubkey & challenge signature
authSigMsg
,
err
:=
shareAuthSignature
(
sc
,
locPubKey
,
locSignature
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
fmt
.
Errorf
(
"shareAuthSignature: %v"
,
err
)
}
remPubKey
,
remSignature
:=
authSigMsg
.
Key
,
authSigMsg
.
Sig
if
!
remPubKey
.
VerifyBytes
(
challenge
[
:
],
remSignature
)
{
...
...
@@ -205,7 +205,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) {
var
err
error
ephPub
,
ephPriv
,
err
=
box
.
GenerateKey
(
crand
.
Reader
)
if
err
!=
nil
{
types
.
PanicCrisis
(
"Could not generate ephemeral keypairs"
)
t
t
ypes
.
PanicCrisis
(
"Could not generate ephemeral keypairs"
)
}
return
}
...
...
@@ -282,26 +282,28 @@ type authSigMessage struct {
func
shareAuthSignature
(
sc
io
.
ReadWriter
,
pubKey
crypto
.
PubKey
,
signature
crypto
.
Signature
)
(
*
authSigMessage
,
error
)
{
var
recvMsg
authSigMessage
var
err1
,
err2
error
pubLen
:=
len
(
pubKey
.
Bytes
())
sigLen
:=
len
(
signature
.
Bytes
())
Parallel
(
func
()
{
msgByte
:=
make
([]
byte
,
len
(
pubKey
.
Bytes
())
+
len
(
signature
.
Bytes
())
)
copy
(
msgByte
,
pubKey
.
Bytes
())
copy
(
msgByte
[
len
(
pubKey
.
Bytes
())
:
],
signature
.
Bytes
())
msgByte
:=
make
([]
byte
,
pubLen
+
sigLen
)
copy
(
msgByte
,
pubKey
.
Bytes
()
[
:
pubLen
]
)
copy
(
msgByte
[
pubLen
:
],
signature
.
Bytes
())
_
,
err1
=
sc
.
Write
(
msgByte
)
},
func
()
{
readBuffer
:=
make
([]
byte
,
authSigMsgSize
)
readBuffer
:=
make
([]
byte
,
pubLen
+
sigLen
)
_
,
err2
=
io
.
ReadFull
(
sc
,
readBuffer
)
if
err2
!=
nil
{
return
}
recvMsg
.
Key
,
err2
=
t
ypes
.
ConsensusCrypto
.
PubKeyFromBytes
(
readBuffer
[
:
32
])
recvMsg
.
Key
,
err2
=
t
types
.
ConsensusCrypto
.
PubKeyFromBytes
(
readBuffer
[
:
pubLen
])
if
err2
!=
nil
{
return
}
recvMsg
.
Sig
,
err2
=
t
ypes
.
ConsensusCrypto
.
SignatureFromBytes
(
readBuffer
[
32
:
])
recvMsg
.
Sig
,
err2
=
t
types
.
ConsensusCrypto
.
SignatureFromBytes
(
readBuffer
[
pubLen
:
])
if
err2
!=
nil
{
return
}
...
...
plugin/consensus/tendermint/state.go
View file @
34c89f73
...
...
@@ -385,7 +385,7 @@ func getprivkey(key string) crypto.PrivKey {
if
err
!=
nil
{
panic
(
err
)
}
priv
,
err
:=
cr
.
PrivKeyFromBytes
(
bkey
)
priv
,
err
:=
cr
.
PrivKeyFromBytes
(
bkey
[
:
32
]
)
if
err
!=
nil
{
panic
(
err
)
}
...
...
plugin/consensus/tendermint/store.go
View file @
34c89f73
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
tendermint
import
(
...
...
plugin/consensus/tendermint/tendermint.go
View file @
34c89f73
...
...
@@ -24,11 +24,14 @@ import (
"github.com/golang/protobuf/proto"
)
const
tendermintVersion
=
"0.1.0"
const
(
tendermintVersion
=
"0.1.0"
)
var
(
tendermintlog
=
log15
.
New
(
"module"
,
"tendermint"
)
genesis
string
genesisAmount
int64
=
1e8
genesisBlockTime
int64
timeoutTxAvail
int32
=
1000
timeoutPropose
int32
=
3000
// millisecond
...
...
@@ -41,12 +44,15 @@ var (
skipTimeoutCommit
=
false
createEmptyBlocks
=
false
fastSync
=
false
preExec
=
false
createEmptyBlocksInterval
int32
// second
validatorNodes
=
[]
string
{
"127.0.0.1:46656"
}
peerGossipSleepDuration
int32
=
1
00
peerGossipSleepDuration
int32
=
2
00
peerQueryMaj23SleepDuration
int32
=
2000
zeroHash
[
32
]
byte
random
*
rand
.
Rand
signName
=
"ed25519"
useAggSig
=
false
)
func
init
()
{
...
...
@@ -65,7 +71,6 @@ type Client struct {
pubKey
string
csState
*
ConsensusState
csStore
*
ConsensusStore
// save consensus state
crypto
crypto
.
Crypto
node
*
Node
txsAvailable
chan
int64
stopC
chan
struct
{}
...
...
@@ -73,6 +78,7 @@ type Client struct {
type
subConfig
struct
{
Genesis
string
`json:"genesis"`
GenesisAmount
int64
`json:"genesisAmount"`
GenesisBlockTime
int64
`json:"genesisBlockTime"`
TimeoutTxAvail
int32
`json:"timeoutTxAvail"`
TimeoutPropose
int32
`json:"timeoutPropose"`
...
...
@@ -87,9 +93,12 @@ type subConfig struct {
CreateEmptyBlocksInterval
int32
`json:"createEmptyBlocksInterval"`
ValidatorNodes
[]
string
`json:"validatorNodes"`
FastSync
bool
`json:"fastSync"`
PreExec
bool
`json:"preExec"`
SignName
string
`json:"signName"`
UseAggregateSignature
bool
`json:"useAggregateSignature"`
}
func
(
client
*
Client
)
applyConfig
(
sub
[]
byte
)
{
func
applyConfig
(
sub
[]
byte
)
{
var
subcfg
subConfig
if
sub
!=
nil
{
types
.
MustDecode
(
sub
,
&
subcfg
)
...
...
@@ -97,6 +106,9 @@ func (client *Client) applyConfig(sub []byte) {
if
subcfg
.
Genesis
!=
""
{
genesis
=
subcfg
.
Genesis
}
if
subcfg
.
GenesisAmount
>
0
{
genesisAmount
=
subcfg
.
GenesisAmount
}
if
subcfg
.
GenesisBlockTime
>
0
{
genesisBlockTime
=
subcfg
.
GenesisBlockTime
}
...
...
@@ -133,6 +145,11 @@ func (client *Client) applyConfig(sub []byte) {
validatorNodes
=
subcfg
.
ValidatorNodes
}
fastSync
=
subcfg
.
FastSync
preExec
=
subcfg
.
PreExec
if
subcfg
.
SignName
!=
""
{
signName
=
subcfg
.
SignName
}
useAggSig
=
subcfg
.
UseAggregateSignature
}
// DefaultDBProvider returns a database using the DBBackend and DBDir
...
...
@@ -144,37 +161,47 @@ func DefaultDBProvider(name string) dbm.DB {
// New ...
func
New
(
cfg
*
types
.
Consensus
,
sub
[]
byte
)
queue
.
Module
{
tendermintlog
.
Info
(
"Start to create tendermint client"
)
applyConfig
(
sub
)
//init rand
ttypes
.
Init
()
genDoc
,
err
:=
ttypes
.
GenesisDocFromFile
(
"genesis.json"
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"
NewTendermintClient"
,
"msg"
,
"GenesisDocFromFile failded"
,
"error"
,
err
)
signType
,
ok
:=
ttypes
.
SignMap
[
signName
]
if
!
ok
{
tendermintlog
.
Error
(
"
Invalid sign name"
)
return
nil
}
cr
,
err
:=
crypto
.
New
(
types
.
GetSignName
(
""
,
types
.
ED25519
))
ttypes
.
CryptoName
=
types
.
GetSignName
(
""
,
signType
)
cr
,
err
:=
crypto
.
New
(
ttypes
.
CryptoName
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"NewTendermintClient"
,
"err"
,
err
)
return
nil
}
ttypes
.
ConsensusCrypto
=
cr
priv
,
err
:=
cr
.
GenKey
()
if
useAggSig
{
_
,
err
=
crypto
.
ToAggregate
(
ttypes
.
ConsensusCrypto
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"NewTendermintClient"
,
"GenKey err"
,
err
)
tendermintlog
.
Error
(
"ConsensusCrypto not support aggregate signature"
,
"name"
,
ttypes
.
CryptoName
)
return
nil
}
}
genDoc
,
err
:=
ttypes
.
GenesisDocFromFile
(
"genesis.json"
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"NewTendermintClient"
,
"msg"
,
"GenesisDocFromFile fail"
,
"error"
,
err
)
return
nil
}
privValidator
:=
ttypes
.
LoadOrGenPrivValidatorFS
(
"priv_validator.json"
)
if
privValidator
==
nil
{
tendermintlog
.
Error
(
"NewTendermintClient create priv_validator file fail
ed
"
)
tendermintlog
.
Error
(
"NewTendermintClient create priv_validator file fail"
)
return
nil
}
ttypes
.
InitMessageMap
()
priv
:=
privValidator
.
PrivKey
pubkey
:=
privValidator
.
GetPubKey
()
.
KeyString
()
c
:=
drivers
.
NewBaseClient
(
cfg
)
client
:=
&
Client
{
...
...
@@ -184,21 +211,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
privKey
:
priv
,
pubKey
:
pubkey
,
csStore
:
NewConsensusStore
(),
crypto
:
cr
,
txsAvailable
:
make
(
chan
int64
,
1
),
stopC
:
make
(
chan
struct
{},
1
),
}
c
.
SetChild
(
client
)
client
.
applyConfig
(
sub
)
return
client
}
// PrivValidator returns the Node's PrivValidator.
func
(
client
*
Client
)
PrivValidator
()
ttypes
.
PrivValidator
{
return
client
.
privValidator
}
// GenesisDoc returns the Node's GenesisDoc.
func
(
client
*
Client
)
GenesisDoc
()
*
ttypes
.
GenesisDoc
{
return
client
.
genesisDoc
...
...
@@ -216,6 +235,7 @@ func (client *Client) GenesisState() *State {
// Close TODO:may need optimize
func
(
client
*
Client
)
Close
()
{
client
.
BaseClient
.
Close
()
client
.
node
.
Stop
()
client
.
stopC
<-
struct
{}{}
tendermintlog
.
Info
(
"consensus tendermint closed"
)
...
...
@@ -335,7 +355,7 @@ func (client *Client) CreateGenesisTx() (ret []*types.Transaction) {
//gen payload
g
:=
&
cty
.
CoinsAction_Genesis
{}
g
.
Genesis
=
&
types
.
AssetsGenesis
{}
g
.
Genesis
.
Amount
=
1e8
*
types
.
Coin
g
.
Genesis
.
Amount
=
genesisAmount
*
types
.
Coin
tx
.
Payload
=
types
.
Encode
(
&
cty
.
CoinsAction
{
Value
:
g
,
Ty
:
cty
.
CoinsActionGenesis
})
ret
=
append
(
ret
,
&
tx
)
return
...
...
@@ -405,10 +425,13 @@ func (client *Client) ProcEvent(msg *queue.Message) bool {
// CreateBlock a routine monitor whether some transactions available and tell client by available channel
func
(
client
*
Client
)
CreateBlock
()
{
issleep
:=
true
for
{
if
client
.
IsClosed
()
{
tendermintlog
.
Info
(
"CreateBlock quit"
)
break
}
if
!
client
.
csState
.
IsRunning
()
{
tendermintlog
.
Error
(
"consensus not running now
"
)
tendermintlog
.
Info
(
"consensus not running
"
)
time
.
Sleep
(
time
.
Second
)
continue
}
...
...
@@ -483,7 +506,6 @@ func (client *Client) BuildBlock() *types.Block {
client
.
AddTxsToBlock
(
&
newblock
,
txs
)
//固定难度
newblock
.
Difficulty
=
cfg
.
GetP
(
0
)
.
PowLimitBits
//newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
newblock
.
BlockTime
=
types
.
Now
()
.
Unix
()
if
lastBlock
.
BlockTime
>=
newblock
.
BlockTime
{
newblock
.
BlockTime
=
lastBlock
.
BlockTime
+
1
...
...
@@ -498,6 +520,9 @@ func (client *Client) CommitBlock(block *types.Block) error {
if
retErr
!=
nil
{
tendermintlog
.
Info
(
"CommitBlock fail"
,
"err"
,
retErr
)
if
client
.
WaitBlock
(
block
.
Height
)
{
if
!
preExec
{
return
nil
}
curBlock
,
err
:=
client
.
RequestBlock
(
block
.
Height
)
if
err
==
nil
{
if
bytes
.
Equal
(
curBlock
.
Hash
(
cfg
),
block
.
Hash
(
cfg
))
{
...
...
@@ -636,7 +661,7 @@ func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) {
return
&
tmtypes
.
ValidatorSet
{
Validators
:
validators
,
Proposer
:
&
tmtypes
.
Validator
{}},
nil
}
//比较newBlock是不是最优区块
//
CmpBestBlock
比较newBlock是不是最优区块
func
(
client
*
Client
)
CmpBestBlock
(
newBlock
*
types
.
Block
,
cmpBlock
*
types
.
Block
)
bool
{
return
false
}
plugin/consensus/tendermint/tendermint_test.go
View file @
34c89f73
...
...
@@ -272,13 +272,12 @@ func CheckState(t *testing.T, client *Client) {
assert
.
Equal
(
t
,
client
.
csState
.
Prevote
(
0
),
1000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
Precommit
(
0
),
1000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerGossipSleep
(),
1
00
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerGossipSleep
(),
2
00
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerQueryMaj23Sleep
(),
2000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
IsProposer
(),
true
)
assert
.
Nil
(
t
,
client
.
csState
.
GetPrevotesState
(
state
.
LastBlockHeight
,
0
,
nil
))
assert
.
Nil
(
t
,
client
.
csState
.
GetPrecommitsState
(
state
.
LastBlockHeight
,
0
,
nil
))
assert
.
NotEmpty
(
t
,
client
.
PrivValidator
())
assert
.
NotEmpty
(
t
,
client
.
csState
.
GetPrivValidator
())
assert
.
Len
(
t
,
client
.
GenesisDoc
()
.
Validators
,
1
)
msg1
,
err
:=
client
.
Query_IsHealthy
(
&
types
.
ReqNil
{})
...
...
plugin/consensus/tendermint/tools/nonePerf.go
View file @
34c89f73
...
...
@@ -139,7 +139,7 @@ func Put(ip string, size string, privkey string) {
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
return
}
url
:=
"http://"
+
ip
+
":
9
801"
url
:=
"http://"
+
ip
+
":
8
801"
if
privkey
==
""
{
_
,
priv
:=
genaddress
()
privkey
=
common
.
ToHex
(
priv
.
Bytes
())
...
...
plugin/consensus/tendermint/types/block.go
View file @
34c89f73
...
...
@@ -13,18 +13,11 @@ import (
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle"
"github.com/33cn/chain33/types"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
)
var
(
blocklog
=
log15
.
New
(
"module"
,
"tendermint-block"
)
// ConsensusCrypto define
ConsensusCrypto
crypto
.
Crypto
)
// BlockID struct
type
BlockID
struct
{
tmtypes
.
BlockID
...
...
@@ -88,11 +81,6 @@ func (b *TendermintBlock) ValidateBasic() error {
return
errors
.
New
(
"Zero Header.Height"
)
}
newTxs
:=
int64
(
len
(
b
.
Data
.
Txs
))
if
b
.
Header
.
NumTxs
!=
newTxs
{
return
fmt
.
Errorf
(
"Wrong Header.NumTxs. Expected %v, got %v"
,
newTxs
,
b
.
Header
.
NumTxs
)
}
if
b
.
Header
.
TotalTxs
<
0
{
return
errors
.
New
(
"Negative Header.TotalTxs"
)
}
...
...
@@ -192,7 +180,7 @@ func (h *Header) Hash() []byte {
}
bytes
,
err
:=
json
.
Marshal
(
h
)
if
err
!=
nil
{
block
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
tt
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
...
...
@@ -254,6 +242,9 @@ func (commit *Commit) FirstPrecommit() *tmtypes.Vote {
// Height returns the height of the commit
func
(
commit
*
Commit
)
Height
()
int64
{
if
commit
.
AggVote
!=
nil
{
return
commit
.
AggVote
.
Height
}
if
len
(
commit
.
Precommits
)
==
0
{
return
0
}
...
...
@@ -262,6 +253,9 @@ func (commit *Commit) Height() int64 {
// Round returns the round of the commit
func
(
commit
*
Commit
)
Round
()
int
{
if
commit
.
AggVote
!=
nil
{
return
int
(
commit
.
AggVote
.
Round
)
}
if
len
(
commit
.
Precommits
)
==
0
{
return
0
}
...
...
@@ -283,6 +277,10 @@ func (commit *Commit) Size() int {
// BitArray returns a BitArray of which validators voted in this commit
func
(
commit
*
Commit
)
BitArray
()
*
BitArray
{
if
commit
.
AggVote
!=
nil
{
bitArray
:=
&
BitArray
{
TendermintBitArray
:
commit
.
AggVote
.
ValidatorArray
}
return
bitArray
.
copy
()
}
if
commit
.
bitArray
==
nil
{
commit
.
bitArray
=
NewBitArray
(
len
(
commit
.
Precommits
))
for
i
,
precommit
:=
range
commit
.
Precommits
{
...
...
@@ -301,7 +299,16 @@ func (commit *Commit) GetByIndex(index int) *Vote {
// IsCommit returns true if there is at least one vote
func
(
commit
*
Commit
)
IsCommit
()
bool
{
return
len
(
commit
.
Precommits
)
!=
0
return
len
(
commit
.
Precommits
)
!=
0
||
commit
.
AggVote
!=
nil
}
// GetAggVote ...
func
(
commit
*
Commit
)
GetAggVote
()
*
AggVote
{
if
commit
==
nil
{
return
nil
}
aggVote
:=
&
AggVote
{
commit
.
AggVote
}
return
aggVote
.
Copy
()
}
// ValidateBasic performs basic validation that doesn't involve state data.
...
...
@@ -338,12 +345,28 @@ func (commit *Commit) ValidateBasic() error {
round
,
precommit
.
Round
)
}
}
// validate the aggVote
if
commit
.
AggVote
!=
nil
{
if
commit
.
AggVote
.
Type
!=
uint32
(
VoteTypePrecommit
)
{
return
fmt
.
Errorf
(
"Invalid aggVote type. Expected Precommit, got %v"
,
commit
.
AggVote
.
Type
)
}
if
commit
.
AggVote
.
Height
!=
height
{
return
fmt
.
Errorf
(
"Invalid aggVote height. Expected %v, got %v"
,
height
,
commit
.
AggVote
.
Height
)
}
if
int
(
commit
.
AggVote
.
Round
)
!=
round
{
return
fmt
.
Errorf
(
"Invalid aggVote round. Expected %v, got %v"
,
round
,
commit
.
AggVote
.
Round
)
}
}
return
nil
}
// Hash returns the hash of the commit
func
(
commit
*
Commit
)
Hash
()
[]
byte
{
if
commit
.
hash
==
nil
{
if
commit
.
AggVote
!=
nil
{
aggVote
:=
&
AggVote
{
AggVote
:
commit
.
AggVote
}
commit
.
hash
=
aggVote
.
Hash
()
}
else
{
bs
:=
make
([][]
byte
,
len
(
commit
.
Precommits
))
for
i
,
item
:=
range
commit
.
Precommits
{
precommit
:=
Vote
{
Vote
:
item
}
...
...
@@ -351,6 +374,7 @@ func (commit *Commit) Hash() []byte {
}
commit
.
hash
=
merkle
.
GetMerkleRoot
(
bs
)
}
}
return
commit
.
hash
}
...
...
@@ -366,9 +390,11 @@ func (commit *Commit) StringIndented(indent string) string {
return
Fmt
(
`Commit{
%s BlockID: %v
%s Precommits: %v
%s AggVote: %v
%s}#%v`
,
indent
,
commit
.
BlockID
,
indent
,
strings
.
Join
(
precommitStrings
,
"
\n
"
+
indent
+
" "
),
indent
,
commit
.
AggVote
.
String
(),
indent
,
commit
.
hash
)
}
...
...
plugin/consensus/tendermint/types/
errors
.go
→
plugin/consensus/tendermint/types/
const
.go
View file @
34c89f73
...
...
@@ -4,7 +4,17 @@
package
types
import
"errors"
import
(
"errors"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
const
(
AuthBLS
=
259
)
var
(
// ErrHeightLessThanOne error type
...
...
@@ -18,3 +28,17 @@ var (
// ErrLastBlockID error type
ErrLastBlockID
=
errors
.
New
(
"ErrLastBlockID"
)
)
var
(
ttlog
=
log15
.
New
(
"module"
,
"tendermint-types"
)
// ConsensusCrypto define
ConsensusCrypto
crypto
.
Crypto
CryptoName
string
// SignMap define sign type
SignMap
=
map
[
string
]
int
{
"secp256k1"
:
types
.
SECP256K1
,
"ed25519"
:
types
.
ED25519
,
"sm2"
:
types
.
SM2
,
"bls"
:
AuthBLS
,
}
)
plugin/consensus/tendermint/types/height_vote_set.go
View file @
34c89f73
...
...
@@ -138,6 +138,30 @@ func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err er
return
}
// AddAggVote Duplicate votes return added=false, err=nil.
// By convention, peerKey is "" if origin is self.
func
(
hvs
*
HeightVoteSet
)
AddAggVote
(
vote
*
AggVote
,
peerID
string
)
(
added
bool
,
err
error
)
{
hvs
.
mtx
.
Lock
()
defer
hvs
.
mtx
.
Unlock
()
if
!
IsVoteTypeValid
(
byte
(
vote
.
Type
))
{
return
}
round
:=
int
(
vote
.
Round
)
voteSet
:=
hvs
.
getVoteSet
(
round
,
byte
(
vote
.
Type
))
if
voteSet
==
nil
{
if
rndz
:=
hvs
.
peerCatchupRounds
[
peerID
];
len
(
rndz
)
<
2
{
hvs
.
addRound
(
int
(
vote
.
Round
))
voteSet
=
hvs
.
getVoteSet
(
round
,
byte
(
vote
.
Type
))
hvs
.
peerCatchupRounds
[
peerID
]
=
append
(
rndz
,
round
)
}
else
{
err
=
errors
.
New
(
"Peer has sent a aggregate vote that does not match our round for more than one round"
)
return
}
}
added
,
err
=
voteSet
.
AddAggVote
(
vote
)
return
}
// Prevotes ...
func
(
hvs
*
HeightVoteSet
)
Prevotes
(
round
int
)
*
VoteSet
{
hvs
.
mtx
.
Lock
()
...
...
plugin/consensus/tendermint/types/params.go
View file @
34c89f73
...
...
@@ -113,7 +113,7 @@ func (params *ConsensusParams) Validate() error {
func
(
params
*
ConsensusParams
)
Hash
()
[]
byte
{
bytes
,
err
:=
json
.
Marshal
(
params
)
if
err
!=
nil
{
block
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
tt
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
...
...
plugin/consensus/tendermint/types/priv_validator.go
View file @
34c89f73
...
...
@@ -6,6 +6,7 @@ package types
import
(
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
...
...
@@ -14,8 +15,6 @@ import (
"sync"
"time"
"encoding/hex"
"github.com/33cn/chain33/common/crypto"
)
...
...
@@ -296,15 +295,15 @@ func (pv *PrivValidatorImp) save() {
LastStep
:
pv
.
LastStep
,
LastSignature
:
nil
,
}
privValFS
.
PrivKey
=
KeyText
{
Kind
:
"ed25519"
,
Data
:
Fmt
(
"%X"
,
pv
.
PrivKey
.
Bytes
()[
:
])}
privValFS
.
PubKey
=
KeyText
{
Kind
:
"ed25519"
,
Data
:
pv
.
PubKey
.
KeyString
()}
privValFS
.
PrivKey
=
KeyText
{
Kind
:
CryptoName
,
Data
:
Fmt
(
"%X"
,
pv
.
PrivKey
.
Bytes
()[
:
])}
privValFS
.
PubKey
=
KeyText
{
Kind
:
CryptoName
,
Data
:
pv
.
PubKey
.
KeyString
()}
if
len
(
pv
.
LastSignBytes
)
!=
0
{
tmp
:=
Fmt
(
"%X"
,
pv
.
LastSignBytes
[
:
])
privValFS
.
LastSignBytes
=
tmp
}
if
pv
.
LastSignature
!=
nil
{
sig
:=
Fmt
(
"%X"
,
pv
.
LastSignature
.
Bytes
()[
:
])
privValFS
.
LastSignature
=
&
KeyText
{
Kind
:
"ed25519"
,
Data
:
sig
}
privValFS
.
LastSignature
=
&
KeyText
{
Kind
:
CryptoName
,
Data
:
sig
}
}
jsonBytes
,
err
:=
json
.
Marshal
(
privValFS
)
if
err
!=
nil
{
...
...
plugin/consensus/tendermint/types/round_state.go
View file @
34c89f73
...
...
@@ -42,6 +42,7 @@ const (
ProposalHeartbeatID
=
byte
(
0x08
)
ProposalBlockID
=
byte
(
0x09
)
ValidBlockID
=
byte
(
0x0a
)
AggVoteID
=
byte
(
0x0b
)
PacketTypePing
=
byte
(
0xff
)
PacketTypePong
=
byte
(
0xfe
)
...
...
@@ -60,6 +61,7 @@ func InitMessageMap() {
ProposalHeartbeatID
:
reflect
.
TypeOf
(
tmtypes
.
Heartbeat
{}),
ProposalBlockID
:
reflect
.
TypeOf
(
tmtypes
.
TendermintBlock
{}),
ValidBlockID
:
reflect
.
TypeOf
(
tmtypes
.
ValidBlockMsg
{}),
AggVoteID
:
reflect
.
TypeOf
(
tmtypes
.
AggVote
{}),
}
}
...
...
@@ -186,6 +188,7 @@ type PeerRoundState struct {
LastCommit
*
BitArray
// All commit precommits of commit for last height.
CatchupCommitRound
int
// Round that we have commit for. Not necessarily unique. -1 if none.
CatchupCommit
*
BitArray
// All commit precommits peer has for this height & CatchupCommitRound
AggPrecommit
bool
// True if peer has aggregate precommit for this round
}
// String returns a string representation of the PeerRoundState
...
...
@@ -204,17 +207,19 @@ func (prs PeerRoundState) StringIndented(indent string) string {
%s Prevotes %v
%s Precommits %v
%s LastCommit %v (round %v)
%s Catchup %v (round %v)
%s CatchupCommit %v (round %v)
%s AggPrecommit %v
%s}`
,
indent
,
prs
.
Height
,
prs
.
Round
,
prs
.
Step
,
prs
.
StartTime
,
indent
,
prs
.
Proposal
,
indent
,
prs
.
ProposalBlock
,
indent
,
prs
.
ProposalBlock
,
indent
,
prs
.
ProposalBlock
Hash
,
indent
,
prs
.
ProposalPOL
,
prs
.
ProposalPOLRound
,
indent
,
prs
.
Prevotes
,
indent
,
prs
.
Precommits
,
indent
,
prs
.
LastCommit
,
prs
.
LastCommitRound
,
indent
,
prs
.
CatchupCommit
,
prs
.
CatchupCommitRound
,
indent
,
prs
.
AggPrecommit
,
indent
)
}
...
...
@@ -274,6 +279,12 @@ type CanonicalJSONOnceVote struct {
Vote
CanonicalJSONVote
`json:"vote"`
}
// CanonicalJSONOnceAggVote ...
type
CanonicalJSONOnceAggVote
struct
{
ChainID
string
`json:"chain_id"`
AggVote
CanonicalJSONVote
`json:"agg_vote"`
}
// CanonicalJSONOnceHeartbeat ...
type
CanonicalJSONOnceHeartbeat
struct
{
ChainID
string
`json:"chain_id"`
...
...
@@ -305,11 +316,26 @@ func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
// CanonicalVote ...
func
CanonicalVote
(
vote
*
Vote
)
CanonicalJSONVote
{
timestamp
:=
""
if
!
vote
.
UseAggSig
{
timestamp
=
CanonicalTime
(
time
.
Unix
(
0
,
vote
.
Timestamp
))
}
return
CanonicalJSONVote
{
BlockID
:
CanonicalJSONBlockID
{
Hash
:
vote
.
BlockID
.
Hash
},
Height
:
vote
.
Height
,
Round
:
int
(
vote
.
Round
),
Timestamp
:
timestamp
,
Type
:
byte
(
vote
.
Type
),
}
}
// CanonicalAggVote ...
func
CanonicalAggVote
(
vote
*
AggVote
)
CanonicalJSONVote
{
return
CanonicalJSONVote
{
BlockID
:
CanonicalJSONBlockID
{
Hash
:
vote
.
BlockID
.
Hash
},
Height
:
vote
.
Height
,
Round
:
int
(
vote
.
Round
),
Timestamp
:
CanonicalTime
(
time
.
Unix
(
0
,
vote
.
Timestamp
))
,
Timestamp
:
""
,
Type
:
byte
(
vote
.
Type
),
}
}
...
...
plugin/consensus/tendermint/types/signable.go
View file @
34c89f73
...
...
@@ -13,7 +13,6 @@ import (
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
)
...
...
@@ -27,7 +26,7 @@ var (
ErrVoteNonDeterministicSignature
=
errors
.
New
(
"Non-deterministic signature"
)
ErrVoteConflict
=
errors
.
New
(
"Conflicting vote"
)
ErrVoteNil
=
errors
.
New
(
"Nil vote"
)
votelog
=
log15
.
New
(
"module"
,
"tendermint-
vote"
)
ErrAggVoteNil
=
errors
.
New
(
"Nil aggregate
vote"
)
)
// Signable is an interface for all signable things.
...
...
@@ -156,7 +155,7 @@ func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error
byteVote
,
e
:=
json
.
Marshal
(
&
canonical
)
if
e
!=
nil
{
*
err
=
e
vote
log
.
Error
(
"vote WriteSignBytes marshal failed"
,
"err"
,
e
)
tt
log
.
Error
(
"vote WriteSignBytes marshal failed"
,
"err"
,
e
)
return
}
number
,
writeErr
:=
w
.
Write
(
byteVote
)
...
...
@@ -200,7 +199,7 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
vote
.
Signature
)
if
err
!=
nil
{
votelog
.
Error
(
"vote Verify failed
"
,
"err"
,
err
)
ttlog
.
Error
(
"vote Verify fail
"
,
"err"
,
err
)
return
err
}
...
...
@@ -217,7 +216,109 @@ func (vote *Vote) Hash() []byte {
}
bytes
,
err
:=
json
.
Marshal
(
vote
)
if
err
!=
nil
{
votelog
.
Error
(
"vote hash marshal failed"
,
"err"
,
err
)
ttlog
.
Error
(
"vote hash marshal failed"
,
"err"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
}
// AggVote Represents a prevote, precommit, or commit vote from validators for consensus.
type
AggVote
struct
{
*
tmtypes
.
AggVote
}
// WriteSignBytes ...
func
(
aggVote
*
AggVote
)
WriteSignBytes
(
chainID
string
,
w
io
.
Writer
,
n
*
int
,
err
*
error
)
{
if
*
err
!=
nil
{
return
}
canonical
:=
CanonicalJSONOnceAggVote
{
chainID
,
CanonicalAggVote
(
aggVote
),
}
byteVote
,
e
:=
json
.
Marshal
(
&
canonical
)
if
e
!=
nil
{
*
err
=
e
ttlog
.
Error
(
"aggVote WriteSignBytes marshal failed"
,
"err"
,
e
)
return
}
number
,
writeErr
:=
w
.
Write
(
byteVote
)
*
n
=
number
*
err
=
writeErr
}
// Verify ...
func
(
aggVote
*
AggVote
)
Verify
(
chainID
string
,
valSet
*
ValidatorSet
)
error
{
aggSig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
aggVote
.
Signature
)
if
err
!=
nil
{
return
errors
.
New
(
"invalid aggregate signature"
)
}
pubs
:=
make
([]
crypto
.
PubKey
,
0
)
arr
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
for
i
,
val
:=
range
valSet
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
pub
,
_
:=
ConsensusCrypto
.
PubKeyFromBytes
(
val
.
PubKey
)
pubs
=
append
(
pubs
,
pub
)
}
}
origVote
:=
&
Vote
{
&
tmtypes
.
Vote
{
BlockID
:
aggVote
.
BlockID
,
Height
:
aggVote
.
Height
,
Round
:
aggVote
.
Round
,
Timestamp
:
aggVote
.
Timestamp
,
Type
:
aggVote
.
Type
,
UseAggSig
:
true
,
}}
aggr
,
err
:=
crypto
.
ToAggregate
(
ConsensusCrypto
)
if
err
!=
nil
{
return
err
}
err
=
aggr
.
VerifyAggregatedOne
(
pubs
,
SignBytes
(
chainID
,
origVote
),
aggSig
)
if
err
!=
nil
{
ttlog
.
Error
(
"aggVote Verify fail"
,
"err"
,
err
,
"aggVote"
,
aggVote
,
"aggSig"
,
aggSig
)
return
err
}
return
nil
}
// Copy ...
func
(
aggVote
*
AggVote
)
Copy
()
*
AggVote
{
copy
:=
*
aggVote
return
&
copy
}
func
(
aggVote
*
AggVote
)
String
()
string
{
if
aggVote
==
nil
{
return
"nil-AggVote"
}
var
typeString
string
switch
byte
(
aggVote
.
Type
)
{
case
VoteTypePrevote
:
typeString
=
"Prevote"
case
VoteTypePrecommit
:
typeString
=
"Precommit"
default
:
PanicSanity
(
"Unknown vote type"
)
}
bitArray
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
return
fmt
.
Sprintf
(
"AggVote{%X %v/%02d/%v(%v) %X %X @ %s %v}"
,
Fingerprint
(
aggVote
.
ValidatorAddress
),
aggVote
.
Height
,
aggVote
.
Round
,
aggVote
.
Type
,
typeString
,
Fingerprint
(
aggVote
.
BlockID
.
Hash
),
aggVote
.
Signature
,
CanonicalTime
(
time
.
Unix
(
0
,
aggVote
.
Timestamp
)),
bitArray
)
}
// Hash ...
func
(
aggVote
*
AggVote
)
Hash
()
[]
byte
{
if
aggVote
==
nil
{
return
nil
}
bytes
,
err
:=
json
.
Marshal
(
aggVote
)
if
err
!=
nil
{
ttlog
.
Error
(
"aggVote hash marshal failed"
,
"err"
,
err
)
return
nil
}
...
...
plugin/consensus/tendermint/types/validator_set.go
View file @
34c89f73
...
...
@@ -12,13 +12,10 @@ import (
"strings"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle"
"github.com/pkg/errors"
)
var
validatorsetlog
=
log15
.
New
(
"module"
,
"tendermint-val"
)
// Validator ...
type
Validator
struct
{
Address
[]
byte
`json:"address"`
...
...
@@ -313,7 +310,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
if
valSet
.
Size
()
!=
len
(
commit
.
Precommits
)
{
return
fmt
.
Errorf
(
"Invalid commit -- wrong set size: %v vs %v"
,
valSet
.
Size
(),
len
(
commit
.
Precommits
))
}
validatorse
tlog
.
Debug
(
"VerifyCommit will get commit height"
,
"height"
,
commit
.
Height
())
t
tlog
.
Debug
(
"VerifyCommit will get commit height"
,
"height"
,
commit
.
Height
())
commitHeight
:=
commit
.
Height
()
if
height
!=
commitHeight
{
return
fmt
.
Errorf
(
"VerifyCommit 1 Invalid commit -- wrong height: %v vs %v"
,
height
,
commitHeight
)
...
...
@@ -322,6 +319,29 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
talliedVotingPower
:=
int64
(
0
)
round
:=
commit
.
Round
()
if
commit
.
AggVote
!=
nil
{
aggVote
:=
&
AggVote
{
AggVote
:
commit
.
AggVote
}
// Make sure the step matches
if
(
aggVote
.
Height
!=
height
)
||
(
int
(
aggVote
.
Round
)
!=
round
)
||
(
aggVote
.
Type
!=
uint32
(
VoteTypePrecommit
))
{
return
errors
.
Wrapf
(
ErrVoteUnexpectedStep
,
"Got %d/%d/%d, expected %d/%d/%d"
,
height
,
round
,
VoteTypePrecommit
,
aggVote
.
Height
,
aggVote
.
Round
,
aggVote
.
Type
)
}
// Check signature
err
:=
aggVote
.
Verify
(
chainID
,
valSet
)
if
err
!=
nil
{
return
err
}
// calc voting power
arr
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
for
i
,
val
:=
range
valSet
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
talliedVotingPower
+=
val
.
VotingPower
}
}
}
else
{
for
idx
,
item
:=
range
commit
.
Precommits
{
// may be nil if validator skipped.
if
item
==
nil
||
len
(
item
.
Signature
)
==
0
{
...
...
@@ -338,8 +358,8 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
return
fmt
.
Errorf
(
"Invalid commit -- not precommit @ index %v"
,
idx
)
}
_
,
val
:=
valSet
.
GetByIndex
(
idx
)
// Validate signature
// Validate signature
precommitSignBytes
:=
SignBytes
(
chainID
,
precommit
)
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
precommit
.
Signature
)
if
err
!=
nil
{
...
...
@@ -358,6 +378,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
// Good precommit!
talliedVotingPower
+=
val
.
VotingPower
}
}
if
talliedVotingPower
>
valSet
.
TotalVotingPower
()
*
2
/
3
{
return
nil
...
...
plugin/consensus/tendermint/types/vote_set.go
View file @
34c89f73
...
...
@@ -8,7 +8,9 @@ import (
"bytes"
"strings"
"sync"
"time"
"github.com/33cn/chain33/common/crypto"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
"github.com/pkg/errors"
)
...
...
@@ -63,6 +65,7 @@ type VoteSet struct {
maj23
*
tmtypes
.
BlockID
// First 2/3 majority seen
votesByBlock
map
[
string
]
*
blockVotes
// string(blockHash|blockParts) -> blockVotes
peerMaj23s
map
[
string
]
*
tmtypes
.
BlockID
// Maj23 for each peer
aggVote
*
AggVote
// aggregate vote
}
// NewVoteSet Constructs a new VoteSet struct used to accumulate votes for given height/round.
...
...
@@ -82,6 +85,7 @@ func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *
maj23
:
nil
,
votesByBlock
:
make
(
map
[
string
]
*
blockVotes
,
valSet
.
Size
()),
peerMaj23s
:
make
(
map
[
string
]
*
tmtypes
.
BlockID
),
aggVote
:
nil
,
}
}
...
...
@@ -133,7 +137,7 @@ func (voteSet *VoteSet) Size() int {
// NOTE: Vote must not be nil
func
(
voteSet
*
VoteSet
)
AddVote
(
vote
*
Vote
)
(
added
bool
,
err
error
)
{
if
voteSet
==
nil
{
PanicSanity
(
"AddVote() on nil VoteS
et"
)
return
false
,
errors
.
New
(
"nil vote s
et"
)
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
...
...
@@ -291,6 +295,146 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
return
true
,
conflicting
}
// AddAggVote Returns added=true if aggVote is valid and new
func
(
voteSet
*
VoteSet
)
AddAggVote
(
vote
*
AggVote
)
(
bool
,
error
)
{
if
voteSet
==
nil
{
return
false
,
errors
.
New
(
"nil vote set"
)
}
if
vote
==
nil
{
return
false
,
ErrAggVoteNil
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
valAddr
:=
vote
.
ValidatorAddress
valset
:=
voteSet
.
valSet
if
len
(
valAddr
)
==
0
{
return
false
,
errors
.
Wrap
(
ErrVoteInvalidValidatorAddress
,
"Empty address"
)
}
// Make sure the step matches
if
(
vote
.
Height
!=
voteSet
.
height
)
||
(
int
(
vote
.
Round
)
!=
voteSet
.
round
)
||
(
vote
.
Type
!=
uint32
(
voteSet
.
voteType
))
{
return
false
,
errors
.
Wrapf
(
ErrVoteUnexpectedStep
,
"Got %d/%d/%d, expected %d/%d/%d"
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
vote
.
Height
,
vote
.
Round
,
vote
.
Type
)
}
// Ensure that signer is proposer
propAddr
:=
valset
.
Proposer
.
Address
if
!
bytes
.
Equal
(
valAddr
,
propAddr
)
{
return
false
,
errors
.
Wrapf
(
ErrVoteInvalidValidatorAddress
,
"aggVote.ValidatorAddress (%X) does not match proposer address (%X)"
,
valAddr
,
propAddr
)
}
// If we already know of this vote, return false
if
voteSet
.
aggVote
!=
nil
{
if
bytes
.
Equal
(
voteSet
.
aggVote
.
Signature
,
vote
.
Signature
)
{
return
false
,
nil
// duplicate
}
return
false
,
errors
.
Wrapf
(
ErrVoteNonDeterministicSignature
,
"Existing vote: %v; New vote: %v"
,
voteSet
.
aggVote
,
vote
)
}
// Check signature
err
:=
vote
.
Verify
(
voteSet
.
chainID
,
voteSet
.
valSet
)
if
err
!=
nil
{
return
false
,
err
}
// Check maj32
sum
:=
int64
(
0
)
arr
:=
&
BitArray
{
TendermintBitArray
:
vote
.
ValidatorArray
}
for
i
,
val
:=
range
valset
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
sum
+=
val
.
VotingPower
}
}
quorum
:=
voteSet
.
valSet
.
TotalVotingPower
()
*
2
/
3
+
1
if
sum
<
quorum
{
return
false
,
errors
.
New
(
"less than 2/3 total power"
)
}
voteSet
.
votesBitArray
=
arr
.
copy
()
voteSet
.
aggVote
=
vote
voteSet
.
maj23
=
vote
.
BlockID
voteSet
.
sum
=
sum
votesByBlock
:=
newBlockVotes
(
false
,
voteSet
.
valSet
.
Size
())
votesByBlock
.
bitArray
=
arr
.
copy
()
votesByBlock
.
sum
=
sum
voteSet
.
votesByBlock
[
string
(
voteSet
.
maj23
.
Hash
)]
=
votesByBlock
return
true
,
nil
}
// SetAggVote generate aggregate vote when voteSet have 2/3 majority
func
(
voteSet
*
VoteSet
)
SetAggVote
()
error
{
if
voteSet
==
nil
{
return
errors
.
New
(
"nil vote set"
)
}
if
voteSet
.
maj23
==
nil
{
return
errors
.
New
(
"no 2/3 majority in voteSet"
)
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
blockKey
:=
string
(
voteSet
.
maj23
.
Hash
)
votesByBlock
,
ok
:=
voteSet
.
votesByBlock
[
blockKey
]
if
!
ok
{
return
errors
.
New
(
"no 2/3 majority blockKey"
)
}
bitArray
:=
votesByBlock
.
bitArray
.
copy
()
sigs
:=
make
([]
crypto
.
Signature
,
0
)
for
_
,
vote
:=
range
votesByBlock
.
votes
{
if
vote
!=
nil
{
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
vote
.
Signature
)
if
err
!=
nil
{
return
errors
.
New
(
"invalid aggregate signature"
)
}
sigs
=
append
(
sigs
,
sig
)
}
}
aggr
,
err
:=
crypto
.
ToAggregate
(
ConsensusCrypto
)
if
err
!=
nil
{
return
err
}
aggSig
,
err
:=
aggr
.
Aggregate
(
sigs
)
if
err
!=
nil
{
return
err
}
aggVote
:=
&
AggVote
{
&
tmtypes
.
AggVote
{
ValidatorAddress
:
voteSet
.
valSet
.
Proposer
.
Address
,
ValidatorArray
:
bitArray
.
TendermintBitArray
,
Height
:
voteSet
.
height
,
Round
:
int32
(
voteSet
.
round
),
Timestamp
:
time
.
Now
()
.
UnixNano
(),
Type
:
uint32
(
voteSet
.
voteType
),
BlockID
:
voteSet
.
maj23
,
Signature
:
aggSig
.
Bytes
(),
}}
// Verify aggVote
err
=
aggVote
.
Verify
(
voteSet
.
chainID
,
voteSet
.
valSet
)
if
err
!=
nil
{
return
err
}
voteSet
.
aggVote
=
aggVote
return
nil
}
// GetAggVote ...
func
(
voteSet
*
VoteSet
)
GetAggVote
()
*
AggVote
{
if
voteSet
==
nil
{
return
nil
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
if
voteSet
.
aggVote
==
nil
{
return
nil
}
return
voteSet
.
aggVote
.
Copy
()
}
// SetPeerMaj23 If a peer claims that it has 2/3 majority for given blockKey, call this.
// NOTE: if there are too many peers, or too much peer churn,
// this can cause memory issues.
...
...
@@ -446,12 +590,12 @@ func (voteSet *VoteSet) StringIndented(indent string) string {
}
}
return
Fmt
(
`VoteSet{
%s H:%v R:%v T:%v
%s H:%v R:%v T:%v
+2/3:%X
%s %v
%s %v
%s %v
%s}`
,
indent
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
indent
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
voteSet
.
maj23
,
indent
,
strings
.
Join
(
voteStrings
,
"
\n
"
+
indent
+
" "
),
indent
,
voteSet
.
votesBitArray
,
indent
,
voteSet
.
peerMaj23s
,
...
...
@@ -491,10 +635,15 @@ func (voteSet *VoteSet) MakeCommit() *tmtypes.TendermintCommit {
votesCopy
[
i
]
=
&
tmtypes
.
Vote
{}
}
}
//copy(votesCopy, voteSet.votes)
var
aggVote
*
tmtypes
.
AggVote
if
voteSet
.
aggVote
!=
nil
{
copy
:=
voteSet
.
aggVote
.
Copy
()
aggVote
=
copy
.
AggVote
}
return
&
tmtypes
.
TendermintCommit
{
BlockID
:
voteSet
.
maj23
,
Precommits
:
votesCopy
,
AggVote
:
aggVote
,
}
}
...
...
@@ -549,4 +698,5 @@ type VoteSetReader interface {
BitArray
()
*
BitArray
GetByIndex
(
int
)
*
Vote
IsCommit
()
bool
GetAggVote
()
*
AggVote
}
plugin/crypto/bls/bls.go
0 → 100644
View file @
34c89f73
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
bls
import
(
"bytes"
"crypto/rand"
"errors"
"fmt"
"github.com/33cn/chain33/common/crypto"
"github.com/phoreproject/bls/g1pubs"
)
const
(
BLSPrivateKeyLength
=
32
BLSPublicKeyLength
=
48
BLSSignatureLength
=
96
)
// Driver driver
type
Driver
struct
{}
// GenKey create private key
func
(
d
Driver
)
GenKey
()
(
crypto
.
PrivKey
,
error
)
{
privKeyBytes
:=
new
([
BLSPrivateKeyLength
]
byte
)
priv
,
err
:=
g1pubs
.
RandKey
(
rand
.
Reader
)
if
err
!=
nil
{
return
nil
,
err
}
privBytes
:=
priv
.
Serialize
()
copy
(
privKeyBytes
[
:
],
privBytes
[
:
])
return
PrivKeyBLS
(
*
privKeyBytes
),
nil
}
// PrivKeyFromBytes create private key from bytes
func
(
d
Driver
)
PrivKeyFromBytes
(
b
[]
byte
)
(
privKey
crypto
.
PrivKey
,
err
error
)
{
if
len
(
b
)
!=
BLSPrivateKeyLength
{
return
nil
,
errors
.
New
(
"invalid bls priv key byte"
)
}
privKeyBytes
:=
new
([
BLSPrivateKeyLength
]
byte
)
copy
(
privKeyBytes
[
:
],
b
[
:
BLSPrivateKeyLength
])
priv
:=
g1pubs
.
DeserializeSecretKey
(
*
privKeyBytes
)
if
priv
==
nil
{
return
nil
,
errors
.
New
(
"invalid bls privkey"
)
}
privBytes
:=
priv
.
Serialize
()
copy
(
privKeyBytes
[
:
],
privBytes
[
:
])
return
PrivKeyBLS
(
*
privKeyBytes
),
nil
}
// PubKeyFromBytes create public key from bytes
func
(
d
Driver
)
PubKeyFromBytes
(
b
[]
byte
)
(
pubKey
crypto
.
PubKey
,
err
error
)
{
if
len
(
b
)
!=
BLSPublicKeyLength
{
return
nil
,
errors
.
New
(
"invalid bls pub key byte"
)
}
pubKeyBytes
:=
new
([
BLSPublicKeyLength
]
byte
)
copy
(
pubKeyBytes
[
:
],
b
[
:
])
return
PubKeyBLS
(
*
pubKeyBytes
),
nil
}
// SignatureFromBytes create signature from bytes
func
(
d
Driver
)
SignatureFromBytes
(
b
[]
byte
)
(
sig
crypto
.
Signature
,
err
error
)
{
sigBytes
:=
new
([
BLSSignatureLength
]
byte
)
copy
(
sigBytes
[
:
],
b
[
:
])
return
SignatureBLS
(
*
sigBytes
),
nil
}
//Aggregate aggregates signatures together into a new signature.
func
(
d
Driver
)
Aggregate
(
sigs
[]
crypto
.
Signature
)
(
crypto
.
Signature
,
error
)
{
if
len
(
sigs
)
==
0
{
return
nil
,
errors
.
New
(
"no signatures to aggregate"
)
}
g1sigs
:=
make
([]
*
g1pubs
.
Signature
,
0
,
len
(
sigs
))
for
i
,
sig
:=
range
sigs
{
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1sigs
=
append
(
g1sigs
,
g1sig
)
}
agsig
:=
g1pubs
.
AggregateSignatures
(
g1sigs
)
return
SignatureBLS
(
agsig
.
Serialize
()),
nil
}
//AggregatePublic aggregates public keys together into a new PublicKey.
func
(
d
Driver
)
AggregatePublic
(
pubs
[]
crypto
.
PubKey
)
(
crypto
.
PubKey
,
error
)
{
if
len
(
pubs
)
==
0
{
return
nil
,
errors
.
New
(
"no public keys to aggregate"
)
}
//blank public key
g1pubs
:=
g1pubs
.
NewAggregatePubkey
()
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
.
Aggregate
(
g1pub
)
}
return
PubKeyBLS
(
g1pubs
.
Serialize
()),
nil
}
// VerifyAggregatedOne verifies each public key against a message.
func
(
d
Driver
)
VerifyAggregatedOne
(
pubs
[]
crypto
.
PubKey
,
m
[]
byte
,
sig
crypto
.
Signature
)
error
{
g1pubs
:=
make
([]
*
g1pubs
.
PublicKey
,
0
,
len
(
pubs
))
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
=
append
(
g1pubs
,
g1pub
)
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
err
}
if
g1sig
.
VerifyAggregateCommon
(
g1pubs
,
m
)
{
return
nil
}
return
errors
.
New
(
"bls signature mismatch"
)
}
// VerifyAggregatedN verifies each public key against each message.
func
(
d
Driver
)
VerifyAggregatedN
(
pubs
[]
crypto
.
PubKey
,
ms
[][]
byte
,
sig
crypto
.
Signature
)
error
{
g1pubs
:=
make
([]
*
g1pubs
.
PublicKey
,
0
,
len
(
pubs
))
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
=
append
(
g1pubs
,
g1pub
)
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
err
}
if
len
(
g1pubs
)
!=
len
(
ms
)
{
return
fmt
.
Errorf
(
"different length of pubs and messages, %d vs %d"
,
len
(
g1pubs
),
len
(
ms
))
}
if
g1sig
.
VerifyAggregate
(
g1pubs
,
ms
)
{
return
nil
}
return
errors
.
New
(
"bls signature mismatch"
)
}
// ConvertToSignature convert to BLS Signature
func
ConvertToSignature
(
sig
crypto
.
Signature
)
(
*
g1pubs
.
Signature
,
error
)
{
// unwrap if needed
if
wrap
,
ok
:=
sig
.
(
SignatureS
);
ok
{
sig
=
wrap
.
Signature
}
sigBLS
,
ok
:=
sig
.
(
SignatureBLS
)
if
!
ok
{
return
nil
,
errors
.
New
(
"invalid bls signature"
)
}
g1sig
,
err
:=
g1pubs
.
DeserializeSignature
(
sigBLS
)
if
err
!=
nil
{
return
nil
,
err
}
return
g1sig
,
nil
}
// ConvertToPublicKey convert to BLS PublicKey
func
ConvertToPublicKey
(
pub
crypto
.
PubKey
)
(
*
g1pubs
.
PublicKey
,
error
)
{
pubBLS
,
ok
:=
pub
.
(
PubKeyBLS
)
if
!
ok
{
return
nil
,
errors
.
New
(
"invalid bls public key"
)
}
g1pub
,
err
:=
g1pubs
.
DeserializePublicKey
(
pubBLS
)
if
err
!=
nil
{
return
nil
,
err
}
return
g1pub
,
nil
}
// PrivKeyBLS PrivKey
type
PrivKeyBLS
[
BLSPrivateKeyLength
]
byte
// Bytes convert to bytes
func
(
privKey
PrivKeyBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
BLSPrivateKeyLength
)
copy
(
s
,
privKey
[
:
])
return
s
}
// Sign create signature
func
(
privKey
PrivKeyBLS
)
Sign
(
msg
[]
byte
)
crypto
.
Signature
{
priv
:=
g1pubs
.
DeserializeSecretKey
(
privKey
)
sig
:=
g1pubs
.
Sign
(
msg
,
priv
)
return
SignatureBLS
(
sig
.
Serialize
())
}
// PubKey convert to public key
func
(
privKey
PrivKeyBLS
)
PubKey
()
crypto
.
PubKey
{
priv
:=
g1pubs
.
DeserializeSecretKey
(
privKey
)
return
PubKeyBLS
(
g1pubs
.
PrivToPub
(
priv
)
.
Serialize
())
}
// Equals check privkey is equal
func
(
privKey
PrivKeyBLS
)
Equals
(
other
crypto
.
PrivKey
)
bool
{
if
otherSecp
,
ok
:=
other
.
(
PrivKeyBLS
);
ok
{
return
bytes
.
Equal
(
privKey
[
:
],
otherSecp
[
:
])
}
return
false
}
// String convert to string
func
(
privKey
PrivKeyBLS
)
String
()
string
{
return
fmt
.
Sprintf
(
"PrivKeyBLS{*****}"
)
}
// PubKeyBLS PubKey
type
PubKeyBLS
[
BLSPublicKeyLength
]
byte
// Bytes convert to bytes
func
(
pubKey
PubKeyBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
BLSPublicKeyLength
)
copy
(
s
,
pubKey
[
:
])
return
s
}
// VerifyBytes verify signature
func
(
pubKey
PubKeyBLS
)
VerifyBytes
(
msg
[]
byte
,
sig
crypto
.
Signature
)
bool
{
pub
,
err
:=
g1pubs
.
DeserializePublicKey
(
pubKey
)
if
err
!=
nil
{
fmt
.
Println
(
"invalid bls pubkey"
)
return
false
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
fmt
.
Println
(
"ConvertToSignature fail:"
,
err
)
return
false
}
return
g1pubs
.
Verify
(
msg
,
pub
,
g1sig
)
}
// String convert to string
func
(
pubKey
PubKeyBLS
)
String
()
string
{
return
fmt
.
Sprintf
(
"PubKeyBLS{%X}"
,
pubKey
[
:
])
}
// KeyString Must return the full bytes in hex.
// Used for map keying, etc.
func
(
pubKey
PubKeyBLS
)
KeyString
()
string
{
return
fmt
.
Sprintf
(
"%X"
,
pubKey
[
:
])
}
// Equals check public key is equal
func
(
pubKey
PubKeyBLS
)
Equals
(
other
crypto
.
PubKey
)
bool
{
if
otherSecp
,
ok
:=
other
.
(
PubKeyBLS
);
ok
{
return
bytes
.
Equal
(
pubKey
[
:
],
otherSecp
[
:
])
}
return
false
}
// SignatureBLS Signature
type
SignatureBLS
[
BLSSignatureLength
]
byte
// SignatureS signature struct
type
SignatureS
struct
{
crypto
.
Signature
}
// Bytes convert signature to bytes
func
(
sig
SignatureBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
len
(
sig
))
copy
(
s
,
sig
[
:
])
return
s
}
// IsZero check signature is zero
func
(
sig
SignatureBLS
)
IsZero
()
bool
{
return
len
(
sig
)
==
0
}
// String convert signature to string
func
(
sig
SignatureBLS
)
String
()
string
{
fingerprint
:=
make
([]
byte
,
len
(
sig
[
:
]))
copy
(
fingerprint
,
sig
[
:
])
return
fmt
.
Sprintf
(
"/%X.../"
,
fingerprint
)
}
// Equals check signature equals
func
(
sig
SignatureBLS
)
Equals
(
other
crypto
.
Signature
)
bool
{
if
otherEd
,
ok
:=
other
.
(
SignatureBLS
);
ok
{
return
bytes
.
Equal
(
sig
[
:
],
otherEd
[
:
])
}
return
false
}
// Name name
const
Name
=
"bls"
// ID id
const
ID
=
259
func
init
()
{
crypto
.
Register
(
Name
,
&
Driver
{})
crypto
.
RegisterType
(
Name
,
ID
)
}
plugin/crypto/bls/bls_test.go
0 → 100644
View file @
34c89f73
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
bls
import
(
"fmt"
"testing"
"github.com/33cn/chain33/common/crypto"
"github.com/stretchr/testify/assert"
)
var
blsDrv
=
&
Driver
{}
func
TestGenKey
(
t
*
testing
.
T
)
{
sk
,
err
:=
blsDrv
.
GenKey
()
assert
.
NoError
(
t
,
err
)
assert
.
NotEmpty
(
t
,
sk
)
pk
:=
sk
.
PubKey
()
assert
.
NotEmpty
(
t
,
pk
)
sk2
,
_
:=
blsDrv
.
GenKey
()
assert
.
NotEqual
(
t
,
sk
.
Bytes
(),
sk2
.
Bytes
(),
"should not generate two same key"
,
sk
,
sk2
)
}
func
TestSignAndVerify
(
t
*
testing
.
T
)
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
m1
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
// sign and verify
sig1
:=
sk
.
Sign
(
m1
)
ret
:=
pk
.
VerifyBytes
(
m1
,
sig1
)
assert
.
Equal
(
t
,
true
,
ret
)
// different message should have different signature
m2
:=
[]
byte
(
"message to be signed. 将要做签名的消息."
)
sig2
:=
sk
.
Sign
(
m2
)
assert
.
NotEqual
(
t
,
sig1
,
sig2
,
"different message got the same signature"
,
sig1
,
sig2
)
// different key should have different signature for a same message.
sk2
,
_
:=
blsDrv
.
GenKey
()
sig12
:=
sk2
.
Sign
(
m1
)
ret
=
pk
.
VerifyBytes
(
m1
,
sig12
)
assert
.
Equal
(
t
,
false
,
ret
)
}
func
TestAggregate
(
t
*
testing
.
T
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
8
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
msgs
:=
make
([][]
byte
,
0
,
n
)
dsigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for each (key,message) pair
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
m
))
msgi
:=
append
(
m
,
byte
(
i
))
msgs
=
append
(
msgs
,
msgi
)
dsigs
=
append
(
dsigs
,
sk
.
Sign
(
msgi
))
}
asig
,
err
:=
blsDrv
.
Aggregate
(
sigs
)
assert
.
NoError
(
t
,
err
)
// One
err
=
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
assert
.
NoError
(
t
,
err
)
apub
,
err
:=
blsDrv
.
AggregatePublic
(
pubs
)
assert
.
NoError
(
t
,
err
)
ret
:=
apub
.
VerifyBytes
(
m
,
asig
)
assert
.
Equal
(
t
,
true
,
ret
)
// N
adsig
,
err
:=
blsDrv
.
Aggregate
(
dsigs
)
assert
.
NoError
(
t
,
err
)
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
adsig
)
assert
.
NoError
(
t
,
err
)
//lose some messages will cause an error
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
[
1
:
],
adsig
)
assert
.
Error
(
t
,
err
)
//with out-of-order public keys, will has no effect on VerifyAggregatedOne, but DO effects VerifyAggregatedN
pubs
[
0
],
pubs
[
1
]
=
pubs
[
1
],
pubs
[
0
]
err
=
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
assert
.
NoError
(
t
,
err
)
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
adsig
)
assert
.
Error
(
t
,
err
)
//invalid length
_
,
err
=
blsDrv
.
Aggregate
(
nil
)
assert
.
Error
(
t
,
err
)
_
,
err
=
blsDrv
.
AggregatePublic
(
make
([]
crypto
.
PubKey
,
0
))
assert
.
Error
(
t
,
err
)
}
//benchmark
func
BenchmarkBLSAggregateSignature
(
b
*
testing
.
B
)
{
msg
:=
[]
byte
(
">16 character identical message"
)
n
:=
200
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
sigs
=
append
(
sigs
,
sk
.
Sign
(
msg
))
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
Aggregate
(
sigs
)
//nolint:errcheck
}
}
func
BenchmarkBLSSign
(
b
*
testing
.
B
)
{
sks
:=
make
([]
crypto
.
PrivKey
,
b
.
N
)
msgs
:=
make
([][]
byte
,
0
,
b
.
N
)
for
i
:=
range
sks
{
sks
[
i
],
_
=
blsDrv
.
GenKey
()
msgs
=
append
(
msgs
,
[]
byte
(
fmt
.
Sprintf
(
"Hello world! 16 characters %d"
,
i
)))
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
sks
[
i
]
.
Sign
(
msgs
[
i
])
}
}
func
BenchmarkBLSVerify
(
b
*
testing
.
B
)
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
m
:=
[]
byte
(
">16 character identical message"
)
sig
:=
sk
.
Sign
(
m
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
pk
.
VerifyBytes
(
m
,
sig
)
//nolint:errcheck
}
}
func
BenchmarkBlsManager_VerifyAggregatedOne
(
b
*
testing
.
B
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
100
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
m
))
}
asig
,
_
:=
blsDrv
.
Aggregate
(
sigs
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
//nolint:errcheck
}
}
func
BenchmarkBlsManager_VerifyAggregatedN
(
b
*
testing
.
B
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
100
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
msgs
:=
make
([][]
byte
,
0
,
n
)
for
i
:=
0
;
i
<
n
;
i
++
{
mi
:=
append
(
m
,
byte
(
i
))
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
mi
))
msgs
=
append
(
msgs
,
mi
)
}
asig
,
_
:=
blsDrv
.
Aggregate
(
sigs
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
asig
)
//nolint:errcheck
}
}
plugin/crypto/init/init.go
View file @
34c89f73
package
init
import
(
_
"github.com/33cn/plugin/plugin/crypto/bls"
//auto gen
_
"github.com/33cn/plugin/plugin/crypto/ecdsa"
//auto gen
_
"github.com/33cn/plugin/plugin/crypto/sm2"
//auto gen
)
plugin/dapp/valnode/commands/valnode.go
View file @
34c89f73
...
...
@@ -25,6 +25,7 @@ var (
strChars
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
// 62 characters
genFile
=
"genesis_file.json"
pvFile
=
"priv_validator_"
AuthBLS
=
259
)
// ValCmd valnode cmd register
...
...
@@ -164,8 +165,9 @@ func CreateCmd() *cobra.Command {
}
func
addCreateCmdFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"num"
,
"n"
,
""
,
"
N
um of the keyfile to create"
)
cmd
.
Flags
()
.
StringP
(
"num"
,
"n"
,
""
,
"
n
um of the keyfile to create"
)
cmd
.
MarkFlagRequired
(
"num"
)
cmd
.
Flags
()
.
StringP
(
"type"
,
"t"
,
"ed25519"
,
"sign type of the keyfile (secp256k1, ed25519, sm2, bls)"
)
}
// RandStr ...
...
...
@@ -192,10 +194,11 @@ MAIN_LOOP:
return
string
(
chars
)
}
func
initCryptoImpl
()
error
{
cr
,
err
:=
crypto
.
New
(
types
.
GetSignName
(
""
,
types
.
ED25519
))
func
initCryptoImpl
(
signType
int
)
error
{
ttypes
.
CryptoName
=
types
.
GetSignName
(
""
,
signType
)
cr
,
err
:=
crypto
.
New
(
ttypes
.
CryptoName
)
if
err
!=
nil
{
fmt
.
Printf
(
"
New crypto impl failed err
: %v"
,
err
)
fmt
.
Printf
(
"
Init crypto fail
: %v"
,
err
)
return
err
}
ttypes
.
ConsensusCrypto
=
cr
...
...
@@ -204,7 +207,13 @@ func initCryptoImpl() error {
func
createFiles
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
// init crypto instance
err
:=
initCryptoImpl
()
ty
,
_
:=
cmd
.
Flags
()
.
GetString
(
"type"
)
signType
,
ok
:=
ttypes
.
SignMap
[
ty
]
if
!
ok
{
fmt
.
Println
(
"type parameter is not valid"
)
return
}
err
:=
initCryptoImpl
(
signType
)
if
err
!=
nil
{
return
}
...
...
@@ -232,7 +241,7 @@ func createFiles(cmd *cobra.Command, args []string) {
// create genesis validator by the pubkey of private validator
gv
:=
ttypes
.
GenesisValidator
{
PubKey
:
ttypes
.
KeyText
{
Kind
:
"ed25519"
,
Data
:
privValidator
.
GetPubKey
()
.
KeyString
()},
PubKey
:
ttypes
.
KeyText
{
Kind
:
ttypes
.
CryptoName
,
Data
:
privValidator
.
GetPubKey
()
.
KeyString
()},
Power
:
10
,
}
genDoc
.
Validators
=
append
(
genDoc
.
Validators
,
gv
)
...
...
plugin/dapp/valnode/executor/exec.go
View file @
34c89f73
...
...
@@ -35,11 +35,22 @@ func (val *ValNode) Exec_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types
return
receipt
,
nil
}
func
getConfigKey
(
key
string
,
db
dbm
.
KV
)
([]
byte
,
error
)
{
configKey
:=
types
.
ConfigKey
(
key
)
value
,
err
:=
db
.
Get
([]
byte
(
configKey
))
if
err
!=
nil
{
clog
.
Error
(
"getConfigKey not find"
,
"configKey"
,
configKey
,
"err"
,
err
)
return
nil
,
err
}
return
value
,
nil
}
func
getManageKey
(
key
string
,
db
dbm
.
KV
)
([]
byte
,
error
)
{
manageKey
:=
types
.
ManageKey
(
key
)
value
,
err
:=
db
.
Get
([]
byte
(
manageKey
))
if
err
!=
nil
{
return
nil
,
err
clog
.
Info
(
"getManageKey not find"
,
"manageKey"
,
manageKey
,
"err"
,
err
)
return
getConfigKey
(
key
,
db
)
}
return
value
,
nil
}
...
...
plugin/dapp/valnode/proto/tendermint.proto
View file @
34c89f73
...
...
@@ -5,86 +5,88 @@ import "blockchain.proto";
package
types
;
message
BlockID
{
bytes
H
ash
=
1
;
bytes
h
ash
=
1
;
}
message
TendermintBitArray
{
int32
B
its
=
1
;
repeated
uint64
E
lems
=
2
;
int32
b
its
=
1
;
repeated
uint64
e
lems
=
2
;
}
message
Vote
{
bytes
ValidatorAddress
=
1
;
int32
ValidatorIndex
=
2
;
int64
Height
=
3
;
int32
Round
=
4
;
int64
Timestamp
=
5
;
uint32
Type
=
6
;
BlockID
BlockID
=
7
;
bytes
Signature
=
8
;
bytes
validatorAddress
=
1
;
int32
validatorIndex
=
2
;
int64
height
=
3
;
int32
round
=
4
;
int64
timestamp
=
5
;
uint32
type
=
6
;
BlockID
blockID
=
7
;
bytes
signature
=
8
;
bool
useAggSig
=
9
;
}
message
TendermintCommit
{
BlockID
BlockID
=
1
;
repeated
Vote
Precommits
=
2
;
BlockID
blockID
=
1
;
repeated
Vote
precommits
=
2
;
AggVote
aggVote
=
3
;
}
message
TendermintBlockInfo
{
State
S
tate
=
2
;
Proposal
P
roposal
=
3
;
State
s
tate
=
2
;
Proposal
p
roposal
=
3
;
TendermintBlock
block
=
4
;
}
message
BlockSize
{
int32
M
axBytes
=
1
;
int32
M
axTxs
=
2
;
int64
M
axGas
=
3
;
int32
m
axBytes
=
1
;
int32
m
axTxs
=
2
;
int64
m
axGas
=
3
;
}
message
TxSize
{
int32
M
axBytes
=
1
;
int64
M
axGas
=
2
;
int32
m
axBytes
=
1
;
int64
m
axGas
=
2
;
}
message
BlockGossip
{
int32
B
lockPartSizeBytes
=
1
;
int32
b
lockPartSizeBytes
=
1
;
}
message
EvidenceParams
{
int64
M
axAge
=
1
;
int64
m
axAge
=
1
;
}
message
ConsensusParams
{
BlockSize
B
lockSize
=
1
;
TxSize
T
xSize
=
2
;
BlockGossip
B
lockGossip
=
3
;
EvidenceParams
E
videnceParams
=
4
;
BlockSize
b
lockSize
=
1
;
TxSize
t
xSize
=
2
;
BlockGossip
b
lockGossip
=
3
;
EvidenceParams
e
videnceParams
=
4
;
}
message
Validator
{
bytes
A
ddress
=
1
;
bytes
P
ubKey
=
2
;
int64
V
otingPower
=
3
;
int64
A
ccum
=
4
;
bytes
a
ddress
=
1
;
bytes
p
ubKey
=
2
;
int64
v
otingPower
=
3
;
int64
a
ccum
=
4
;
}
message
ValidatorSet
{
repeated
Validator
V
alidators
=
1
;
Validator
P
roposer
=
2
;
repeated
Validator
v
alidators
=
1
;
Validator
p
roposer
=
2
;
}
message
State
{
string
C
hainID
=
1
;
int64
L
astBlockHeight
=
2
;
int64
L
astBlockTotalTx
=
3
;
BlockID
L
astBlockID
=
4
;
int64
L
astBlockTime
=
5
;
ValidatorSet
V
alidators
=
6
;
ValidatorSet
L
astValidators
=
7
;
int64
L
astHeightValidatorsChanged
=
8
;
ConsensusParams
C
onsensusParams
=
9
;
int64
L
astHeightConsensusParamsChanged
=
10
;
bytes
L
astResultsHash
=
11
;
bytes
A
ppHash
=
12
;
string
c
hainID
=
1
;
int64
l
astBlockHeight
=
2
;
int64
l
astBlockTotalTx
=
3
;
BlockID
l
astBlockID
=
4
;
int64
l
astBlockTime
=
5
;
ValidatorSet
v
alidators
=
6
;
ValidatorSet
l
astValidators
=
7
;
int64
l
astHeightValidatorsChanged
=
8
;
ConsensusParams
c
onsensusParams
=
9
;
int64
l
astHeightConsensusParamsChanged
=
10
;
bytes
l
astResultsHash
=
11
;
bytes
a
ppHash
=
12
;
}
message
TendermintBlockHeader
{
...
...
@@ -174,3 +176,14 @@ message Heartbeat {
message
IsHealthy
{
bool
isHealthy
=
1
;
}
message
AggVote
{
bytes
validatorAddress
=
1
;
TendermintBitArray
validatorArray
=
2
;
int64
height
=
3
;
int32
round
=
4
;
int64
timestamp
=
5
;
uint32
type
=
6
;
BlockID
blockID
=
7
;
bytes
signature
=
8
;
}
\ No newline at end of file
plugin/dapp/valnode/types/tendermint.pb.go
View file @
34c89f73
...
...
@@ -23,7 +23,7 @@ var _ = math.Inf
const
_
=
proto
.
ProtoPackageIsVersion3
// please upgrade the proto package
type
BlockID
struct
{
Hash
[]
byte
`protobuf:"bytes,1,opt,name=
Hash,proto3" json:"H
ash,omitempty"`
Hash
[]
byte
`protobuf:"bytes,1,opt,name=
hash,proto3" json:"h
ash,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -62,8 +62,8 @@ func (m *BlockID) GetHash() []byte {
}
type
TendermintBitArray
struct
{
Bits
int32
`protobuf:"varint,1,opt,name=
Bits,proto3" json:"B
its,omitempty"`
Elems
[]
uint64
`protobuf:"varint,2,rep,packed,name=
Elems,proto3" json:"E
lems,omitempty"`
Bits
int32
`protobuf:"varint,1,opt,name=
bits,proto3" json:"b
its,omitempty"`
Elems
[]
uint64
`protobuf:"varint,2,rep,packed,name=
elems,proto3" json:"e
lems,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -109,14 +109,15 @@ func (m *TendermintBitArray) GetElems() []uint64 {
}
type
Vote
struct
{
ValidatorAddress
[]
byte
`protobuf:"bytes,1,opt,name=ValidatorAddress,proto3" json:"ValidatorAddress,omitempty"`
ValidatorIndex
int32
`protobuf:"varint,2,opt,name=ValidatorIndex,proto3" json:"ValidatorIndex,omitempty"`
Height
int64
`protobuf:"varint,3,opt,name=Height,proto3" json:"Height,omitempty"`
Round
int32
`protobuf:"varint,4,opt,name=Round,proto3" json:"Round,omitempty"`
Timestamp
int64
`protobuf:"varint,5,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
Type
uint32
`protobuf:"varint,6,opt,name=Type,proto3" json:"Type,omitempty"`
BlockID
*
BlockID
`protobuf:"bytes,7,opt,name=BlockID,proto3" json:"BlockID,omitempty"`
Signature
[]
byte
`protobuf:"bytes,8,opt,name=Signature,proto3" json:"Signature,omitempty"`
ValidatorAddress
[]
byte
`protobuf:"bytes,1,opt,name=validatorAddress,proto3" json:"validatorAddress,omitempty"`
ValidatorIndex
int32
`protobuf:"varint,2,opt,name=validatorIndex,proto3" json:"validatorIndex,omitempty"`
Height
int64
`protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
Round
int32
`protobuf:"varint,4,opt,name=round,proto3" json:"round,omitempty"`
Timestamp
int64
`protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
Type
uint32
`protobuf:"varint,6,opt,name=type,proto3" json:"type,omitempty"`
BlockID
*
BlockID
`protobuf:"bytes,7,opt,name=blockID,proto3" json:"blockID,omitempty"`
Signature
[]
byte
`protobuf:"bytes,8,opt,name=signature,proto3" json:"signature,omitempty"`
UseAggSig
bool
`protobuf:"varint,9,opt,name=useAggSig,proto3" json:"useAggSig,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -203,9 +204,17 @@ func (m *Vote) GetSignature() []byte {
return
nil
}
func
(
m
*
Vote
)
GetUseAggSig
()
bool
{
if
m
!=
nil
{
return
m
.
UseAggSig
}
return
false
}
type
TendermintCommit
struct
{
BlockID
*
BlockID
`protobuf:"bytes,1,opt,name=BlockID,proto3" json:"BlockID,omitempty"`
Precommits
[]
*
Vote
`protobuf:"bytes,2,rep,name=Precommits,proto3" json:"Precommits,omitempty"`
BlockID
*
BlockID
`protobuf:"bytes,1,opt,name=blockID,proto3" json:"blockID,omitempty"`
Precommits
[]
*
Vote
`protobuf:"bytes,2,rep,name=precommits,proto3" json:"precommits,omitempty"`
AggVote
*
AggVote
`protobuf:"bytes,3,opt,name=aggVote,proto3" json:"aggVote,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -250,9 +259,16 @@ func (m *TendermintCommit) GetPrecommits() []*Vote {
return
nil
}
func
(
m
*
TendermintCommit
)
GetAggVote
()
*
AggVote
{
if
m
!=
nil
{
return
m
.
AggVote
}
return
nil
}
type
TendermintBlockInfo
struct
{
State
*
State
`protobuf:"bytes,2,opt,name=
State,proto3" json:"S
tate,omitempty"`
Proposal
*
Proposal
`protobuf:"bytes,3,opt,name=
Proposal,proto3" json:"P
roposal,omitempty"`
State
*
State
`protobuf:"bytes,2,opt,name=
state,proto3" json:"s
tate,omitempty"`
Proposal
*
Proposal
`protobuf:"bytes,3,opt,name=
proposal,proto3" json:"p
roposal,omitempty"`
Block
*
TendermintBlock
`protobuf:"bytes,4,opt,name=block,proto3" json:"block,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
...
...
@@ -306,9 +322,9 @@ func (m *TendermintBlockInfo) GetBlock() *TendermintBlock {
}
type
BlockSize
struct
{
MaxBytes
int32
`protobuf:"varint,1,opt,name=
MaxBytes,proto3" json:"M
axBytes,omitempty"`
MaxTxs
int32
`protobuf:"varint,2,opt,name=
MaxTxs,proto3" json:"M
axTxs,omitempty"`
MaxGas
int64
`protobuf:"varint,3,opt,name=
MaxGas,proto3" json:"M
axGas,omitempty"`
MaxBytes
int32
`protobuf:"varint,1,opt,name=
maxBytes,proto3" json:"m
axBytes,omitempty"`
MaxTxs
int32
`protobuf:"varint,2,opt,name=
maxTxs,proto3" json:"m
axTxs,omitempty"`
MaxGas
int64
`protobuf:"varint,3,opt,name=
maxGas,proto3" json:"m
axGas,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -361,8 +377,8 @@ func (m *BlockSize) GetMaxGas() int64 {
}
type
TxSize
struct
{
MaxBytes
int32
`protobuf:"varint,1,opt,name=
MaxBytes,proto3" json:"M
axBytes,omitempty"`
MaxGas
int64
`protobuf:"varint,2,opt,name=
MaxGas,proto3" json:"M
axGas,omitempty"`
MaxBytes
int32
`protobuf:"varint,1,opt,name=
maxBytes,proto3" json:"m
axBytes,omitempty"`
MaxGas
int64
`protobuf:"varint,2,opt,name=
maxGas,proto3" json:"m
axGas,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -408,7 +424,7 @@ func (m *TxSize) GetMaxGas() int64 {
}
type
BlockGossip
struct
{
BlockPartSizeBytes
int32
`protobuf:"varint,1,opt,name=
BlockPartSizeBytes,proto3" json:"B
lockPartSizeBytes,omitempty"`
BlockPartSizeBytes
int32
`protobuf:"varint,1,opt,name=
blockPartSizeBytes,proto3" json:"b
lockPartSizeBytes,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -447,7 +463,7 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 {
}
type
EvidenceParams
struct
{
MaxAge
int64
`protobuf:"varint,1,opt,name=
MaxAge,proto3" json:"M
axAge,omitempty"`
MaxAge
int64
`protobuf:"varint,1,opt,name=
maxAge,proto3" json:"m
axAge,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -486,10 +502,10 @@ func (m *EvidenceParams) GetMaxAge() int64 {
}
type
ConsensusParams
struct
{
BlockSize
*
BlockSize
`protobuf:"bytes,1,opt,name=
BlockSize,proto3" json:"B
lockSize,omitempty"`
TxSize
*
TxSize
`protobuf:"bytes,2,opt,name=
TxSize,proto3" json:"T
xSize,omitempty"`
BlockGossip
*
BlockGossip
`protobuf:"bytes,3,opt,name=
BlockGossip,proto3" json:"B
lockGossip,omitempty"`
EvidenceParams
*
EvidenceParams
`protobuf:"bytes,4,opt,name=
EvidenceParams,proto3" json:"E
videnceParams,omitempty"`
BlockSize
*
BlockSize
`protobuf:"bytes,1,opt,name=
blockSize,proto3" json:"b
lockSize,omitempty"`
TxSize
*
TxSize
`protobuf:"bytes,2,opt,name=
txSize,proto3" json:"t
xSize,omitempty"`
BlockGossip
*
BlockGossip
`protobuf:"bytes,3,opt,name=
blockGossip,proto3" json:"b
lockGossip,omitempty"`
EvidenceParams
*
EvidenceParams
`protobuf:"bytes,4,opt,name=
evidenceParams,proto3" json:"e
videnceParams,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -549,10 +565,10 @@ func (m *ConsensusParams) GetEvidenceParams() *EvidenceParams {
}
type
Validator
struct
{
Address
[]
byte
`protobuf:"bytes,1,opt,name=
Address,proto3" json:"A
ddress,omitempty"`
PubKey
[]
byte
`protobuf:"bytes,2,opt,name=
PubKey,proto3" json:"P
ubKey,omitempty"`
VotingPower
int64
`protobuf:"varint,3,opt,name=
VotingPower,proto3" json:"V
otingPower,omitempty"`
Accum
int64
`protobuf:"varint,4,opt,name=
Accum,proto3" json:"A
ccum,omitempty"`
Address
[]
byte
`protobuf:"bytes,1,opt,name=
address,proto3" json:"a
ddress,omitempty"`
PubKey
[]
byte
`protobuf:"bytes,2,opt,name=
pubKey,proto3" json:"p
ubKey,omitempty"`
VotingPower
int64
`protobuf:"varint,3,opt,name=
votingPower,proto3" json:"v
otingPower,omitempty"`
Accum
int64
`protobuf:"varint,4,opt,name=
accum,proto3" json:"a
ccum,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -612,8 +628,8 @@ func (m *Validator) GetAccum() int64 {
}
type
ValidatorSet
struct
{
Validators
[]
*
Validator
`protobuf:"bytes,1,rep,name=
Validators,proto3" json:"V
alidators,omitempty"`
Proposer
*
Validator
`protobuf:"bytes,2,opt,name=
Proposer,proto3" json:"P
roposer,omitempty"`
Validators
[]
*
Validator
`protobuf:"bytes,1,rep,name=
validators,proto3" json:"v
alidators,omitempty"`
Proposer
*
Validator
`protobuf:"bytes,2,opt,name=
proposer,proto3" json:"p
roposer,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -659,18 +675,18 @@ func (m *ValidatorSet) GetProposer() *Validator {
}
type
State
struct
{
ChainID
string
`protobuf:"bytes,1,opt,name=
ChainID,proto3" json:"C
hainID,omitempty"`
LastBlockHeight
int64
`protobuf:"varint,2,opt,name=
LastBlockHeight,proto3" json:"L
astBlockHeight,omitempty"`
LastBlockTotalTx
int64
`protobuf:"varint,3,opt,name=
LastBlockTotalTx,proto3" json:"L
astBlockTotalTx,omitempty"`
LastBlockID
*
BlockID
`protobuf:"bytes,4,opt,name=
LastBlockID,proto3" json:"L
astBlockID,omitempty"`
LastBlockTime
int64
`protobuf:"varint,5,opt,name=
LastBlockTime,proto3" json:"L
astBlockTime,omitempty"`
Validators
*
ValidatorSet
`protobuf:"bytes,6,opt,name=
Validators,proto3" json:"V
alidators,omitempty"`
LastValidators
*
ValidatorSet
`protobuf:"bytes,7,opt,name=
LastValidators,proto3" json:"L
astValidators,omitempty"`
LastHeightValidatorsChanged
int64
`protobuf:"varint,8,opt,name=
LastHeightValidatorsChanged,proto3" json:"L
astHeightValidatorsChanged,omitempty"`
ConsensusParams
*
ConsensusParams
`protobuf:"bytes,9,opt,name=
ConsensusParams,proto3" json:"C
onsensusParams,omitempty"`
LastHeightConsensusParamsChanged
int64
`protobuf:"varint,10,opt,name=
LastHeightConsensusParamsChanged,proto3" json:"L
astHeightConsensusParamsChanged,omitempty"`
LastResultsHash
[]
byte
`protobuf:"bytes,11,opt,name=
LastResultsHash,proto3" json:"L
astResultsHash,omitempty"`
AppHash
[]
byte
`protobuf:"bytes,12,opt,name=
AppHash,proto3" json:"A
ppHash,omitempty"`
ChainID
string
`protobuf:"bytes,1,opt,name=
chainID,proto3" json:"c
hainID,omitempty"`
LastBlockHeight
int64
`protobuf:"varint,2,opt,name=
lastBlockHeight,proto3" json:"l
astBlockHeight,omitempty"`
LastBlockTotalTx
int64
`protobuf:"varint,3,opt,name=
lastBlockTotalTx,proto3" json:"l
astBlockTotalTx,omitempty"`
LastBlockID
*
BlockID
`protobuf:"bytes,4,opt,name=
lastBlockID,proto3" json:"l
astBlockID,omitempty"`
LastBlockTime
int64
`protobuf:"varint,5,opt,name=
lastBlockTime,proto3" json:"l
astBlockTime,omitempty"`
Validators
*
ValidatorSet
`protobuf:"bytes,6,opt,name=
validators,proto3" json:"v
alidators,omitempty"`
LastValidators
*
ValidatorSet
`protobuf:"bytes,7,opt,name=
lastValidators,proto3" json:"l
astValidators,omitempty"`
LastHeightValidatorsChanged
int64
`protobuf:"varint,8,opt,name=
lastHeightValidatorsChanged,proto3" json:"l
astHeightValidatorsChanged,omitempty"`
ConsensusParams
*
ConsensusParams
`protobuf:"bytes,9,opt,name=
consensusParams,proto3" json:"c
onsensusParams,omitempty"`
LastHeightConsensusParamsChanged
int64
`protobuf:"varint,10,opt,name=
lastHeightConsensusParamsChanged,proto3" json:"l
astHeightConsensusParamsChanged,omitempty"`
LastResultsHash
[]
byte
`protobuf:"bytes,11,opt,name=
lastResultsHash,proto3" json:"l
astResultsHash,omitempty"`
AppHash
[]
byte
`protobuf:"bytes,12,opt,name=
appHash,proto3" json:"a
ppHash,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
...
@@ -1566,6 +1582,101 @@ func (m *IsHealthy) GetIsHealthy() bool {
return
false
}
type
AggVote
struct
{
ValidatorAddress
[]
byte
`protobuf:"bytes,1,opt,name=validatorAddress,proto3" json:"validatorAddress,omitempty"`
ValidatorArray
*
TendermintBitArray
`protobuf:"bytes,2,opt,name=validatorArray,proto3" json:"validatorArray,omitempty"`
Height
int64
`protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
Round
int32
`protobuf:"varint,4,opt,name=round,proto3" json:"round,omitempty"`
Timestamp
int64
`protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
Type
uint32
`protobuf:"varint,6,opt,name=type,proto3" json:"type,omitempty"`
BlockID
*
BlockID
`protobuf:"bytes,7,opt,name=blockID,proto3" json:"blockID,omitempty"`
Signature
[]
byte
`protobuf:"bytes,8,opt,name=signature,proto3" json:"signature,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
}
func
(
m
*
AggVote
)
Reset
()
{
*
m
=
AggVote
{}
}
func
(
m
*
AggVote
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
AggVote
)
ProtoMessage
()
{}
func
(
*
AggVote
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_04f926c8da23c367
,
[]
int
{
24
}
}
func
(
m
*
AggVote
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_AggVote
.
Unmarshal
(
m
,
b
)
}
func
(
m
*
AggVote
)
XXX_Marshal
(
b
[]
byte
,
deterministic
bool
)
([]
byte
,
error
)
{
return
xxx_messageInfo_AggVote
.
Marshal
(
b
,
m
,
deterministic
)
}
func
(
m
*
AggVote
)
XXX_Merge
(
src
proto
.
Message
)
{
xxx_messageInfo_AggVote
.
Merge
(
m
,
src
)
}
func
(
m
*
AggVote
)
XXX_Size
()
int
{
return
xxx_messageInfo_AggVote
.
Size
(
m
)
}
func
(
m
*
AggVote
)
XXX_DiscardUnknown
()
{
xxx_messageInfo_AggVote
.
DiscardUnknown
(
m
)
}
var
xxx_messageInfo_AggVote
proto
.
InternalMessageInfo
func
(
m
*
AggVote
)
GetValidatorAddress
()
[]
byte
{
if
m
!=
nil
{
return
m
.
ValidatorAddress
}
return
nil
}
func
(
m
*
AggVote
)
GetValidatorArray
()
*
TendermintBitArray
{
if
m
!=
nil
{
return
m
.
ValidatorArray
}
return
nil
}
func
(
m
*
AggVote
)
GetHeight
()
int64
{
if
m
!=
nil
{
return
m
.
Height
}
return
0
}
func
(
m
*
AggVote
)
GetRound
()
int32
{
if
m
!=
nil
{
return
m
.
Round
}
return
0
}
func
(
m
*
AggVote
)
GetTimestamp
()
int64
{
if
m
!=
nil
{
return
m
.
Timestamp
}
return
0
}
func
(
m
*
AggVote
)
GetType
()
uint32
{
if
m
!=
nil
{
return
m
.
Type
}
return
0
}
func
(
m
*
AggVote
)
GetBlockID
()
*
BlockID
{
if
m
!=
nil
{
return
m
.
BlockID
}
return
nil
}
func
(
m
*
AggVote
)
GetSignature
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Signature
}
return
nil
}
func
init
()
{
proto
.
RegisterType
((
*
BlockID
)(
nil
),
"types.BlockID"
)
proto
.
RegisterType
((
*
TendermintBitArray
)(
nil
),
"types.TendermintBitArray"
)
...
...
@@ -1591,6 +1702,7 @@ func init() {
proto
.
RegisterType
((
*
VoteSetBitsMsg
)(
nil
),
"types.VoteSetBitsMsg"
)
proto
.
RegisterType
((
*
Heartbeat
)(
nil
),
"types.Heartbeat"
)
proto
.
RegisterType
((
*
IsHealthy
)(
nil
),
"types.IsHealthy"
)
proto
.
RegisterType
((
*
AggVote
)(
nil
),
"types.AggVote"
)
}
func
init
()
{
...
...
@@ -1598,89 +1710,90 @@ func init() {
}
var
fileDescriptor_04f926c8da23c367
=
[]
byte
{
// 1334 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xbc
,
0x57
,
0xdf
,
0x6e
,
0x1b
,
0xc5
,
0x17
,
0xd6
,
0xc6
,
0x7f
,
0x12
,
0x1f
,
0xe7
,
0x9f
,
0xa6
,
0xbf
,
0xf6
,
0x67
,
0x4a
,
0x90
,
0xac
,
0x11
,
0x20
,
0xd3
,
0x56
,
0xa1
,
0x4a
,
0x2b
,
0x71
,
0x51
,
0x8a
,
0x9a
,
0xa4
,
0x55
,
0x13
,
0x48
,
0xa8
,
0x35
,
0xb6
,
0xca
,
0xf5
,
0xc4
,
0x1e
,
0xec
,
0x05
,
0x7b
,
0xd7
,
0xec
,
0x8c
,
0x9d
,
0x18
,
0x89
,
0x1b
,
0xde
,
0x00
,
0x89
,
0x27
,
0xe0
,
0x9e
,
0x2b
,
0x2e
,
0x78
,
0x04
,
0x9e
,
0x80
,
0x4b
,
0x78
,
0x16
,
0x74
,
0xce
,
0xcc
,
0xae
,
0x67
,
0xd7
,
0x6e
,
0x4a
,
0x11
,
0xe2
,
0x6e
,
0xcf
,
0x37
,
0xdf
,
0xcc
,
0xd9
,
0x39
,
0xe7
,
0x3b
,
0x67
,
0x66
,
0x60
,
0xd7
,
0xa8
,
0xa8
,
0xaf
,
0x92
,
0x71
,
0x18
,
0x99
,
0xfd
,
0x49
,
0x12
,
0x9b
,
0x98
,
0x55
,
0xcc
,
0x7c
,
0xa2
,
0xf4
,
0xed
,
0xdd
,
0x8b
,
0x51
,
0xdc
,
0xfb
,
0xba
,
0x37
,
0x94
,
0x61
,
0x64
,
0x07
,
0xf8
,
0x3b
,
0xb0
,
0x7e
,
0x84
,
0xd8
,
0xe9
,
0x53
,
0xc6
,
0xa0
,
0x7c
,
0x22
,
0xf5
,
0xb0
,
0x11
,
0x34
,
0x83
,
0xd6
,
0xa6
,
0xa0
,
0x6f
,
0xfe
,
0x09
,
0xb0
,
0x6e
,
0xb6
,
0xd6
,
0x51
,
0x68
,
0x0e
,
0x93
,
0x44
,
0xce
,
0x91
,
0x79
,
0x14
,
0x1a
,
0x4d
,
0xcc
,
0x8a
,
0xa0
,
0x6f
,
0xf6
,
0x3f
,
0xa8
,
0x3c
,
0x1b
,
0xa9
,
0xb1
,
0x6e
,
0xac
,
0x35
,
0x4b
,
0xad
,
0xb2
,
0xb0
,
0x06
,
0xff
,
0x7e
,
0x0d
,
0xca
,
0x2f
,
0x63
,
0xa3
,
0xd8
,
0x1d
,
0xd8
,
0x7d
,
0x29
,
0x47
,
0x61
,
0x5f
,
0x9a
,
0x38
,
0x39
,
0xec
,
0xf7
,
0x13
,
0xa5
,
0xb5
,
0x73
,
0xb4
,
0x84
,
0xb3
,
0xf7
,
0x61
,
0x3b
,
0xc3
,
0x4e
,
0xa3
,
0xbe
,
0xba
,
0x6a
,
0xac
,
0x91
,
0xa3
,
0x02
,
0xca
,
0x6e
,
0x41
,
0xf5
,
0x44
,
0x85
,
0x83
,
0xa1
,
0x69
,
0x94
,
0x9a
,
0x41
,
0xab
,
0x24
,
0x9c
,
0x85
,
0xbf
,
0x22
,
0xe2
,
0x69
,
0xd4
,
0x6f
,
0x94
,
0x69
,
0x9a
,
0x35
,
0xd8
,
0x1e
,
0xd4
,
0xba
,
0xe1
,
0x58
,
0x69
,
0x23
,
0xc7
,
0x93
,
0x46
,
0x85
,
0x26
,
0x2c
,
0x00
,
0xdc
,
0x52
,
0x77
,
0x3e
,
0x51
,
0x8d
,
0x6a
,
0x33
,
0x68
,
0x6d
,
0x09
,
0xfa
,
0x66
,
0xad
,
0x2c
,
0x36
,
0x8d
,
0xf5
,
0x66
,
0xd0
,
0xaa
,
0x1f
,
0x6c
,
0xef
,
0x53
,
0x18
,
0xf7
,
0x1d
,
0x2a
,
0xb2
,
0xd0
,
0xed
,
0x41
,
0xad
,
0x13
,
0x0e
,
0x22
,
0x69
,
0xa6
,
0x89
,
0x6a
,
0x6c
,
0xd0
,
0xb6
,
0x16
,
0x00
,
0x0f
,
0x61
,
0x77
,
0x11
,
0xc4
,
0xe3
,
0x78
,
0x3c
,
0x0e
,
0x8d
,
0xbf
,
0x76
,
0x70
,
0xfd
,
0xda
,
0x77
,
0x01
,
0xda
,
0x89
,
0xea
,
0xd1
,
0x34
,
0x1b
,
0xdd
,
0xfa
,
0x41
,
0xdd
,
0x91
,
0x31
,
0xb4
,
0xc2
,
0x1b
,
0xe6
,
0x3f
,
0x06
,
0x70
,
0xc3
,
0x4b
,
0x18
,
0x2d
,
0x11
,
0x7d
,
0x19
,
0x33
,
0x0e
,
0x95
,
0x8e
,
0x91
,
0x46
,
0x51
,
0x24
,
0xeb
,
0x07
,
0x9b
,
0x6e
,
0x3e
,
0x61
,
0xc2
,
0x0e
,
0xb1
,
0xbb
,
0xb0
,
0xd1
,
0x4e
,
0xe2
,
0x49
,
0xac
,
0xe5
,
0x88
,
0x02
,
0x5a
,
0x3f
,
0xd8
,
0x71
,
0xb4
,
0x14
,
0x16
,
0x19
,
0x81
,
0xdd
,
0x83
,
0x0a
,
0x69
,
0x89
,
0x62
,
0x5c
,
0x3f
,
0xb8
,
0xe5
,
0x98
,
0x05
,
0xdf
,
0xc2
,
0x92
,
0xf8
,
0x17
,
0x50
,
0x23
,
0xbb
,
0x13
,
0x7e
,
0xab
,
0xd8
,
0x6d
,
0xd8
,
0x38
,
0x97
,
0x57
,
0x47
,
0x73
,
0xa3
,
0x52
,
0x05
,
0x65
,
0x36
,
0xa6
,
0xf4
,
0x5c
,
0x5e
,
0x75
,
0xaf
,
0xb4
,
0x4b
,
0xb9
,
0xb3
,
0x1c
,
0xfe
,
0x5c
,
0xea
,
0x34
,
0xd5
,
0xd6
,
0xe2
,
0x1f
,
0x43
,
0xb5
,
0x7b
,
0xf5
,
0x37
,
0x57
,
0xc5
,
0xd9
,
0x6b
,
0xb9
,
0xd9
,
0x8f
,
0xa1
,
0x4e
,
0xbf
,
0xf5
,
0x3c
,
0xd6
,
0x3a
,
0x9c
,
0xb0
,
0x7d
,
0x60
,
0x64
,
0xb6
,
0x65
,
0x62
,
0x70
,
0x4d
,
0x7f
,
0xb1
,
0x15
,
0x23
,
0xbc
,
0x05
,
0xdb
,
0xcf
,
0x66
,
0x61
,
0x5f
,
0x45
,
0x3d
,
0xd5
,
0x96
,
0x89
,
0x1c
,
0xa7
,
0x8e
,
0x0e
,
0x07
,
0x8a
,
0x66
,
0x59
,
0x47
,
0x87
,
0x03
,
0xc5
,
0xff
,
0x08
,
0x60
,
0xe7
,
0x38
,
0x8e
,
0xb4
,
0x8a
,
0xf4
,
0x54
,
0x3b
,
0xee
,
0xbe
,
0x17
,
0x13
,
0xa7
,
0x81
,
0x5d
,
0x5f
,
0x03
,
0x88
,
0x0b
,
0x2f
,
0x6c
,
0xef
,
0xa5
,
0x5b
,
0x75
,
0x39
,
0xdc
,
0x4a
,
0x43
,
0x4e
,
0xa0
,
0x48
,
0xe3
,
0xf0
,
0x30
,
0xb7
,
0x27
,
0x97
,
0x48
,
0xe6
,
0x2f
,
0x6c
,
0x47
,
0x44
,
0x6e
,
0xeb
,
0x8f
,
0x8b
,
0x5b
,
0x71
,
0x79
,
0xbd
,
0xe9
,
0x26
,
0xe6
,
0x07
,
0x45
,
0x81
,
0xcc
,
0xa7
,
0x50
,
0xcb
,
0x6a
,
0x93
,
0x35
,
0x60
,
0x3d
,
0x5f
,
0xe1
,
0xa9
,
0x89
,
0xe1
,
0x69
,
0x4f
,
0x2f
,
0x3e
,
0x53
,
0x73
,
0xda
,
0xc2
,
0xa6
,
0x70
,
0x16
,
0x6b
,
0x42
,
0xfd
,
0x65
,
0x6c
,
0xc2
,
0x68
,
0xd0
,
0x8e
,
0x2f
,
0x55
,
0xe2
,
0x52
,
0xec
,
0x43
,
0x58
,
0xd2
,
0x87
,
0xbd
,
0xde
,
0x74
,
0x4c
,
0xbf
,
0x55
,
0x12
,
0xd6
,
0xe0
,
0x11
,
0x6c
,
0x66
,
0x6e
,
0x3b
,
0xca
,
0xb0
,
0xfb
,
0x00
,
0x99
,
0x8d
,
0xce
,
0x4b
,
0x5e
,
0x4c
,
0xb3
,
0x01
,
0xe1
,
0x71
,
0xd8
,
0xbd
,
0x54
,
0xf3
,
0x2a
,
0x71
,
0x61
,
0x5d
,
0xe6
,
0x67
,
0x0c
,
0xfe
,
0x7b
,
0xd9
,
0x95
,
0x11
,
0xee
,
0xf1
,
0x18
,
0xbb
,
0xa8
,
0x2b
,
0xdf
,
0x9a
,
0x48
,
0x4d
,
0xd6
,
0x82
,
0x9d
,
0x33
,
0xa9
,
0xad
,
0xfc
,
0x5d
,
0x77
,
0xb2
,
0xa2
,
0x2b
,
0xc2
,
0xd8
,
0x12
,
0x33
,
0xa8
,
0x1b
,
0x1b
,
0x39
,
0xea
,
0x5e
,
0xb9
,
0xad
,
0x2f
,
0xe1
,
0xec
,
0x3e
,
0xd4
,
0x33
,
0xec
,
0xf4
,
0xa9
,
0x4b
,
0x4e
,
0xb1
,
0x65
,
0xf8
,
0x14
,
0xf6
,
0x2e
,
0x6c
,
0x2d
,
0x56
,
0x09
,
0xc7
,
0xca
,
0xb5
,
0xbc
,
0x3c
,
0xc8
,
0x1e
,
0xe4
,
0x22
,
0x56
,
0xa5
,
0x65
,
0x6f
,
0x14
,
0x23
,
0xd0
,
0x51
,
0x26
,
0x17
,
0xb4
,
0x47
,
0xb0
,
0x8d
,
0xab
,
0x78
,
0x13
,
0xd7
,
0x5f
,
0x3d
,
0xb1
,
0x40
,
0x65
,
0x4f
,
0xe0
,
0x6d
,
0x44
,
0x6c
,
0x0c
,
0x16
,
0xf8
,
0xf1
,
0x50
,
0x46
,
0x03
,
0xd5
,
0xa7
,
0xe6
,
0x59
,
0x12
,
0xd7
,
0x51
,
0xd8
,
0x93
,
0xa5
,
0x5a
,
0x6a
,
0xd4
,
0x72
,
0x4d
,
0xa8
,
0x30
,
0x2a
,
0x96
,
0x4a
,
0xef
,
0x53
,
0x68
,
0x2e
,
0x1c
,
0x14
,
0x06
,
0xd3
,
0x1f
,
0x01
,
0xfa
,
0x91
,
0xd7
,
0xf2
,
0xd2
,
0x7c
,
0x0b
,
0xa5
,
0xa7
,
0x23
,
0xa3
,
0xe9
,
0x00
,
0xad
,
0x93
,
0xb8
,
0x8b
,
0x30
,
0xd5
,
0xc5
,
0x64
,
0x42
,
0x8c
,
0x4d
,
0x57
,
0x17
,
0xd6
,
0xe4
,
0xbf
,
0x96
,
0xe0
,
0x66
,
0xa1
,
0x73
,
0x9e
,
0x28
,
0xd9
,
0x57
,
0x54
,
0x4b
,
0xbd
,
0xbc
,
0xce
,
0x9c
,
0x89
,
0xb5
,
0x34
,
0xf4
,
0xe5
,
0xe5
,
0x2c
,
0xac
,
0x94
,
0x84
,
0x0e
,
0x3f
,
0x2b
,
0x25
,
0x6b
,
0xe0
,
0xf1
,
0x66
,
0x50
,
0x04
,
0xb6
,
0x7c
,
0xe8
,
0x1b
,
0x57
,
0x88
,
0xa6
,
0x63
,
0xec
,
0xb5
,
0x56
,
0x1a
,
0xce
,
0x42
,
0xad
,
0x8d
,
0x3c
,
0xad
,
0x55
,
0x57
,
0x6b
,
0xcd
,
0xa3
,
0x60
,
0xef
,
0x35
,
0x56
,
0xa8
,
0x56
,
0x0a
,
0x25
,
0x91
,
0xd9
,
0x78
,
0x98
,
0x23
,
0xd5
,
0x1e
,
0x7b
,
0xb4
,
0x79
,
0x7b
,
0x3e
,
0x16
,
0x50
,
0xe4
,
0xcd
,
0xb2
,
0x54
,
0x13
,
0xaf
,
0x66
,
0x79
,
0x79
,
0x14
,
0x75
,
0xdd
,
0x4b
,
0x33
,
0x41
,
0x34
,
0x20
,
0x5a
,
0x1e
,
0xc4
,
0xb8
,
0x49
,
0x17
,
0x6b
,
0x9b
,
0x8d
,
0xd4
,
0xc4
,
0x7c
,
0x8d
,
0x0a
,
0xf9
,
0xb2
,
0xd9
,
0x28
,
0xc2
,
0x8c
,
0xc3
,
0xe6
,
0xc4
,
0x55
,
0x3e
,
0x36
,
0xb0
,
0xc6
,
0x16
,
0xd1
,
0x72
,
0x18
,
0xff
,
0x29
,
0x80
,
0x9d
,
0x42
,
0xe6
,
0xd8
,
0x43
,
0xcc
,
0x0c
,
0x66
,
0xcf
,
0x75
,
0xf5
,
0xbd
,
0xd5
,
0x67
,
0xa3
,
0xcd
,
0xb0
,
0x70
,
0x5c
,
0xd6
,
0x84
,
0x72
,
0x5f
,
0x1a
,
0x59
,
0x38
,
0xa0
,
0xed
,
0x29
,
0x4a
,
0x23
,
0xec
,
0x23
,
0x80
,
0x45
,
0xcc
,
0x5c
,
0x0b
,
0xf8
,
0xff
,
0xd2
,
0xda
,
0x76
,
0x58
,
0x78
,
0x54
,
0xfe
,
0x67
,
0xb0
,
0x38
,
0xd9
,
0x3d
,
0xdd
,
0x04
,
0xab
,
0x75
,
0x63
,
0x0f
,
0x5e
,
0xa7
,
0x9b
,
0x3d
,
0xa8
,
0x99
,
0xec
,
0xd2
,
0x64
,
0x15
,
0xb5
,
0x00
,
0x30
,
0xef
,
0xed
,
0x17
,
0x67
,
0xfe
,
0x5d
,
0x2b
,
0xb3
,
0xd9
,
0x3e
,
0x40
,
0xfb
,
0xc5
,
0x59
,
0x2a
,
0xa2
,
0xca
,
0x4a
,
0x11
,
0x79
,
0x0c
,
0xf4
,
0xa4
,
0xb3
,
0x2b
,
0x54
,
0xd5
,
0x5e
,
0xa1
,
0x32
,
0x00
,
0x47
,
0xe9
,
0x26
,
0x31
,
0xc4
,
0x7c
,
0xad
,
0xdb
,
0xd1
,
0x0c
,
0xe0
,
0xbf
,
0x04
,
0xb0
,
0xf3
,
0xb9
,
0xba
,
0x24
,
0xc7
,
0x1d
,
0xa3
,
0x26
,
0xe7
,
0x7a
,
0xf0
,
0x86
,
0xfb
,
0x64
,
0x50
,
0xd6
,
0x46
,
0xd9
,
0x2d
,
0x56
,
0x04
,
0x7d
,
0xb3
,
0x87
,
0x70
,
0x53
,
0xab
,
0x5e
,
0x1c
,
0xf5
,
0x75
,
0x27
,
0x8c
,
0x7a
,
0xaa
,
0x63
,
0x64
,
0x62
,
0xba
,
0x69
,
0x11
,
0x55
,
0xc4
,
0xea
,
0xc1
,
0x54
,
0x5f
,
0x2e
,
0x0d
,
0xe4
,
0xa9
,
0x42
,
0xfc
,
0x22
,
0xcc
,
0x2f
,
0x61
,
0x8b
,
0x9a
,
0x1b
,
0x45
,
0xe0
,
0xcd
,
0x7f
,
0x39
,
0x17
,
0x92
,
0x52
,
0x21
,
0x24
,
0x98
,
0x9a
,
0x50
,
0x7b
,
0x52
,
0xd9
,
0x10
,
0x99
,
0xcd
,
0x7f
,
0x08
,
0x60
,
0x3b
,
0xd5
,
0x43
,
0xfb
,
0xc5
,
0xd9
,
0x75
,
0xae
,
0xef
,
0xc0
,
0xee
,
0x64
,
0xc1
,
0x14
,
0xde
,
0x5f
,
0x2c
,
0xe1
,
0xec
,
0x11
,
0xd4
,
0x3d
,
0xcc
,
0xdd
,
0x3c
,
0xde
,
0x5a
,
0x16
,
0xbf
,
0x7b
,
0x45
,
0x08
,
0x9f
,
0xcd
,
0xfb
,
0x00
,
0x27
,
0x52
,
0xe3
,
0x7d
,
0xf6
,
0x1f
,
0x25
,
0x0f
,
0x9d
,
0xa4
,
0xc9
,
0xc3
,
0x6f
,
0x64
,
0x86
,
0xf4
,
0x74
,
0x70
,
0x6f
,
0x00
,
0x32
,
0xf8
,
0x77
,
0xb0
,
0x83
,
0x2e
,
0x3a
,
0xca
,
0x9c
,
0xcb
,
0xaf
,
0x0e
,
0x1e
,
0xfc
,
0x3b
,
0xae
,
0x5a
,
0xb0
,
0x7e
,
0x71
,
0xed
,
0xb9
,
0x9c
,
0x0e
,
0xf3
,
0x9f
,
0x03
,
0xd8
,
0x76
,
0xfe
,
0xf1
,
0xcd
,
0xf4
,
0x1f
,
0xbb
,
0x67
,
0x1f
,
0x42
,
0x65
,
0x16
,
0xe3
,
0x95
,
0xb6
,
0xf2
,
0xba
,
0xd4
,
0x58
,
0x1e
,
0xff
,
0x2d
,
0x80
,
0xda
,
0x89
,
0x92
,
0x89
,
0xb9
,
0x50
,
0x92
,
0xb4
,
0x30
,
0x7b
,
0xc5
,
0x13
,
0x6e
,
0xb6
,
0xe2
,
0x09
,
0x37
,
0x5b
,
0xf9
,
0x84
,
0x9b
,
0x2d
,
0x3d
,
0xe1
,
0x86
,
0xb9
,
0x27
,
0x5c
,
0x71
,
0xfb
,
0x65
,
0x7f
,
0xfb
,
0xb7
,
0x61
,
0x43
,
0xab
,
0x6f
,
0xa6
,
0x78
,
0xf1
,
0x74
,
0x45
,
0x95
,
0xd9
,
0xd7
,
0xf7
,
0x0f
,
0xfe
,
0x01
,
0xd4
,
0x4e
,
0xf5
,
0x89
,
0x92
,
0x23
,
0x33
,
0x9c
,
0x23
,
0x35
,
0x4c
,
0x0d
,
0xda
,
0xc1
,
0x86
,
0x58
,
0x00
,
0x17
,
0x55
,
0x7a
,
0x18
,
0x3f
,
0xf8
,
0x2b
,
0x00
,
0x00
,
0xff
,
0xff
,
0xbc
,
0x0d
,
0x4d
,
0x91
,
0x45
,
0x0f
,
0x00
,
0x00
,
// 1352 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xd4
,
0x58
,
0xdd
,
0x8e
,
0x1b
,
0x35
,
0x14
,
0xd6
,
0x6c
,
0x32
,
0xf9
,
0x39
,
0xc9
,
0x26
,
0x2b
,
0xf7
,
0x87
,
0xb0
,
0x14
,
0x29
,
0xb2
,
0x00
,
0x85
,
0xb6
,
0x5a
,
0xaa
,
0x6d
,
0x25
,
0x2e
,
0x4a
,
0x51
,
0xb3
,
0x2d
,
0xea
,
0x2e
,
0xb4
,
0x34
,
0x72
,
0x56
,
0xe5
,
0xda
,
0x49
,
0x4c
,
0x32
,
0x90
,
0xf9
,
0x61
,
0xec
,
0x6c
,
0x77
,
0x91
,
0x78
,
0x08
,
0x04
,
0x0f
,
0x80
,
0xb8
,
0xe7
,
0x8a
,
0x0b
,
0x1e
,
0x81
,
0x27
,
0xe0
,
0x12
,
0x9e
,
0x05
,
0xf9
,
0xd8
,
0xf3
,
0x9b
,
0x34
,
0xa5
,
0x08
,
0x21
,
0xb8
,
0x9b
,
0xf3
,
0xf9
,
0xb3
,
0x8f
,
0xcf
,
0x8f
,
0x8f
,
0x8f
,
0x07
,
0xf6
,
0x94
,
0x08
,
0x66
,
0x22
,
0xf6
,
0xbd
,
0x40
,
0x1d
,
0x44
,
0x71
,
0xa8
,
0x42
,
0xe2
,
0xaa
,
0x8b
,
0x48
,
0xc8
,
0xfd
,
0xbd
,
0xc9
,
0x32
,
0x9c
,
0x7e
,
0x39
,
0x5d
,
0x70
,
0x2f
,
0x30
,
0x03
,
0xf4
,
0x4d
,
0xa8
,
0x1f
,
0x69
,
0xec
,
0xe4
,
0x21
,
0x21
,
0x50
,
0x5d
,
0x70
,
0xb9
,
0xe8
,
0x39
,
0x7d
,
0x67
,
0xd0
,
0x66
,
0xf8
,
0x4d
,
0x3f
,
0x04
,
0x72
,
0x9a
,
0xae
,
0x75
,
0xe4
,
0xa9
,
0x61
,
0x1c
,
0xf3
,
0x0b
,
0xcd
,
0x9c
,
0x78
,
0x4a
,
0x22
,
0xd3
,
0x65
,
0xf8
,
0x4d
,
0x2e
,
0x83
,
0x2b
,
0x96
,
0xc2
,
0x97
,
0xbd
,
0x9d
,
0x7e
,
0x65
,
0x50
,
0x65
,
0x46
,
0xa0
,
0x3f
,
0xec
,
0x40
,
0xf5
,
0x59
,
0xa8
,
0x04
,
0xb9
,
0x0e
,
0x7b
,
0x67
,
0x7c
,
0xe9
,
0xcd
,
0xb8
,
0x0a
,
0xe3
,
0xe1
,
0x6c
,
0x16
,
0x0b
,
0x29
,
0xad
,
0xa2
,
0x35
,
0x9c
,
0xbc
,
0x03
,
0x9d
,
0x14
,
0x3b
,
0x09
,
0x66
,
0xe2
,
0xbc
,
0xb7
,
0x83
,
0x8a
,
0x4a
,
0x28
,
0xb9
,
0x0a
,
0xb5
,
0x85
,
0xf0
,
0xe6
,
0x0b
,
0xd5
,
0xab
,
0xf4
,
0x9d
,
0x41
,
0x85
,
0x59
,
0x49
,
0x6f
,
0x25
,
0x0e
,
0x57
,
0xc1
,
0xac
,
0x57
,
0xc5
,
0x69
,
0x46
,
0x20
,
0xd7
,
0xa0
,
0xa9
,
0x3c
,
0x5f
,
0x48
,
0xc5
,
0xfd
,
0xa8
,
0xe7
,
0xe2
,
0x84
,
0x0c
,
0xd0
,
0x26
,
0x69
,
0x17
,
0xf5
,
0x6a
,
0x7d
,
0x67
,
0xb0
,
0xcb
,
0xf0
,
0x9b
,
0x0c
,
0xa0
,
0x3e
,
0x31
,
0xbe
,
0xe9
,
0xd5
,
0xfb
,
0xce
,
0xa0
,
0x75
,
0xd8
,
0x39
,
0x40
,
0x37
,
0x1e
,
0x58
,
0x8f
,
0xb1
,
0x64
,
0x58
,
0xaf
,
0x2d
,
0xbd
,
0x79
,
0xc0
,
0xd5
,
0x2a
,
0x16
,
0xbd
,
0x06
,
0x9a
,
0x95
,
0x01
,
0x7a
,
0x74
,
0x25
,
0xc5
,
0x70
,
0x3e
,
0x1f
,
0x7b
,
0xf3
,
0x5e
,
0xb3
,
0xef
,
0x0c
,
0x1a
,
0x2c
,
0x03
,
0xe8
,
0x77
,
0x0e
,
0xec
,
0x65
,
0x3e
,
0x7e
,
0x10
,
0xfa
,
0xbe
,
0xa7
,
0xf2
,
0xaa
,
0x9d
,
0xed
,
0xaa
,
0x6f
,
0x00
,
0x44
,
0xb1
,
0x98
,
0xe2
,
0x34
,
0xe3
,
0xfc
,
0xd6
,
0x61
,
0xcb
,
0x92
,
0xb5
,
0xe7
,
0x59
,
0x6e
,
0x58
,
0x2f
,
0xcb
,
0xe7
,
0x73
,
0x0d
,
0xa3
,
0xcb
,
0xb2
,
0x65
,
0x87
,
0x06
,
0x65
,
0xc9
,
0x30
,
0xfd
,
0xde
,
0x81
,
0x4b
,
0xb9
,
0xc8
,
0xa3
,
0xb2
,
0xe0
,
0xf3
,
0x90
,
0x50
,
0x70
,
0xa5
,
0xe2
,
0x4a
,
0x60
,
0x48
,
0x5a
,
0x87
,
0x6d
,
0x3b
,
0x7f
,
0xac
,
0x31
,
0x66
,
0x86
,
0xc8
,
0x0d
,
0x68
,
0x44
,
0x71
,
0x18
,
0x85
,
0x92
,
0x2f
,
0xad
,
0x9a
,
0xae
,
0xa5
,
0x8d
,
0x2c
,
0xcc
,
0x52
,
0x02
,
0xb9
,
0x09
,
0x2e
,
0x9a
,
0x82
,
0xc1
,
0x6a
,
0x1d
,
0x5e
,
0xb5
,
0xcc
,
0x92
,
0x6e
,
0x66
,
0x48
,
0xf4
,
0x33
,
0x68
,
0xa2
,
0x3c
,
0xf6
,
0xbe
,
0x16
,
0x64
,
0x1f
,
0x1a
,
0x3e
,
0x3f
,
0x3f
,
0xba
,
0x50
,
0x22
,
0x49
,
0xc5
,
0x54
,
0xd6
,
0xb9
,
0xe1
,
0xf3
,
0xf3
,
0xd3
,
0x73
,
0x69
,
0x73
,
0xc7
,
0x4a
,
0x16
,
0x7f
,
0xc4
,
0x65
,
0x92
,
0x33
,
0x46
,
0xa2
,
0x1f
,
0x40
,
0xed
,
0xf4
,
0xfc
,
0x2f
,
0xae
,
0xaa
,
0x67
,
0xef
,
0x14
,
0x66
,
0xdf
,
0x83
,
0x16
,
0x6e
,
0xeb
,
0x51
,
0x28
,
0xa5
,
0x17
,
0x91
,
0x03
,
0x20
,
0xb8
,
0xdd
,
0x11
,
0x8f
,
0x95
,
0x5e
,
0x33
,
0xbf
,
0xd8
,
0x86
,
0x11
,
0x3a
,
0x80
,
0xce
,
0x47
,
0x67
,
0xde
,
0x4c
,
0x04
,
0x53
,
0x31
,
0xe2
,
0x31
,
0xf7
,
0x13
,
0x45
,
0xc3
,
0xb9
,
0xc0
,
0x59
,
0x46
,
0xd1
,
0x70
,
0x2e
,
0xe8
,
0xef
,
0x0e
,
0x74
,
0x1f
,
0x84
,
0x81
,
0x14
,
0x81
,
0x5c
,
0x49
,
0xcb
,
0x3d
,
0x80
,
0xe6
,
0x24
,
0xf1
,
0x89
,
0xcd
,
0x96
,
0xbd
,
0x7c
,
0xb6
,
0x68
,
0x9c
,
0x65
,
0x14
,
0xf2
,
0x36
,
0xd4
,
0x14
,
0x9a
,
0x6a
,
0x63
,
0xb8
,
0x9b
,
0xb8
,
0x1c
,
0x41
,
0x66
,
0x07
,
0xc9
,
0x1d
,
0x68
,
0x4d
,
0x32
,
0x9b
,
0x6c
,
0x20
,
0x49
,
0x7e
,
0x61
,
0x33
,
0xc2
,
0xf2
,
0x34
,
0x72
,
0x0f
,
0x3a
,
0xa2
,
0x60
,
0x8a
,
0x8d
,
0xeb
,
0x15
,
0x3b
,
0xb1
,
0x68
,
0x27
,
0x2b
,
0x91
,
0xe9
,
0x0a
,
0x9a
,
0xcf
,
0x92
,
0x43
,
0x4e
,
0x7a
,
0x50
,
0xe7
,
0x85
,
0x52
,
0x91
,
0x88
,
0xda
,
0x3d
,
0xd1
,
0x6a
,
0xf2
,
0x89
,
0xb8
,
0x40
,
0x13
,
0xda
,
0xcc
,
0x4a
,
0xa4
,
0x0f
,
0xad
,
0xb3
,
0x50
,
0x79
,
0xc1
,
0x7c
,
0x14
,
0x3e
,
0x17
,
0xb1
,
0x0d
,
0x71
,
0x1e
,
0xd2
,
0xb5
,
0x81
,
0x4f
,
0xa7
,
0x2b
,
0x1f
,
0xb7
,
0x55
,
0x61
,
0x46
,
0xa0
,
0x01
,
0xb4
,
0x53
,
0xb5
,
0x63
,
0xa1
,
0xc8
,
0x2d
,
0x80
,
0xb4
,
0xd6
,
0x68
,
0xe5
,
0x95
,
0x9c
,
0x4f
,
0x53
,
0x22
,
0xcb
,
0x71
,
0xc8
,
0xcd
,
0x24
,
0xe7
,
0x45
,
0x6c
,
0xdd
,
0xba
,
0xce
,
0x4f
,
0x19
,
0xf4
,
0xb7
,
0x2a
,
0xb8
,
0x78
,
0x64
,
0xb4
,
0x8d
,
0x58
,
0x8e
,
0xed
,
0x41
,
0x6f
,
0xb2
,
0x44
,
0x24
,
0x03
,
0xe8
,
0x2e
,
0xb9
,
0x34
,
0xe9
,
0x7f
,
0x6c
,
0xca
,
0x9c
,
0x49
,
0xba
,
0x32
,
0xac
,
0x6b
,
0x6b
,
0x0a
,
0x9d
,
0x86
,
0x8a
,
0x2f
,
0x4f
,
0xcf
,
0xad
,
0xe9
,
0x6b
,
0x38
,
0xb9
,
0x05
,
0xad
,
0x14
,
0x3b
,
0x79
,
0x68
,
0x83
,
0x53
,
0x2e
,
0x2e
,
0x79
,
0x0a
,
0x79
,
0x0b
,
0x76
,
0xb3
,
0x55
,
0x3c
,
0x5f
,
0xd8
,
0xda
,
0x59
,
0x04
,
0xc9
,
0xed
,
0x82
,
0xc7
,
0x6a
,
0xb8
,
0xec
,
0xa5
,
0xb2
,
0x07
,
0xc6
,
0x42
,
0x15
,
0x9c
,
0x76
,
0x17
,
0x3a
,
0x7a
,
0x95
,
0x67
,
0xd9
,
0xc4
,
0xfa
,
0x8b
,
0x27
,
0x96
,
0xa8
,
0xe4
,
0x3e
,
0xbc
,
0xa1
,
0x11
,
0xe3
,
0x83
,
0x0c
,
0x7f
,
0xb0
,
0xe0
,
0xc1
,
0x5c
,
0xcc
,
0xb0
,
0x0a
,
0x57
,
0xd8
,
0x36
,
0x0a
,
0xb9
,
0x0f
,
0xdd
,
0x69
,
0xf1
,
0x2c
,
0x61
,
0x75
,
0xce
,
0x8a
,
0x50
,
0xe9
,
0xa4
,
0xb1
,
0x32
,
0x9d
,
0x7c
,
0x0c
,
0xfd
,
0x4c
,
0x41
,
0x89
,
0x9d
,
0x6c
,
0x04
,
0x70
,
0x23
,
0x2f
,
0xe5
,
0x25
,
0xf1
,
0x66
,
0x42
,
0xae
,
0x96
,
0x4a
,
0x1e
,
0xeb
,
0x9b
,
0xb8
,
0x85
,
0xc9
,
0x5d
,
0x86
,
0xf1
,
0x5c
,
0x44
,
0x11
,
0x32
,
0xda
,
0xf6
,
0x5c
,
0x18
,
0x91
,
0xfe
,
0x52
,
0x81
,
0x2b
,
0xa5
,
0xca
,
0x79
,
0x2c
,
0xf8
,
0x4c
,
0xc4
,
0x5b
,
0xf2
,
0x2c
,
0xbb
,
0x45
,
0x77
,
0x36
,
0xdf
,
0xa2
,
0x26
,
0x95
,
0xec
,
0x2d
,
0xaa
,
0xef
,
0x49
,
0x9d
,
0x04
,
0xe6
,
0xf8
,
0xe0
,
0xb7
,
0x5e
,
0x21
,
0x58
,
0xf9
,
0xba
,
0xd6
,
0x9a
,
0xd4
,
0xb0
,
0x52
,
0x39
,
0xd7
,
0x6a
,
0x2f
,
0xcf
,
0xb5
,
0x7d
,
0x68
,
0x28
,
0x93
,
0xa8
,
0x26
,
0x15
,
0x2a
,
0x2c
,
0x95
,
0x75
,
0x57
,
0xa0
,
0xa9
,
0xe6
,
0x82
,
0x44
,
0xe3
,
0xcd
,
0x45
,
0x5b
,
0x42
,
0x0b
,
0xdd
,
0x83
,
0x71
,
0x63
,
0xd3
,
0xf0
,
0x8a
,
0xa8
,
0xce
,
0xeb
,
0x34
,
0x9c
,
0x48
,
0x03
,
0xa4
,
0x15
,
0xc1
,
0xbc
,
0xaf
,
0x5b
,
0x05
,
0x5f
,
0x6f
,
0x8a
,
0x57
,
0x7b
,
0x73
,
0xbc
,
0x28
,
0xb4
,
0x93
,
0x93
,
0xaf
,
0x5b
,
0x9c
,
0xde
,
0x2e
,
0xd2
,
0x0a
,
0x18
,
0xfd
,
0xd1
,
0x81
,
0x6e
,
0x29
,
0x72
,
0xe4
,
0x8e
,
0x8e
,
0x8c
,
0x8e
,
0x9e
,
0xad
,
0xea
,
0xd7
,
0x36
,
0xdf
,
0x8d
,
0x26
,
0xc2
,
0xcc
,
0x72
,
0x49
,
0x1f
,
0xaa
,
0x33
,
0xae
,
0x78
,
0xe9
,
0x82
,
0x36
,
0xb7
,
0x28
,
0x8e
,
0x90
,
0xf7
,
0x01
,
0x32
,
0x9f
,
0xd9
,
0x12
,
0xf0
,
0xda
,
0xda
,
0xda
,
0x66
,
0x98
,
0xe5
,
0xa8
,
0xf4
,
0x0f
,
0x07
,
0x1a
,
0xc9
,
0x15
,
0x9e
,
0xcb
,
0x1b
,
0x67
,
0x73
,
0xde
,
0xec
,
0xbc
,
0xb0
,
0xfb
,
0xaa
,
0x94
,
0xbb
,
0xaf
,
0x7d
,
0x68
,
0x8c
,
0x9e
,
0x3e
,
0x66
,
0xb9
,
0xa6
,
0x2d
,
0x95
,
0xc9
,
0x01
,
0xc0
,
0xe8
,
0xe9
,
0xe3
,
0x24
,
0x89
,
0xdc
,
0x8d
,
0x49
,
0x94
,
0x63
,
0x14
,
0x7b
,
0xb1
,
0xda
,
0x86
,
0x5e
,
0x0c
,
0xaf
,
0x2b
,
0xec
,
0x74
,
0xeb
,
0x66
,
0x34
,
0x05
,
0xe8
,
0xcf
,
0x0e
,
0x74
,
0x3f
,
0x15
,
0xcf
,
0x51
,
0xf1
,
0x58
,
0x89
,
0xe8
,
0x89
,
0x9c
,
0xbf
,
0xa2
,
0x9d
,
0x04
,
0xaa
,
0x52
,
0x09
,
0x63
,
0xa2
,
0xcb
,
0xf0
,
0x9b
,
0xdc
,
0x81
,
0x2b
,
0x52
,
0x4c
,
0xc3
,
0x60
,
0x26
,
0xc7
,
0x5e
,
0x30
,
0x15
,
0x63
,
0xc5
,
0x63
,
0x75
,
0x9a
,
0x1c
,
0x22
,
0x97
,
0x6d
,
0x1e
,
0x4c
,
0xf2
,
0xcb
,
0x86
,
0x01
,
0x35
,
0xb9
,
0xc8
,
0x2f
,
0xc3
,
0xf4
,
0x39
,
0xec
,
0x62
,
0x71
,
0x43
,
0x0f
,
0xbc
,
0xfa
,
0x96
,
0x0b
,
0x2e
,
0xa9
,
0x94
,
0x5c
,
0xa2
,
0x43
,
0xe3
,
0xc9
,
0x5c
,
0xaa
,
0x34
,
0x58
,
0x2a
,
0xd3
,
0x6f
,
0x1d
,
0xe8
,
0x24
,
0xf9
,
0x30
,
0x7a
,
0xfa
,
0x78
,
0x9b
,
0xea
,
0xeb
,
0xb0
,
0x17
,
0x65
,
0x4c
,
0x96
,
0xdb
,
0xc5
,
0x1a
,
0x4e
,
0xee
,
0x42
,
0x2b
,
0x87
,
0xd9
,
0xce
,
0xe3
,
0xf5
,
0xf5
,
0xe4
,
0xb7
,
0xcf
,
0x11
,
0x96
,
0x67
,
0xd3
,
0x19
,
0xc0
,
0x31
,
0x97
,
0xba
,
0x87
,
0xfd
,
0x5b
,
0xc1
,
0xc3
,
0x47
,
0x80
,
0x0d
,
0x1e
,
0x3e
,
0x02
,
0x2e
,
0x83
,
0xeb
,
0xe1
,
0x1b
,
0xc4
,
0x3e
,
0x26
,
0x50
,
0xa0
,
0xdf
,
0x40
,
0x57
,
0xab
,
0x18
,
0x0b
,
0xf5
,
0x84
,
0x7f
,
0x71
,
0x78
,
0xfb
,
0x9f
,
0x51
,
0x95
,
0x6b
,
0xfa
,
0xab
,
0x5b
,
0x9b
,
0x7e
,
0xfa
,
0x93
,
0x03
,
0x1d
,
0xab
,
0xff
,
0xc8
,
0x53
,
0xf2
,
0x5f
,
0x56
,
0x4f
,
0xde
,
0x03
,
0xf7
,
0x2c
,
0xd4
,
0x2d
,
0xad
,
0xfb
,
0xb2
,
0xd0
,
0x18
,
0x1e
,
0xfd
,
0xd5
,
0x81
,
0xe6
,
0xb1
,
0xe0
,
0xb1
,
0x9a
,
0x08
,
0xae
,
0xfe
,
0x03
,
0x6f
,
0xc1
,
0x7d
,
0x68
,
0x48
,
0xf1
,
0xd5
,
0x4a
,
0x37
,
0x9e
,
0xf6
,
0x50
,
0xa5
,
0xf2
,
0xf6
,
0xfa
,
0x41
,
0xdf
,
0x85
,
0xe6
,
0x89
,
0x3c
,
0x16
,
0x7c
,
0xa9
,
0x16
,
0x17
,
0x9a
,
0xea
,
0x25
,
0x02
,
0x5a
,
0xd0
,
0x60
,
0x19
,
0xa0
,
0xdf
,
0xbe
,
0x75
,
0xfb
,
0xae
,
0x7a
,
0x25
,
0x93
,
0x87
,
0x39
,
0x93
,
0xd1
,
0x8b
,
0xb6
,
0x94
,
0x6f
,
0x71
,
0x73
,
0x69
,
0xc2
,
0xff
,
0xe5
,
0x65
,
0x3c
,
0xa9
,
0xe1
,
0x4f
,
0x88
,
0xdb
,
0x7f
,
0x06
,
0x00
,
0x00
,
0xff
,
0xff
,
0xfd
,
0xb0
,
0x20
,
0xb2
,
0xb1
,
0x10
,
0x00
,
0x00
,
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment