Unverified Commit 34c89f73 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge pull request #852 from caopingcp/issue774_tendermint

tendermint add aggregate signature
parents 4b5cd0a0 b23f5c28
...@@ -23,6 +23,7 @@ require ( ...@@ -23,6 +23,7 @@ require (
github.com/miguelmota/go-solidity-sha3 v0.1.0 github.com/miguelmota/go-solidity-sha3 v0.1.0
github.com/mr-tron/base58 v1.1.3 github.com/mr-tron/base58 v1.1.3
github.com/pborman/uuid v1.2.0 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/pkg/errors v0.8.1
github.com/prometheus/client_golang v0.9.2 // indirect github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/common v0.4.1 github.com/prometheus/common v0.4.1
......
...@@ -79,6 +79,7 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku ...@@ -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 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 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/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/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/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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 ...@@ -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-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/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/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/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/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= 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 ...@@ -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 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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/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 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= 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 ...@@ -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 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= 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/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 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 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= 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 ...@@ -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/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/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 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= 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= ...@@ -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/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/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/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 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.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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+ ...@@ -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 h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= 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/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/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 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 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= ...@@ -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/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 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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-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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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 ...@@ -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-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-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-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-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-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/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 ...@@ -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-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-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-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-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-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= 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 ...@@ -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-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-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-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-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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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 ...@@ -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-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-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-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-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-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-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 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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= 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= ...@@ -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= 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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/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=
...@@ -43,6 +43,8 @@ dbPath="datadir/addrbook" ...@@ -43,6 +43,8 @@ dbPath="datadir/addrbook"
dbCache=4 dbCache=4
grpcLogFile="grpc33.log" grpcLogFile="grpc33.log"
[p2p.sub.dht]
channel=123
[rpc] [rpc]
jrpcBindAddr="localhost:8801" jrpcBindAddr="localhost:8801"
...@@ -73,6 +75,7 @@ powLimitBits = "0x1f2fffff" ...@@ -73,6 +75,7 @@ powLimitBits = "0x1f2fffff"
[consensus.sub.tendermint] [consensus.sub.tendermint]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
genesisAmount=100000000
genesisBlockTime=1514533394 genesisBlockTime=1514533394
timeoutTxAvail=1000 timeoutTxAvail=1000
timeoutPropose=1000 timeoutPropose=1000
...@@ -86,14 +89,21 @@ skipTimeoutCommit=false ...@@ -86,14 +89,21 @@ skipTimeoutCommit=false
createEmptyBlocks=true createEmptyBlocks=true
createEmptyBlocksInterval=1 createEmptyBlocksInterval=1
validatorNodes=["127.0.0.1:46656", "127.0.0.2:46656"] 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] [store]
name="mavl" name="kvmvcc"
driver="leveldb" driver="leveldb"
dbPath="datadir/mavltree" dbPath="datadir/kvmvcc"
dbCache=128 dbCache=128
[store.sub.mavl] [store.sub.kvmvcc]
enableMavlPrefix=false enableMavlPrefix=false
enableMVCC=false enableMVCC=false
...@@ -126,3 +136,9 @@ signType="auth_ecdsa" ...@@ -126,3 +136,9 @@ signType="auth_ecdsa"
superManager=[ superManager=[
"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt", "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
] ]
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
#数据保存模式
dataEmitMode="influxdb"
...@@ -31,6 +31,7 @@ var ( ...@@ -31,6 +31,7 @@ var (
ErrInvalidProposalSignature = errors.New("Error invalid proposal signature") ErrInvalidProposalSignature = errors.New("Error invalid proposal signature")
ErrInvalidProposalPOLRound = errors.New("Error invalid proposal POL round") ErrInvalidProposalPOLRound = errors.New("Error invalid proposal POL round")
ErrAddingVote = errors.New("Error adding vote") ErrAddingVote = errors.New("Error adding vote")
ErrAddingAggVote = errors.New("Error adding aggregate vote")
ErrVoteHeightMismatch = errors.New("Error vote height mismatch") ErrVoteHeightMismatch = errors.New("Error vote height mismatch")
) )
...@@ -85,6 +86,7 @@ type ConsensusState struct { ...@@ -85,6 +86,7 @@ type ConsensusState struct {
setProposal func(proposal *tmtypes.Proposal) error setProposal func(proposal *tmtypes.Proposal) error
broadcastChannel chan<- MsgInfo broadcastChannel chan<- MsgInfo
unicastChannel chan<- MsgInfo
ourID ID ourID ID
status uint32 // 0-stop, 1-start status uint32 // 0-stop, 1-start
quit chan struct{} quit chan struct{}
...@@ -131,6 +133,11 @@ func (cs *ConsensusState) SetBroadcastChannel(broadcastChannel chan<- MsgInfo) { ...@@ -131,6 +133,11 @@ func (cs *ConsensusState) SetBroadcastChannel(broadcastChannel chan<- MsgInfo) {
cs.broadcastChannel = broadcastChannel cs.broadcastChannel = broadcastChannel
} }
// SetBroadcastChannel method
func (cs *ConsensusState) SetUnicastChannel(unicastChannel chan<- MsgInfo) {
cs.unicastChannel = unicastChannel
}
// IsRunning method // IsRunning method
func (cs *ConsensusState) IsRunning() bool { func (cs *ConsensusState) IsRunning() bool {
return atomic.LoadUint32(&cs.status) == 1 return atomic.LoadUint32(&cs.status) == 1
...@@ -162,6 +169,15 @@ func (cs *ConsensusState) GetValidators() (int64, []*ttypes.Validator) { ...@@ -162,6 +169,15 @@ func (cs *ConsensusState) GetValidators() (int64, []*ttypes.Validator) {
return cs.state.LastBlockHeight, cs.state.Validators.Copy().Validators 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. // SetPrivValidator sets the private validator account for signing votes.
func (cs *ConsensusState) SetPrivValidator(priv ttypes.PrivValidator) { func (cs *ConsensusState) SetPrivValidator(priv ttypes.PrivValidator) {
cs.mtx.Lock() cs.mtx.Lock()
...@@ -264,6 +280,13 @@ func (cs *ConsensusState) reconstructLastCommit(state State) { ...@@ -264,6 +280,13 @@ func (cs *ConsensusState) reconstructLastCommit(state State) {
panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err)) 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() { if !lastPrecommits.HasTwoThirdsMajority() {
panic("Failed to reconstruct LastCommit: Does not have +2/3 maj") panic("Failed to reconstruct LastCommit: Does not have +2/3 maj")
} }
...@@ -429,6 +452,8 @@ func (cs *ConsensusState) handleMsg(mi MsgInfo) { ...@@ -429,6 +452,8 @@ func (cs *ConsensusState) handleMsg(mi MsgInfo) {
// TODO: If rs.Height == vote.Height && rs.Round < vote.Round, // TODO: If rs.Height == vote.Height && rs.Round < vote.Round,
// the peer is sending us CatchupCommit precommits. // the peer is sending us CatchupCommit precommits.
// We could make note of this and help filter in broadcastHasVoteMessage(). // We could make note of this and help filter in broadcastHasVoteMessage().
case *tmtypes.AggVote:
err = cs.tryAddAggVote(msg, peerID)
default: default:
tendermintlog.Error("Unknown msg type", msg.String(), "peerid", peerID, "peerip", peerIP) tendermintlog.Error("Unknown msg type", msg.String(), "peerid", peerID, "peerip", peerIP)
} }
...@@ -486,7 +511,7 @@ func (cs *ConsensusState) checkTxsAvailable() { ...@@ -486,7 +511,7 @@ func (cs *ConsensusState) checkTxsAvailable() {
} }
cs.txsAvailable <- height cs.txsAvailable <- height
case <-cs.client.StopC(): case <-cs.client.StopC():
tendermintlog.Debug("checkTxsAvailable exit") tendermintlog.Info("checkTxsAvailable quit")
return return
} }
} }
...@@ -589,7 +614,7 @@ func (cs *ConsensusState) proposalHeartbeat(height int64, round int) { ...@@ -589,7 +614,7 @@ func (cs *ConsensusState) proposalHeartbeat(height int64, round int) {
ValidatorIndex: int32(valIndex), ValidatorIndex: int32(valIndex),
} }
heartbeatMsg := &ttypes.Heartbeat{Heartbeat: heartbeat} heartbeatMsg := &ttypes.Heartbeat{Heartbeat: heartbeat}
err := cs.privValidator.SignHeartbeat(chainID, heartbeatMsg) err := cs.GetPrivValidator().SignHeartbeat(chainID, heartbeatMsg)
if err != nil { if err != nil {
tendermintlog.Error("SignHeartbeat failed", "err", err) tendermintlog.Error("SignHeartbeat failed", "err", err)
continue continue
...@@ -661,12 +686,22 @@ func (cs *ConsensusState) isProposer() bool { ...@@ -661,12 +686,22 @@ func (cs *ConsensusState) isProposer() bool {
return bytes.Equal(cs.Validators.GetProposer().Address, cs.privValidator.GetAddress()) 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) { func (cs *ConsensusState) defaultDecideProposal(height int64, round int) {
var block *ttypes.TendermintBlock var block *ttypes.TendermintBlock
// Decide on block // Decide on block
if cs.ValidBlock != nil { if cs.ValidBlock != nil {
if preExec {
// If there is valid block, PreExec that. // If there is valid block, PreExec that.
pblockNew := cs.client.PreExecBlock(cs.ValidBlock.Data, false) pblockNew := cs.client.PreExecBlock(cs.ValidBlock.Data, false)
if pblockNew == nil { if pblockNew == nil {
...@@ -674,6 +709,7 @@ func (cs *ConsensusState) defaultDecideProposal(height int64, round int) { ...@@ -674,6 +709,7 @@ func (cs *ConsensusState) defaultDecideProposal(height int64, round int) {
return return
} }
cs.ValidBlock.Data = pblockNew cs.ValidBlock.Data = pblockNew
}
block = cs.ValidBlock block = cs.ValidBlock
} else { } else {
// Create a new proposal block from state/txs from the mempool. // Create a new proposal block from state/txs from the mempool.
...@@ -756,12 +792,14 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock) ...@@ -756,12 +792,14 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock)
} }
block.Data.TxHash = merkle.CalcMerkleRoot(cfg, block.Data.Height, block.Data.Txs) block.Data.TxHash = merkle.CalcMerkleRoot(cfg, block.Data.Height, block.Data.Txs)
if preExec {
pblockNew := cs.client.PreExecBlock(block.Data, false) pblockNew := cs.client.PreExecBlock(block.Data, false)
if pblockNew == nil { if pblockNew == nil {
tendermintlog.Error("createProposalBlock PreExecBlock fail") tendermintlog.Error("createProposalBlock PreExecBlock fail")
return nil return nil
} }
block.Data = pblockNew block.Data = pblockNew
}
return block return block
} }
...@@ -800,6 +838,11 @@ func (cs *ConsensusState) enterPrevote(height int64, round int) { ...@@ -800,6 +838,11 @@ func (cs *ConsensusState) enterPrevote(height int64, round int) {
cs.newStep() 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)) 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 // Sign and broadcast vote as necessary
...@@ -833,7 +876,7 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) { ...@@ -833,7 +876,7 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
return return
} }
if !cs.isProposer() { if preExec && !cs.isProposer() {
// PreExec proposal block // PreExec proposal block
blockCopy := *cs.ProposalBlock.Data blockCopy := *cs.ProposalBlock.Data
blockNew := cs.client.PreExecBlock(&blockCopy, true) blockNew := cs.client.PreExecBlock(&blockCopy, true)
...@@ -898,6 +941,11 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { ...@@ -898,6 +941,11 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) {
cs.newStep() 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() blockID, ok := cs.Votes.Prevotes(round).TwoThirdsMajority()
// If we don't have a polka, we must precommit nil // If we don't have a polka, we must precommit nil
...@@ -1010,7 +1058,7 @@ func (cs *ConsensusState) enterCommit(height int64, commitRound int) { ...@@ -1010,7 +1058,7 @@ func (cs *ConsensusState) enterCommit(height int64, commitRound int) {
blockID, ok := cs.Votes.Precommits(commitRound).TwoThirdsMajority() blockID, ok := cs.Votes.Precommits(commitRound).TwoThirdsMajority()
if !ok { if !ok {
panic("RunActionCommit() expects +2/3 precommits") panic("enterCommit expects +2/3 precommits")
} }
// The Locked* fields no longer matter. // The Locked* fields no longer matter.
...@@ -1114,6 +1162,10 @@ func (cs *ConsensusState) finalizeCommit(height int64) { ...@@ -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, 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))) "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 //check whether need update validator nodes
valNodes, err := cs.client.QueryValidatorsByHeight(block.Header.Height) valNodes, err := cs.client.QueryValidatorsByHeight(block.Header.Height)
...@@ -1278,6 +1330,121 @@ func (cs *ConsensusState) addProposalBlock(proposalBlock *tmtypes.TendermintBloc ...@@ -1278,6 +1330,121 @@ func (cs *ConsensusState) addProposalBlock(proposalBlock *tmtypes.TendermintBloc
return nil 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 // 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 { func (cs *ConsensusState) tryAddVote(voteRaw *tmtypes.Vote, peerID string, peerIP string) error {
vote := &ttypes.Vote{Vote: voteRaw} vote := &ttypes.Vote{Vote: voteRaw}
...@@ -1344,7 +1511,7 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin ...@@ -1344,7 +1511,7 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
// Not necessarily a bad peer, but not favourable behaviour. // Not necessarily a bad peer, but not favourable behaviour.
if vote.Height != cs.Height { if vote.Height != cs.Height {
err = ErrVoteHeightMismatch 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 return
} }
...@@ -1426,6 +1593,16 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin ...@@ -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 case cs.Round == int(vote.Round) && ttypes.RoundStepPrevote <= cs.Step: // current round
blockID, ok := prevotes.TwoThirdsMajority() blockID, ok := prevotes.TwoThirdsMajority()
if ok && (cs.isProposalComplete() || len(blockID.Hash) == 0) { 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)) cs.enterPrecommit(height, int(vote.Round))
} else if prevotes.HasTwoThirdsAny() { } else if prevotes.HasTwoThirdsAny() {
cs.enterPrevoteWait(height, int(vote.Round)) cs.enterPrevoteWait(height, int(vote.Round))
...@@ -1447,6 +1624,16 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin ...@@ -1447,6 +1624,16 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin
cs.enterNewRound(height, int(vote.Round)) cs.enterNewRound(height, int(vote.Round))
cs.enterPrecommit(height, int(vote.Round)) cs.enterPrecommit(height, int(vote.Round))
if len(blockID.Hash) != 0 { 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)) cs.enterCommit(height, int(vote.Round))
if skipTimeoutCommit && precommits.HasAll() { if skipTimeoutCommit && precommits.HasAll() {
cs.enterNewRound(cs.Height, 0) cs.enterNewRound(cs.Height, 0)
...@@ -1467,7 +1654,6 @@ func (cs *ConsensusState) addVote(vote *ttypes.Vote, peerID string, peerIP strin ...@@ -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) { func (cs *ConsensusState) signVote(voteType byte, hash []byte) (*ttypes.Vote, error) {
addr := cs.privValidator.GetAddress() addr := cs.privValidator.GetAddress()
valIndex, _ := cs.Validators.GetByAddress(addr) valIndex, _ := cs.Validators.GetByAddress(addr)
tVote := &tmtypes.Vote{} tVote := &tmtypes.Vote{}
...@@ -1482,11 +1668,10 @@ func (cs *ConsensusState) signVote(voteType byte, hash []byte) (*ttypes.Vote, er ...@@ -1482,11 +1668,10 @@ func (cs *ConsensusState) signVote(voteType byte, hash []byte) (*ttypes.Vote, er
Type: uint32(voteType), Type: uint32(voteType),
BlockID: &tmtypes.BlockID{Hash: hash}, BlockID: &tmtypes.BlockID{Hash: hash},
Signature: nil, Signature: nil,
UseAggSig: useAggSig,
}, },
} }
beg := time.Now()
err := cs.privValidator.SignVote(cs.state.ChainID, vote) err := cs.privValidator.SignVote(cs.state.ChainID, vote)
tendermintlog.Debug("signVote", "height", cs.Height, "cost", types.Since(beg))
return vote, err return vote, err
} }
...@@ -1498,14 +1683,18 @@ func (cs *ConsensusState) signAddVote(voteType byte, hash []byte) *ttypes.Vote { ...@@ -1498,14 +1683,18 @@ func (cs *ConsensusState) signAddVote(voteType byte, hash []byte) *ttypes.Vote {
} }
vote, err := cs.signVote(voteType, hash) vote, err := cs.signVote(voteType, hash)
if err == nil { if err == nil {
// send to self
cs.sendInternalMessage(MsgInfo{TypeID: ttypes.VoteID, Msg: vote.Vote, PeerID: cs.ourID, PeerIP: ""}) 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 return vote
} }
tendermintlog.Error("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "err", err) tendermintlog.Error("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "err", err)
return nil return nil
} }
// CompareHRS method // CompareHRS method
...@@ -1570,6 +1759,9 @@ func (cs *ConsensusState) PeerQueryMaj23Sleep() time.Duration { ...@@ -1570,6 +1759,9 @@ func (cs *ConsensusState) PeerQueryMaj23Sleep() time.Duration {
// IsProposer method // IsProposer method
func (cs *ConsensusState) IsProposer() bool { func (cs *ConsensusState) IsProposer() bool {
cs.mtx.Lock()
defer cs.mtx.Unlock()
return cs.isProposer() return cs.isProposer()
} }
......
...@@ -25,6 +25,7 @@ const ( ...@@ -25,6 +25,7 @@ const (
tryListenSeconds = 5 tryListenSeconds = 5
handshakeTimeout = 20 // * time.Second, handshakeTimeout = 20 // * time.Second,
maxSendQueueSize = 1024 maxSendQueueSize = 1024
minSendQueueSize = 10
defaultSendTimeout = 60 * time.Second defaultSendTimeout = 60 * time.Second
//MaxMsgPacketPayloadSize define //MaxMsgPacketPayloadSize define
MaxMsgPacketPayloadSize = 10 * 1024 * 1024 MaxMsgPacketPayloadSize = 10 * 1024 * 1024
...@@ -57,11 +58,12 @@ func Parallel(tasks ...func()) { ...@@ -57,11 +58,12 @@ func Parallel(tasks ...func()) {
wg.Wait() wg.Wait()
} }
// GenAddressByPubKey method // GenIDByPubKey method
func GenAddressByPubKey(pubkey crypto.PubKey) []byte { func GenIDByPubKey(pubkey crypto.PubKey) ID {
//must add 3 bytes ahead to make compatibly //must add 3 bytes ahead to make compatibly
typeAddr := append([]byte{byte(0x01), byte(0x01), byte(0x20)}, pubkey.Bytes()...) typeAddr := append([]byte{byte(0x01), byte(0x01), byte(0x20)}, pubkey.Bytes()[:32]...)
return crypto.Ripemd160(typeAddr) address := crypto.Ripemd160(typeAddr)
return ID(hex.EncodeToString(address))
} }
// IP2IPPort struct // IP2IPPort struct
...@@ -129,6 +131,7 @@ type Node struct { ...@@ -129,6 +131,7 @@ type Node struct {
state *ConsensusState state *ConsensusState
broadcastChannel chan MsgInfo broadcastChannel chan MsgInfo
unicastChannel chan MsgInfo
started uint32 // atomic started uint32 // atomic
stopped uint32 // atomic stopped uint32 // atomic
quit chan struct{} quit chan struct{}
...@@ -136,8 +139,6 @@ type Node struct { ...@@ -136,8 +139,6 @@ type Node struct {
// NewNode method // NewNode method
func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivKey, network string, version string, state *ConsensusState) *Node { func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivKey, network string, version string, state *ConsensusState) *Node {
address := GenAddressByPubKey(privKey.PubKey())
node := &Node{ node := &Node{
peerSet: NewPeerSet(), peerSet: NewPeerSet(),
seeds: seeds, seeds: seeds,
...@@ -148,16 +149,18 @@ func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivK ...@@ -148,16 +149,18 @@ func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivK
privKey: privKey, privKey: privKey,
Network: network, Network: network,
Version: version, Version: version,
ID: ID(hex.EncodeToString(address)), ID: GenIDByPubKey(privKey.PubKey()),
dialing: NewMutexMap(), dialing: NewMutexMap(),
reconnecting: NewMutexMap(), reconnecting: NewMutexMap(),
broadcastChannel: make(chan MsgInfo, maxSendQueueSize), broadcastChannel: make(chan MsgInfo, maxSendQueueSize),
unicastChannel: make(chan MsgInfo, minSendQueueSize),
state: state, state: state,
localIPs: make(map[string]net.IP), localIPs: make(map[string]net.IP),
} }
state.SetOurID(node.ID) state.SetOurID(node.ID)
state.SetBroadcastChannel(node.broadcastChannel) state.SetBroadcastChannel(node.broadcastChannel)
state.SetUnicastChannel(node.unicastChannel)
localIPs := getNaiveExternalAddress(true) localIPs := getNaiveExternalAddress(true)
if len(localIPs) > 0 { if len(localIPs) > 0 {
...@@ -179,7 +182,7 @@ func (node *Node) Start() { ...@@ -179,7 +182,7 @@ func (node *Node) Start() {
if err == nil { if err == nil {
break break
} else if i < tryListenSeconds-1 { } else if i < tryListenSeconds-1 {
time.Sleep(time.Second * 1) time.Sleep(time.Second)
} }
} }
if err != nil { if err != nil {
...@@ -213,6 +216,7 @@ func (node *Node) Start() { ...@@ -213,6 +216,7 @@ func (node *Node) Start() {
go node.StartConsensusRoutine() go node.StartConsensusRoutine()
go node.BroadcastRoutine() go node.BroadcastRoutine()
go node.UnicastRoutine()
} }
} }
...@@ -305,13 +309,33 @@ func (node *Node) BroadcastRoutine() { ...@@ -305,13 +309,33 @@ func (node *Node) BroadcastRoutine() {
for { for {
msg, ok := <-node.broadcastChannel msg, ok := <-node.broadcastChannel
if !ok { if !ok {
tendermintlog.Debug("broadcastChannel closed") tendermintlog.Info("broadcastChannel closed")
return return
} }
node.Broadcast(msg) 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) { func (node *Node) connectComming(inConn net.Conn) {
maxPeers := maxNumPeers maxPeers := maxNumPeers
if maxPeers <= node.peerSet.Size() { if maxPeers <= node.peerSet.Size() {
...@@ -640,7 +664,7 @@ func dial(addr string) (net.Conn, error) { ...@@ -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) { func newOutboundPeerConn(addr string, ourNodePrivKey crypto.PrivKey, onPeerError func(Peer, interface{}), state *ConsensusState) (*peerConn, error) {
conn, err := dial(addr) conn, err := dial(addr)
if err != nil { 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) pc, err := newPeerConn(conn, true, true, ourNodePrivKey, onPeerError, state)
...@@ -684,7 +708,7 @@ func newPeerConn( ...@@ -684,7 +708,7 @@ func newPeerConn(
// Encrypt connection // Encrypt connection
conn, err = MakeSecretConnection(conn, ourNodePrivKey) conn, err = MakeSecretConnection(conn, ourNodePrivKey)
if err != nil { 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 // Only the information we already have
......
...@@ -54,17 +54,19 @@ func TestParallel(t *testing.T) { ...@@ -54,17 +54,19 @@ func TestParallel(t *testing.T) {
assert.Equal(t, 6, sum) assert.Equal(t, 6, sum)
} }
func TestGenAddressByPubKey(t *testing.T) { func TestGenIDByPubKey(t *testing.T) {
tmp, err := hex.DecodeString(privKey) tmp, err := hex.DecodeString(privKey)
assert.Nil(t, err) assert.Nil(t, err)
priv, err := secureConnCrypto.PrivKeyFromBytes(tmp) priv, err := secureConnCrypto.PrivKeyFromBytes(tmp)
assert.Nil(t, err) 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) strAddr := fmt.Sprintf("%X", addr)
assert.Equal(t, expectAddress, strAddr) assert.Equal(t, expectAddress, strAddr)
fmt.Println("TestGenAddressByPubKey ok") fmt.Println("TestGenIDByPubKey ok")
} }
func TestIP2IPPort(t *testing.T) { func TestIP2IPPort(t *testing.T) {
...@@ -154,7 +156,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) { ...@@ -154,7 +156,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
}, },
} }
ps := pc.state ps := pc.state
pc.waitQuit.Add(1)
go pc.updateStateRoutine() go pc.updateStateRoutine()
//NewRoundStepID msg //NewRoundStepID msg
...@@ -249,7 +250,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) { ...@@ -249,7 +250,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
assert.NotNil(t, ps.getVoteBitArray(3, 2, ttypes.VoteTypePrecommit)) assert.NotNil(t, ps.getVoteBitArray(3, 2, ttypes.VoteTypePrecommit))
pc.quitUpdate <- struct{}{} pc.quitUpdate <- struct{}{}
pc.waitQuit.Wait()
fmt.Println("testUpdateStateRoutine ok") fmt.Println("testUpdateStateRoutine ok")
} }
...@@ -8,13 +8,11 @@ import ( ...@@ -8,13 +8,11 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"net" "net"
"reflect" "reflect"
"runtime/debug"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
...@@ -56,8 +54,6 @@ type Peer interface { ...@@ -56,8 +54,6 @@ type Peer interface {
Stop() Stop()
SetTransferChannel(chan MsgInfo) SetTransferChannel(chan MsgInfo)
//Set(string, interface{})
//Get(string) interface{}
} }
// PeerConnState struct // PeerConnState struct
...@@ -85,10 +81,8 @@ type peerConn struct { ...@@ -85,10 +81,8 @@ type peerConn struct {
started uint32 //atomic started uint32 //atomic
stopped uint32 // atomic stopped uint32 // atomic
quitSend chan struct{}
quitUpdate chan struct{} quitUpdate chan struct{}
quitBeat chan struct{} quitBeat chan struct{}
waitQuit sync.WaitGroup
transferChannel chan MsgInfo transferChannel chan MsgInfo
...@@ -222,8 +216,7 @@ func (pc *peerConn) ID() ID { ...@@ -222,8 +216,7 @@ func (pc *peerConn) ID() ID {
if len(pc.id) != 0 { if len(pc.id) != 0 {
return pc.id return pc.id
} }
address := GenAddressByPubKey(pc.conn.(*SecretConnection).RemotePubKey()) pc.id = GenIDByPubKey(pc.conn.(*SecretConnection).RemotePubKey())
pc.id = ID(hex.EncodeToString(address))
return pc.id return pc.id
} }
...@@ -265,6 +258,11 @@ func (pc *peerConn) SetTransferChannel(transferChannel chan MsgInfo) { ...@@ -265,6 +258,11 @@ func (pc *peerConn) SetTransferChannel(transferChannel chan MsgInfo) {
pc.transferChannel = transferChannel 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() { func (pc *peerConn) CloseConn() {
err := pc.conn.Close() // nolint: errcheck err := pc.conn.Close() // nolint: errcheck
if err != nil { if err != nil {
...@@ -358,7 +356,7 @@ func (pc *peerConn) Send(msg MsgInfo) bool { ...@@ -358,7 +356,7 @@ func (pc *peerConn) Send(msg MsgInfo) bool {
atomic.AddInt32(&pc.sendQueueSize, 1) atomic.AddInt32(&pc.sendQueueSize, 1)
return true return true
case <-time.After(defaultSendTimeout): 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 return false
} }
} }
...@@ -379,9 +377,25 @@ func (pc *peerConn) TrySend(msg MsgInfo) bool { ...@@ -379,9 +377,25 @@ func (pc *peerConn) TrySend(msg MsgInfo) bool {
// PickSendVote picks a vote and sends it to the peer. // PickSendVote picks a vote and sends it to the peer.
// Returns true if vote was sent. // Returns true if vote was sent.
func (pc *peerConn) PickSendVote(votes ttypes.VoteSetReader) bool { 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()} 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) { if pc.Send(msg) {
pc.state.SetHasVote(vote) pc.state.SetHasVote(vote)
return true return true
...@@ -406,7 +420,6 @@ func (pc *peerConn) Start() error { ...@@ -406,7 +420,6 @@ func (pc *peerConn) Start() error {
pc.pongChannel = make(chan struct{}) pc.pongChannel = make(chan struct{})
pc.sendQueue = make(chan MsgInfo, maxSendQueueSize) pc.sendQueue = make(chan MsgInfo, maxSendQueueSize)
pc.sendBuffer = make([]byte, 0, MaxMsgPacketPayloadSize) pc.sendBuffer = make([]byte, 0, MaxMsgPacketPayloadSize)
pc.quitSend = make(chan struct{})
pc.quitUpdate = make(chan struct{}) pc.quitUpdate = make(chan struct{})
pc.quitBeat = make(chan struct{}) pc.quitBeat = make(chan struct{})
pc.state = &PeerConnState{ip: pc.ip, PeerRoundState: ttypes.PeerRoundState{ pc.state = &PeerConnState{ip: pc.ip, PeerRoundState: ttypes.PeerRoundState{
...@@ -417,7 +430,6 @@ func (pc *peerConn) Start() error { ...@@ -417,7 +430,6 @@ func (pc *peerConn) Start() error {
}} }}
pc.updateStateQueue = make(chan MsgInfo, maxSendQueueSize) pc.updateStateQueue = make(chan MsgInfo, maxSendQueueSize)
pc.heartbeatQueue = make(chan proto.Message, 100) pc.heartbeatQueue = make(chan proto.Message, 100)
pc.waitQuit.Add(5) //heartbeatRoutine, updateStateRoutine,gossipDataRoutine,gossipVotesRoutine,queryMaj23Routine
go pc.sendRoutine() go pc.sendRoutine()
go pc.recvRoutine() go pc.recvRoutine()
...@@ -434,27 +446,8 @@ func (pc *peerConn) Start() error { ...@@ -434,27 +446,8 @@ func (pc *peerConn) Start() error {
func (pc *peerConn) Stop() { func (pc *peerConn) Stop() {
if atomic.CompareAndSwapUint32(&pc.stopped, 0, 1) { 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() pc.CloseConn()
tendermintlog.Info("peerConn stop finish", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn close connection", "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)
} }
} }
...@@ -468,12 +461,9 @@ func (pc *peerConn) stopForError(r interface{}) { ...@@ -468,12 +461,9 @@ func (pc *peerConn) stopForError(r interface{}) {
} }
func (pc *peerConn) sendRoutine() { func (pc *peerConn) sendRoutine() {
defer pc._recover()
FOR_LOOP: FOR_LOOP:
for { for {
select { select {
case <-pc.quitSend:
break FOR_LOOP
case msg := <-pc.sendQueue: case msg := <-pc.sendQueue:
bytes, err := proto.Marshal(msg.Msg) bytes, err := proto.Marshal(msg.Msg)
if err != nil { if err != nil {
...@@ -525,7 +515,6 @@ FOR_LOOP: ...@@ -525,7 +515,6 @@ FOR_LOOP:
} }
func (pc *peerConn) recvRoutine() { func (pc *peerConn) recvRoutine() {
defer pc._recover()
FOR_LOOP: FOR_LOOP:
for { for {
//typeID+msgLen+msg //typeID+msgLen+msg
...@@ -563,7 +552,7 @@ FOR_LOOP: ...@@ -563,7 +552,7 @@ FOR_LOOP:
continue continue
} }
if pc.transferChannel != nil && (pkt.TypeID == ttypes.ProposalID || pkt.TypeID == ttypes.VoteID || 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()} pc.transferChannel <- MsgInfo{pkt.TypeID, realMsg.(proto.Message), pc.ID(), pc.ip.String()}
if pkt.TypeID == ttypes.ProposalID { if pkt.TypeID == ttypes.ProposalID {
proposal := realMsg.(*tmtypes.Proposal) proposal := realMsg.(*tmtypes.Proposal)
...@@ -577,6 +566,9 @@ FOR_LOOP: ...@@ -577,6 +566,9 @@ FOR_LOOP:
block := &ttypes.TendermintBlock{TendermintBlock: realMsg.(*tmtypes.TendermintBlock)} block := &ttypes.TendermintBlock{TendermintBlock: realMsg.(*tmtypes.TendermintBlock)}
tendermintlog.Debug("Receiving proposal block", "block-height", block.Header.Height, "peerip", pc.ip.String()) tendermintlog.Debug("Receiving proposal block", "block-height", block.Header.Height, "peerip", pc.ip.String())
pc.state.SetHasProposalBlock(block) 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 { } else if pkt.TypeID == ttypes.ProposalHeartbeatID {
pc.heartbeatQueue <- realMsg.(*tmtypes.Heartbeat) pc.heartbeatQueue <- realMsg.(*tmtypes.Heartbeat)
...@@ -591,10 +583,8 @@ FOR_LOOP: ...@@ -591,10 +583,8 @@ FOR_LOOP:
} }
} }
} }
pc.quitUpdate <- struct{}{}
close(pc.pongChannel) pc.quitBeat <- struct{}{}
close(pc.heartbeatQueue)
close(pc.updateStateQueue)
tendermintlog.Info("peerConn stop recvRoutine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop recvRoutine", "peerIP", pc.ip.String())
} }
...@@ -603,7 +593,6 @@ FOR_LOOP: ...@@ -603,7 +593,6 @@ FOR_LOOP:
for { for {
select { select {
case <-pc.quitUpdate: case <-pc.quitUpdate:
pc.waitQuit.Done()
break FOR_LOOP break FOR_LOOP
case msg := <-pc.updateStateQueue: case msg := <-pc.updateStateQueue:
typeID := msg.TypeID typeID := msg.TypeID
...@@ -662,6 +651,7 @@ FOR_LOOP: ...@@ -662,6 +651,7 @@ FOR_LOOP:
} }
} }
} }
close(pc.updateStateQueue)
tendermintlog.Info("peerConn stop updateStateRoutine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop updateStateRoutine", "peerIP", pc.ip.String())
} }
...@@ -670,15 +660,17 @@ FOR_LOOP: ...@@ -670,15 +660,17 @@ FOR_LOOP:
for { for {
select { select {
case <-pc.quitBeat: case <-pc.quitBeat:
pc.waitQuit.Done()
break FOR_LOOP break FOR_LOOP
case heartbeat := <-pc.heartbeatQueue: case heartbeat := <-pc.heartbeatQueue:
msg := heartbeat.(*tmtypes.Heartbeat) msg, ok := heartbeat.(*tmtypes.Heartbeat)
if ok {
tendermintlog.Debug("Received proposal heartbeat message", tendermintlog.Debug("Received proposal heartbeat message",
"height", msg.Height, "round", msg.Round, "sequence", msg.Sequence, "height", msg.Height, "round", msg.Round, "sequence", msg.Sequence,
"valIdx", msg.ValidatorIndex, "valAddr", msg.ValidatorAddress) "valIdx", msg.ValidatorIndex, "valAddr", msg.ValidatorAddress)
} }
} }
}
close(pc.heartbeatQueue)
tendermintlog.Info("peerConn stop heartbeatRoutine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop heartbeatRoutine", "peerIP", pc.ip.String())
} }
...@@ -687,7 +679,6 @@ OUTER_LOOP: ...@@ -687,7 +679,6 @@ OUTER_LOOP:
for { for {
// Manage disconnects from self or peer. // Manage disconnects from self or peer.
if !pc.IsRunning() { if !pc.IsRunning() {
pc.waitQuit.Done()
tendermintlog.Info("peerConn stop gossipDataRoutine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop gossipDataRoutine", "peerIP", pc.ip.String())
return return
} }
...@@ -789,7 +780,6 @@ OUTER_LOOP: ...@@ -789,7 +780,6 @@ OUTER_LOOP:
for { for {
// Manage disconnects from self or peer. // Manage disconnects from self or peer.
if !pc.IsRunning() { if !pc.IsRunning() {
pc.waitQuit.Done()
tendermintlog.Info("peerConn stop gossipVotesRoutine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop gossipVotesRoutine", "peerIP", pc.ip.String())
return return
} }
...@@ -806,7 +796,7 @@ OUTER_LOOP: ...@@ -806,7 +796,7 @@ OUTER_LOOP:
// If height matches, then send LastCommit, Prevotes, Precommits. // If height matches, then send LastCommit, Prevotes, Precommits.
if rs.Height == prs.Height { if rs.Height == prs.Height {
if pc.gossipVotesForHeight(rs, &prs.PeerRoundState) { if !useAggSig && pc.gossipVotesForHeight(rs, &prs.PeerRoundState) {
continue OUTER_LOOP continue OUTER_LOOP
} }
} }
...@@ -914,7 +904,6 @@ OUTER_LOOP: ...@@ -914,7 +904,6 @@ OUTER_LOOP:
for { for {
// Manage disconnects from self or peer. // Manage disconnects from self or peer.
if !pc.IsRunning() { if !pc.IsRunning() {
pc.waitQuit.Done()
tendermintlog.Info("peerConn stop queryMaj23Routine", "peerIP", pc.ip.String()) tendermintlog.Info("peerConn stop queryMaj23Routine", "peerIP", pc.ip.String())
return return
} }
...@@ -1003,20 +992,6 @@ OUTER_LOOP: ...@@ -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\nStack: %s", se.Err, se.Stack)
}
func (se StackError) Error() string {
return se.String()
}
// GetRoundState returns an atomic snapshot of the PeerRoundState. // GetRoundState returns an atomic snapshot of the PeerRoundState.
// There's no point in mutating it since it won't change PeerState. // There's no point in mutating it since it won't change PeerState.
func (ps *PeerConnState) GetRoundState() *ttypes.PeerRoundState { func (ps *PeerConnState) GetRoundState() *ttypes.PeerRoundState {
...@@ -1073,6 +1048,23 @@ func (ps *PeerConnState) SetHasProposalBlock(block *ttypes.TendermintBlock) { ...@@ -1073,6 +1048,23 @@ func (ps *PeerConnState) SetHasProposalBlock(block *ttypes.TendermintBlock) {
ps.ProposalBlock = true 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. // PickVoteToSend picks a vote to send to the peer.
// Returns true if a vote was picked. // Returns true if a vote was picked.
// NOTE: `votes` must be the correct Size() for the Height(). // NOTE: `votes` must be the correct Size() for the Height().
...@@ -1266,6 +1258,7 @@ func (ps *PeerConnState) ApplyNewRoundStepMessage(msg *tmtypes.NewRoundStepMsg) ...@@ -1266,6 +1258,7 @@ func (ps *PeerConnState) ApplyNewRoundStepMessage(msg *tmtypes.NewRoundStepMsg)
// We'll update the BitArray capacity later. // We'll update the BitArray capacity later.
ps.Prevotes = nil ps.Prevotes = nil
ps.Precommits = nil ps.Precommits = nil
ps.AggPrecommit = false
} }
if psHeight == msg.Height && psRound != int(msg.Round) && int(msg.Round) == psCatchupCommitRound { if psHeight == msg.Height && psRound != int(msg.Round) && int(msg.Round) == psCatchupCommitRound {
// Peer caught up to CatchupCommitRound. // Peer caught up to CatchupCommitRound.
......
...@@ -16,12 +16,13 @@ import ( ...@@ -16,12 +16,13 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
"time" "time"
"github.com/33cn/chain33/common/crypto" "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/box"
"golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/nacl/secretbox"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
...@@ -33,7 +34,6 @@ const ( ...@@ -33,7 +34,6 @@ const (
dataMaxSize = 1024 dataMaxSize = 1024
totalFrameSize = dataMaxSize + dataLenSize totalFrameSize = dataMaxSize + dataLenSize
sealedFrameSize = totalFrameSize + secretbox.Overhead sealedFrameSize = totalFrameSize + secretbox.Overhead
authSigMsgSize = (32) + (64)
) // fixed size (length prefixed) byte arrays ) // fixed size (length prefixed) byte arrays
// SecretConnection Implements net.Conn // SecretConnection Implements net.Conn
...@@ -62,7 +62,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (* ...@@ -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) // (see DJB's Curve25519 paper: http://cr.yp.to/ecdh/curve25519-20060209.pdf)
remEphPub, err := shareEphPubKey(conn, locEphPub) remEphPub, err := shareEphPubKey(conn, locEphPub)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("shareEphPubKey: %v", err)
} }
// Compute common shared secret. // Compute common shared secret.
...@@ -96,7 +96,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (* ...@@ -96,7 +96,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
// Share (in secret) each other's pubkey & challenge signature // Share (in secret) each other's pubkey & challenge signature
authSigMsg, err := shareAuthSignature(sc, locPubKey, locSignature) authSigMsg, err := shareAuthSignature(sc, locPubKey, locSignature)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("shareAuthSignature: %v", err)
} }
remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig
if !remPubKey.VerifyBytes(challenge[:], remSignature) { if !remPubKey.VerifyBytes(challenge[:], remSignature) {
...@@ -205,7 +205,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) { ...@@ -205,7 +205,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) {
var err error var err error
ephPub, ephPriv, err = box.GenerateKey(crand.Reader) ephPub, ephPriv, err = box.GenerateKey(crand.Reader)
if err != nil { if err != nil {
types.PanicCrisis("Could not generate ephemeral keypairs") ttypes.PanicCrisis("Could not generate ephemeral keypairs")
} }
return return
} }
...@@ -282,26 +282,28 @@ type authSigMessage struct { ...@@ -282,26 +282,28 @@ type authSigMessage struct {
func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature crypto.Signature) (*authSigMessage, error) { func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature crypto.Signature) (*authSigMessage, error) {
var recvMsg authSigMessage var recvMsg authSigMessage
var err1, err2 error var err1, err2 error
pubLen := len(pubKey.Bytes())
sigLen := len(signature.Bytes())
Parallel( Parallel(
func() { func() {
msgByte := make([]byte, len(pubKey.Bytes())+len(signature.Bytes())) msgByte := make([]byte, pubLen+sigLen)
copy(msgByte, pubKey.Bytes()) copy(msgByte, pubKey.Bytes()[:pubLen])
copy(msgByte[len(pubKey.Bytes()):], signature.Bytes()) copy(msgByte[pubLen:], signature.Bytes())
_, err1 = sc.Write(msgByte) _, err1 = sc.Write(msgByte)
}, },
func() { func() {
readBuffer := make([]byte, authSigMsgSize) readBuffer := make([]byte, pubLen+sigLen)
_, err2 = io.ReadFull(sc, readBuffer) _, err2 = io.ReadFull(sc, readBuffer)
if err2 != nil { if err2 != nil {
return return
} }
recvMsg.Key, err2 = types.ConsensusCrypto.PubKeyFromBytes(readBuffer[:32]) recvMsg.Key, err2 = ttypes.ConsensusCrypto.PubKeyFromBytes(readBuffer[:pubLen])
if err2 != nil { if err2 != nil {
return return
} }
recvMsg.Sig, err2 = types.ConsensusCrypto.SignatureFromBytes(readBuffer[32:]) recvMsg.Sig, err2 = ttypes.ConsensusCrypto.SignatureFromBytes(readBuffer[pubLen:])
if err2 != nil { if err2 != nil {
return return
} }
......
...@@ -385,7 +385,7 @@ func getprivkey(key string) crypto.PrivKey { ...@@ -385,7 +385,7 @@ func getprivkey(key string) crypto.PrivKey {
if err != nil { if err != nil {
panic(err) panic(err)
} }
priv, err := cr.PrivKeyFromBytes(bkey) priv, err := cr.PrivKeyFromBytes(bkey[:32])
if err != nil { if err != nil {
panic(err) panic(err)
} }
......
// 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 package tendermint
import ( import (
......
...@@ -24,11 +24,14 @@ import ( ...@@ -24,11 +24,14 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
) )
const tendermintVersion = "0.1.0" const (
tendermintVersion = "0.1.0"
)
var ( var (
tendermintlog = log15.New("module", "tendermint") tendermintlog = log15.New("module", "tendermint")
genesis string genesis string
genesisAmount int64 = 1e8
genesisBlockTime int64 genesisBlockTime int64
timeoutTxAvail int32 = 1000 timeoutTxAvail int32 = 1000
timeoutPropose int32 = 3000 // millisecond timeoutPropose int32 = 3000 // millisecond
...@@ -41,12 +44,15 @@ var ( ...@@ -41,12 +44,15 @@ var (
skipTimeoutCommit = false skipTimeoutCommit = false
createEmptyBlocks = false createEmptyBlocks = false
fastSync = false fastSync = false
preExec = false
createEmptyBlocksInterval int32 // second createEmptyBlocksInterval int32 // second
validatorNodes = []string{"127.0.0.1:46656"} validatorNodes = []string{"127.0.0.1:46656"}
peerGossipSleepDuration int32 = 100 peerGossipSleepDuration int32 = 200
peerQueryMaj23SleepDuration int32 = 2000 peerQueryMaj23SleepDuration int32 = 2000
zeroHash [32]byte zeroHash [32]byte
random *rand.Rand random *rand.Rand
signName = "ed25519"
useAggSig = false
) )
func init() { func init() {
...@@ -65,7 +71,6 @@ type Client struct { ...@@ -65,7 +71,6 @@ type Client struct {
pubKey string pubKey string
csState *ConsensusState csState *ConsensusState
csStore *ConsensusStore // save consensus state csStore *ConsensusStore // save consensus state
crypto crypto.Crypto
node *Node node *Node
txsAvailable chan int64 txsAvailable chan int64
stopC chan struct{} stopC chan struct{}
...@@ -73,6 +78,7 @@ type Client struct { ...@@ -73,6 +78,7 @@ type Client struct {
type subConfig struct { type subConfig struct {
Genesis string `json:"genesis"` Genesis string `json:"genesis"`
GenesisAmount int64 `json:"genesisAmount"`
GenesisBlockTime int64 `json:"genesisBlockTime"` GenesisBlockTime int64 `json:"genesisBlockTime"`
TimeoutTxAvail int32 `json:"timeoutTxAvail"` TimeoutTxAvail int32 `json:"timeoutTxAvail"`
TimeoutPropose int32 `json:"timeoutPropose"` TimeoutPropose int32 `json:"timeoutPropose"`
...@@ -87,9 +93,12 @@ type subConfig struct { ...@@ -87,9 +93,12 @@ type subConfig struct {
CreateEmptyBlocksInterval int32 `json:"createEmptyBlocksInterval"` CreateEmptyBlocksInterval int32 `json:"createEmptyBlocksInterval"`
ValidatorNodes []string `json:"validatorNodes"` ValidatorNodes []string `json:"validatorNodes"`
FastSync bool `json:"fastSync"` 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 var subcfg subConfig
if sub != nil { if sub != nil {
types.MustDecode(sub, &subcfg) types.MustDecode(sub, &subcfg)
...@@ -97,6 +106,9 @@ func (client *Client) applyConfig(sub []byte) { ...@@ -97,6 +106,9 @@ func (client *Client) applyConfig(sub []byte) {
if subcfg.Genesis != "" { if subcfg.Genesis != "" {
genesis = subcfg.Genesis genesis = subcfg.Genesis
} }
if subcfg.GenesisAmount > 0 {
genesisAmount = subcfg.GenesisAmount
}
if subcfg.GenesisBlockTime > 0 { if subcfg.GenesisBlockTime > 0 {
genesisBlockTime = subcfg.GenesisBlockTime genesisBlockTime = subcfg.GenesisBlockTime
} }
...@@ -133,6 +145,11 @@ func (client *Client) applyConfig(sub []byte) { ...@@ -133,6 +145,11 @@ func (client *Client) applyConfig(sub []byte) {
validatorNodes = subcfg.ValidatorNodes validatorNodes = subcfg.ValidatorNodes
} }
fastSync = subcfg.FastSync fastSync = subcfg.FastSync
preExec = subcfg.PreExec
if subcfg.SignName != "" {
signName = subcfg.SignName
}
useAggSig = subcfg.UseAggregateSignature
} }
// DefaultDBProvider returns a database using the DBBackend and DBDir // DefaultDBProvider returns a database using the DBBackend and DBDir
...@@ -144,37 +161,47 @@ func DefaultDBProvider(name string) dbm.DB { ...@@ -144,37 +161,47 @@ func DefaultDBProvider(name string) dbm.DB {
// New ... // New ...
func New(cfg *types.Consensus, sub []byte) queue.Module { func New(cfg *types.Consensus, sub []byte) queue.Module {
tendermintlog.Info("Start to create tendermint client") tendermintlog.Info("Start to create tendermint client")
applyConfig(sub)
//init rand //init rand
ttypes.Init() ttypes.Init()
genDoc, err := ttypes.GenesisDocFromFile("genesis.json") signType, ok := ttypes.SignMap[signName]
if err != nil { if !ok {
tendermintlog.Error("NewTendermintClient", "msg", "GenesisDocFromFile failded", "error", err) tendermintlog.Error("Invalid sign name")
return nil return nil
} }
cr, err := crypto.New(types.GetSignName("", types.ED25519)) ttypes.CryptoName = types.GetSignName("", signType)
cr, err := crypto.New(ttypes.CryptoName)
if err != nil { if err != nil {
tendermintlog.Error("NewTendermintClient", "err", err) tendermintlog.Error("NewTendermintClient", "err", err)
return nil return nil
} }
ttypes.ConsensusCrypto = cr ttypes.ConsensusCrypto = cr
priv, err := cr.GenKey() if useAggSig {
_, err = crypto.ToAggregate(ttypes.ConsensusCrypto)
if err != nil { 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 return nil
} }
privValidator := ttypes.LoadOrGenPrivValidatorFS("priv_validator.json") privValidator := ttypes.LoadOrGenPrivValidatorFS("priv_validator.json")
if privValidator == nil { if privValidator == nil {
tendermintlog.Error("NewTendermintClient create priv_validator file failed") tendermintlog.Error("NewTendermintClient create priv_validator file fail")
return nil return nil
} }
ttypes.InitMessageMap() ttypes.InitMessageMap()
priv := privValidator.PrivKey
pubkey := privValidator.GetPubKey().KeyString() pubkey := privValidator.GetPubKey().KeyString()
c := drivers.NewBaseClient(cfg) c := drivers.NewBaseClient(cfg)
client := &Client{ client := &Client{
...@@ -184,21 +211,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -184,21 +211,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
privKey: priv, privKey: priv,
pubKey: pubkey, pubKey: pubkey,
csStore: NewConsensusStore(), csStore: NewConsensusStore(),
crypto: cr,
txsAvailable: make(chan int64, 1), txsAvailable: make(chan int64, 1),
stopC: make(chan struct{}, 1), stopC: make(chan struct{}, 1),
} }
c.SetChild(client) c.SetChild(client)
client.applyConfig(sub)
return client return client
} }
// PrivValidator returns the Node's PrivValidator.
func (client *Client) PrivValidator() ttypes.PrivValidator {
return client.privValidator
}
// GenesisDoc returns the Node's GenesisDoc. // GenesisDoc returns the Node's GenesisDoc.
func (client *Client) GenesisDoc() *ttypes.GenesisDoc { func (client *Client) GenesisDoc() *ttypes.GenesisDoc {
return client.genesisDoc return client.genesisDoc
...@@ -216,6 +235,7 @@ func (client *Client) GenesisState() *State { ...@@ -216,6 +235,7 @@ func (client *Client) GenesisState() *State {
// Close TODO:may need optimize // Close TODO:may need optimize
func (client *Client) Close() { func (client *Client) Close() {
client.BaseClient.Close()
client.node.Stop() client.node.Stop()
client.stopC <- struct{}{} client.stopC <- struct{}{}
tendermintlog.Info("consensus tendermint closed") tendermintlog.Info("consensus tendermint closed")
...@@ -335,7 +355,7 @@ func (client *Client) CreateGenesisTx() (ret []*types.Transaction) { ...@@ -335,7 +355,7 @@ func (client *Client) CreateGenesisTx() (ret []*types.Transaction) {
//gen payload //gen payload
g := &cty.CoinsAction_Genesis{} g := &cty.CoinsAction_Genesis{}
g.Genesis = &types.AssetsGenesis{} 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}) tx.Payload = types.Encode(&cty.CoinsAction{Value: g, Ty: cty.CoinsActionGenesis})
ret = append(ret, &tx) ret = append(ret, &tx)
return return
...@@ -405,10 +425,13 @@ func (client *Client) ProcEvent(msg *queue.Message) bool { ...@@ -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 // CreateBlock a routine monitor whether some transactions available and tell client by available channel
func (client *Client) CreateBlock() { func (client *Client) CreateBlock() {
issleep := true issleep := true
for { for {
if client.IsClosed() {
tendermintlog.Info("CreateBlock quit")
break
}
if !client.csState.IsRunning() { if !client.csState.IsRunning() {
tendermintlog.Error("consensus not running now") tendermintlog.Info("consensus not running")
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
...@@ -483,7 +506,6 @@ func (client *Client) BuildBlock() *types.Block { ...@@ -483,7 +506,6 @@ func (client *Client) BuildBlock() *types.Block {
client.AddTxsToBlock(&newblock, txs) client.AddTxsToBlock(&newblock, txs)
//固定难度 //固定难度
newblock.Difficulty = cfg.GetP(0).PowLimitBits newblock.Difficulty = cfg.GetP(0).PowLimitBits
//newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
newblock.BlockTime = types.Now().Unix() newblock.BlockTime = types.Now().Unix()
if lastBlock.BlockTime >= newblock.BlockTime { if lastBlock.BlockTime >= newblock.BlockTime {
newblock.BlockTime = lastBlock.BlockTime + 1 newblock.BlockTime = lastBlock.BlockTime + 1
...@@ -498,6 +520,9 @@ func (client *Client) CommitBlock(block *types.Block) error { ...@@ -498,6 +520,9 @@ func (client *Client) CommitBlock(block *types.Block) error {
if retErr != nil { if retErr != nil {
tendermintlog.Info("CommitBlock fail", "err", retErr) tendermintlog.Info("CommitBlock fail", "err", retErr)
if client.WaitBlock(block.Height) { if client.WaitBlock(block.Height) {
if !preExec {
return nil
}
curBlock, err := client.RequestBlock(block.Height) curBlock, err := client.RequestBlock(block.Height)
if err == nil { if err == nil {
if bytes.Equal(curBlock.Hash(cfg), block.Hash(cfg)) { if bytes.Equal(curBlock.Hash(cfg), block.Hash(cfg)) {
...@@ -636,7 +661,7 @@ func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) { ...@@ -636,7 +661,7 @@ func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) {
return &tmtypes.ValidatorSet{Validators: validators, Proposer: &tmtypes.Validator{}}, nil return &tmtypes.ValidatorSet{Validators: validators, Proposer: &tmtypes.Validator{}}, nil
} }
//比较newBlock是不是最优区块 // CmpBestBlock 比较newBlock是不是最优区块
func (client *Client) CmpBestBlock(newBlock *types.Block, cmpBlock *types.Block) bool { func (client *Client) CmpBestBlock(newBlock *types.Block, cmpBlock *types.Block) bool {
return false return false
} }
...@@ -272,13 +272,12 @@ func CheckState(t *testing.T, client *Client) { ...@@ -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.Prevote(0), 1000*time.Millisecond)
assert.Equal(t, client.csState.Precommit(0), 1000*time.Millisecond) assert.Equal(t, client.csState.Precommit(0), 1000*time.Millisecond)
assert.Equal(t, client.csState.PeerGossipSleep(), 100*time.Millisecond) assert.Equal(t, client.csState.PeerGossipSleep(), 200*time.Millisecond)
assert.Equal(t, client.csState.PeerQueryMaj23Sleep(), 2000*time.Millisecond) assert.Equal(t, client.csState.PeerQueryMaj23Sleep(), 2000*time.Millisecond)
assert.Equal(t, client.csState.IsProposer(), true) assert.Equal(t, client.csState.IsProposer(), true)
assert.Nil(t, client.csState.GetPrevotesState(state.LastBlockHeight, 0, nil)) assert.Nil(t, client.csState.GetPrevotesState(state.LastBlockHeight, 0, nil))
assert.Nil(t, client.csState.GetPrecommitsState(state.LastBlockHeight, 0, nil)) assert.Nil(t, client.csState.GetPrecommitsState(state.LastBlockHeight, 0, nil))
assert.NotEmpty(t, client.csState.GetPrivValidator())
assert.NotEmpty(t, client.PrivValidator())
assert.Len(t, client.GenesisDoc().Validators, 1) assert.Len(t, client.GenesisDoc().Validators, 1)
msg1, err := client.Query_IsHealthy(&types.ReqNil{}) msg1, err := client.Query_IsHealthy(&types.ReqNil{})
......
...@@ -139,7 +139,7 @@ func Put(ip string, size string, privkey string) { ...@@ -139,7 +139,7 @@ func Put(ip string, size string, privkey string) {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return return
} }
url := "http://" + ip + ":9801" url := "http://" + ip + ":8801"
if privkey == "" { if privkey == "" {
_, priv := genaddress() _, priv := genaddress()
privkey = common.ToHex(priv.Bytes()) privkey = common.ToHex(priv.Bytes())
......
...@@ -13,18 +13,11 @@ import ( ...@@ -13,18 +13,11 @@ import (
"time" "time"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle" "github.com/33cn/chain33/common/merkle"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types" tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
) )
var (
blocklog = log15.New("module", "tendermint-block")
// ConsensusCrypto define
ConsensusCrypto crypto.Crypto
)
// BlockID struct // BlockID struct
type BlockID struct { type BlockID struct {
tmtypes.BlockID tmtypes.BlockID
...@@ -88,11 +81,6 @@ func (b *TendermintBlock) ValidateBasic() error { ...@@ -88,11 +81,6 @@ func (b *TendermintBlock) ValidateBasic() error {
return errors.New("Zero Header.Height") 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 { if b.Header.TotalTxs < 0 {
return errors.New("Negative Header.TotalTxs") return errors.New("Negative Header.TotalTxs")
} }
...@@ -192,7 +180,7 @@ func (h *Header) Hash() []byte { ...@@ -192,7 +180,7 @@ func (h *Header) Hash() []byte {
} }
bytes, err := json.Marshal(h) bytes, err := json.Marshal(h)
if err != nil { if err != nil {
blocklog.Error("block header Hash() marshal failed", "error", err) ttlog.Error("block header Hash() marshal failed", "error", err)
return nil return nil
} }
return crypto.Ripemd160(bytes) return crypto.Ripemd160(bytes)
...@@ -254,6 +242,9 @@ func (commit *Commit) FirstPrecommit() *tmtypes.Vote { ...@@ -254,6 +242,9 @@ func (commit *Commit) FirstPrecommit() *tmtypes.Vote {
// Height returns the height of the commit // Height returns the height of the commit
func (commit *Commit) Height() int64 { func (commit *Commit) Height() int64 {
if commit.AggVote != nil {
return commit.AggVote.Height
}
if len(commit.Precommits) == 0 { if len(commit.Precommits) == 0 {
return 0 return 0
} }
...@@ -262,6 +253,9 @@ func (commit *Commit) Height() int64 { ...@@ -262,6 +253,9 @@ func (commit *Commit) Height() int64 {
// Round returns the round of the commit // Round returns the round of the commit
func (commit *Commit) Round() int { func (commit *Commit) Round() int {
if commit.AggVote != nil {
return int(commit.AggVote.Round)
}
if len(commit.Precommits) == 0 { if len(commit.Precommits) == 0 {
return 0 return 0
} }
...@@ -283,6 +277,10 @@ func (commit *Commit) Size() int { ...@@ -283,6 +277,10 @@ func (commit *Commit) Size() int {
// BitArray returns a BitArray of which validators voted in this commit // BitArray returns a BitArray of which validators voted in this commit
func (commit *Commit) BitArray() *BitArray { func (commit *Commit) BitArray() *BitArray {
if commit.AggVote != nil {
bitArray := &BitArray{TendermintBitArray: commit.AggVote.ValidatorArray}
return bitArray.copy()
}
if commit.bitArray == nil { if commit.bitArray == nil {
commit.bitArray = NewBitArray(len(commit.Precommits)) commit.bitArray = NewBitArray(len(commit.Precommits))
for i, precommit := range commit.Precommits { for i, precommit := range commit.Precommits {
...@@ -301,7 +299,16 @@ func (commit *Commit) GetByIndex(index int) *Vote { ...@@ -301,7 +299,16 @@ func (commit *Commit) GetByIndex(index int) *Vote {
// IsCommit returns true if there is at least one vote // IsCommit returns true if there is at least one vote
func (commit *Commit) IsCommit() bool { 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. // ValidateBasic performs basic validation that doesn't involve state data.
...@@ -338,12 +345,28 @@ func (commit *Commit) ValidateBasic() error { ...@@ -338,12 +345,28 @@ func (commit *Commit) ValidateBasic() error {
round, precommit.Round) 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 return nil
} }
// Hash returns the hash of the commit // Hash returns the hash of the commit
func (commit *Commit) Hash() []byte { func (commit *Commit) Hash() []byte {
if commit.hash == nil { if commit.hash == nil {
if commit.AggVote != nil {
aggVote := &AggVote{AggVote: commit.AggVote}
commit.hash = aggVote.Hash()
} else {
bs := make([][]byte, len(commit.Precommits)) bs := make([][]byte, len(commit.Precommits))
for i, item := range commit.Precommits { for i, item := range commit.Precommits {
precommit := Vote{Vote: item} precommit := Vote{Vote: item}
...@@ -351,6 +374,7 @@ func (commit *Commit) Hash() []byte { ...@@ -351,6 +374,7 @@ func (commit *Commit) Hash() []byte {
} }
commit.hash = merkle.GetMerkleRoot(bs) commit.hash = merkle.GetMerkleRoot(bs)
} }
}
return commit.hash return commit.hash
} }
...@@ -366,9 +390,11 @@ func (commit *Commit) StringIndented(indent string) string { ...@@ -366,9 +390,11 @@ func (commit *Commit) StringIndented(indent string) string {
return Fmt(`Commit{ return Fmt(`Commit{
%s BlockID: %v %s BlockID: %v
%s Precommits: %v %s Precommits: %v
%s AggVote: %v
%s}#%v`, %s}#%v`,
indent, commit.BlockID, indent, commit.BlockID,
indent, strings.Join(precommitStrings, "\n"+indent+" "), indent, strings.Join(precommitStrings, "\n"+indent+" "),
indent, commit.AggVote.String(),
indent, commit.hash) indent, commit.hash)
} }
......
...@@ -4,7 +4,17 @@ ...@@ -4,7 +4,17 @@
package types 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 ( var (
// ErrHeightLessThanOne error type // ErrHeightLessThanOne error type
...@@ -18,3 +28,17 @@ var ( ...@@ -18,3 +28,17 @@ var (
// ErrLastBlockID error type // ErrLastBlockID error type
ErrLastBlockID = errors.New("ErrLastBlockID") 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,
}
)
...@@ -138,6 +138,30 @@ func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err er ...@@ -138,6 +138,30 @@ func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err er
return 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 ... // Prevotes ...
func (hvs *HeightVoteSet) Prevotes(round int) *VoteSet { func (hvs *HeightVoteSet) Prevotes(round int) *VoteSet {
hvs.mtx.Lock() hvs.mtx.Lock()
......
...@@ -113,7 +113,7 @@ func (params *ConsensusParams) Validate() error { ...@@ -113,7 +113,7 @@ func (params *ConsensusParams) Validate() error {
func (params *ConsensusParams) Hash() []byte { func (params *ConsensusParams) Hash() []byte {
bytes, err := json.Marshal(params) bytes, err := json.Marshal(params)
if err != nil { if err != nil {
blocklog.Error("block header Hash() marshal failed", "error", err) ttlog.Error("block header Hash() marshal failed", "error", err)
return nil return nil
} }
return crypto.Ripemd160(bytes) return crypto.Ripemd160(bytes)
......
...@@ -6,6 +6,7 @@ package types ...@@ -6,6 +6,7 @@ package types
import ( import (
"bytes" "bytes"
"encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
...@@ -14,8 +15,6 @@ import ( ...@@ -14,8 +15,6 @@ import (
"sync" "sync"
"time" "time"
"encoding/hex"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
) )
...@@ -296,15 +295,15 @@ func (pv *PrivValidatorImp) save() { ...@@ -296,15 +295,15 @@ func (pv *PrivValidatorImp) save() {
LastStep: pv.LastStep, LastStep: pv.LastStep,
LastSignature: nil, LastSignature: nil,
} }
privValFS.PrivKey = KeyText{Kind: "ed25519", Data: Fmt("%X", pv.PrivKey.Bytes()[:])} privValFS.PrivKey = KeyText{Kind: CryptoName, Data: Fmt("%X", pv.PrivKey.Bytes()[:])}
privValFS.PubKey = KeyText{Kind: "ed25519", Data: pv.PubKey.KeyString()} privValFS.PubKey = KeyText{Kind: CryptoName, Data: pv.PubKey.KeyString()}
if len(pv.LastSignBytes) != 0 { if len(pv.LastSignBytes) != 0 {
tmp := Fmt("%X", pv.LastSignBytes[:]) tmp := Fmt("%X", pv.LastSignBytes[:])
privValFS.LastSignBytes = tmp privValFS.LastSignBytes = tmp
} }
if pv.LastSignature != nil { if pv.LastSignature != nil {
sig := Fmt("%X", pv.LastSignature.Bytes()[:]) 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) jsonBytes, err := json.Marshal(privValFS)
if err != nil { if err != nil {
......
...@@ -42,6 +42,7 @@ const ( ...@@ -42,6 +42,7 @@ const (
ProposalHeartbeatID = byte(0x08) ProposalHeartbeatID = byte(0x08)
ProposalBlockID = byte(0x09) ProposalBlockID = byte(0x09)
ValidBlockID = byte(0x0a) ValidBlockID = byte(0x0a)
AggVoteID = byte(0x0b)
PacketTypePing = byte(0xff) PacketTypePing = byte(0xff)
PacketTypePong = byte(0xfe) PacketTypePong = byte(0xfe)
...@@ -60,6 +61,7 @@ func InitMessageMap() { ...@@ -60,6 +61,7 @@ func InitMessageMap() {
ProposalHeartbeatID: reflect.TypeOf(tmtypes.Heartbeat{}), ProposalHeartbeatID: reflect.TypeOf(tmtypes.Heartbeat{}),
ProposalBlockID: reflect.TypeOf(tmtypes.TendermintBlock{}), ProposalBlockID: reflect.TypeOf(tmtypes.TendermintBlock{}),
ValidBlockID: reflect.TypeOf(tmtypes.ValidBlockMsg{}), ValidBlockID: reflect.TypeOf(tmtypes.ValidBlockMsg{}),
AggVoteID: reflect.TypeOf(tmtypes.AggVote{}),
} }
} }
...@@ -186,6 +188,7 @@ type PeerRoundState struct { ...@@ -186,6 +188,7 @@ type PeerRoundState struct {
LastCommit *BitArray // All commit precommits of commit for last height. LastCommit *BitArray // All commit precommits of commit for last height.
CatchupCommitRound int // Round that we have commit for. Not necessarily unique. -1 if none. 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 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 // String returns a string representation of the PeerRoundState
...@@ -204,17 +207,19 @@ func (prs PeerRoundState) StringIndented(indent string) string { ...@@ -204,17 +207,19 @@ func (prs PeerRoundState) StringIndented(indent string) string {
%s Prevotes %v %s Prevotes %v
%s Precommits %v %s Precommits %v
%s LastCommit %v (round %v) %s LastCommit %v (round %v)
%s Catchup %v (round %v) %s CatchupCommit %v (round %v)
%s AggPrecommit %v
%s}`, %s}`,
indent, prs.Height, prs.Round, prs.Step, prs.StartTime, indent, prs.Height, prs.Round, prs.Step, prs.StartTime,
indent, prs.Proposal, indent, prs.Proposal,
indent, prs.ProposalBlock, indent, prs.ProposalBlock,
indent, prs.ProposalBlock, indent, prs.ProposalBlockHash,
indent, prs.ProposalPOL, prs.ProposalPOLRound, indent, prs.ProposalPOL, prs.ProposalPOLRound,
indent, prs.Prevotes, indent, prs.Prevotes,
indent, prs.Precommits, indent, prs.Precommits,
indent, prs.LastCommit, prs.LastCommitRound, indent, prs.LastCommit, prs.LastCommitRound,
indent, prs.CatchupCommit, prs.CatchupCommitRound, indent, prs.CatchupCommit, prs.CatchupCommitRound,
indent, prs.AggPrecommit,
indent) indent)
} }
...@@ -274,6 +279,12 @@ type CanonicalJSONOnceVote struct { ...@@ -274,6 +279,12 @@ type CanonicalJSONOnceVote struct {
Vote CanonicalJSONVote `json:"vote"` Vote CanonicalJSONVote `json:"vote"`
} }
// CanonicalJSONOnceAggVote ...
type CanonicalJSONOnceAggVote struct {
ChainID string `json:"chain_id"`
AggVote CanonicalJSONVote `json:"agg_vote"`
}
// CanonicalJSONOnceHeartbeat ... // CanonicalJSONOnceHeartbeat ...
type CanonicalJSONOnceHeartbeat struct { type CanonicalJSONOnceHeartbeat struct {
ChainID string `json:"chain_id"` ChainID string `json:"chain_id"`
...@@ -305,11 +316,26 @@ func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal { ...@@ -305,11 +316,26 @@ func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
// CanonicalVote ... // CanonicalVote ...
func CanonicalVote(vote *Vote) CanonicalJSONVote { 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{ return CanonicalJSONVote{
BlockID: CanonicalJSONBlockID{Hash: vote.BlockID.Hash}, BlockID: CanonicalJSONBlockID{Hash: vote.BlockID.Hash},
Height: vote.Height, Height: vote.Height,
Round: int(vote.Round), Round: int(vote.Round),
Timestamp: CanonicalTime(time.Unix(0, vote.Timestamp)), Timestamp: "",
Type: byte(vote.Type), Type: byte(vote.Type),
} }
} }
......
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
"time" "time"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types" tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
) )
...@@ -27,7 +26,7 @@ var ( ...@@ -27,7 +26,7 @@ var (
ErrVoteNonDeterministicSignature = errors.New("Non-deterministic signature") ErrVoteNonDeterministicSignature = errors.New("Non-deterministic signature")
ErrVoteConflict = errors.New("Conflicting vote") ErrVoteConflict = errors.New("Conflicting vote")
ErrVoteNil = errors.New("Nil 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. // 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 ...@@ -156,7 +155,7 @@ func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error
byteVote, e := json.Marshal(&canonical) byteVote, e := json.Marshal(&canonical)
if e != nil { if e != nil {
*err = e *err = e
votelog.Error("vote WriteSignBytes marshal failed", "err", e) ttlog.Error("vote WriteSignBytes marshal failed", "err", e)
return return
} }
number, writeErr := w.Write(byteVote) number, writeErr := w.Write(byteVote)
...@@ -200,7 +199,7 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { ...@@ -200,7 +199,7 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
sig, err := ConsensusCrypto.SignatureFromBytes(vote.Signature) sig, err := ConsensusCrypto.SignatureFromBytes(vote.Signature)
if err != nil { if err != nil {
votelog.Error("vote Verify failed", "err", err) ttlog.Error("vote Verify fail", "err", err)
return err return err
} }
...@@ -217,7 +216,109 @@ func (vote *Vote) Hash() []byte { ...@@ -217,7 +216,109 @@ func (vote *Vote) Hash() []byte {
} }
bytes, err := json.Marshal(vote) bytes, err := json.Marshal(vote)
if err != nil { 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 return nil
} }
......
...@@ -12,13 +12,10 @@ import ( ...@@ -12,13 +12,10 @@ import (
"strings" "strings"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle" "github.com/33cn/chain33/common/merkle"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var validatorsetlog = log15.New("module", "tendermint-val")
// Validator ... // Validator ...
type Validator struct { type Validator struct {
Address []byte `json:"address"` Address []byte `json:"address"`
...@@ -313,7 +310,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height ...@@ -313,7 +310,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
if valSet.Size() != len(commit.Precommits) { if valSet.Size() != len(commit.Precommits) {
return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits)) return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits))
} }
validatorsetlog.Debug("VerifyCommit will get commit height", "height", commit.Height()) ttlog.Debug("VerifyCommit will get commit height", "height", commit.Height())
commitHeight := commit.Height() commitHeight := commit.Height()
if height != commitHeight { if height != commitHeight {
return fmt.Errorf("VerifyCommit 1 Invalid commit -- wrong height: %v vs %v", 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 ...@@ -322,6 +319,29 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
talliedVotingPower := int64(0) talliedVotingPower := int64(0)
round := commit.Round() 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 { for idx, item := range commit.Precommits {
// may be nil if validator skipped. // may be nil if validator skipped.
if item == nil || len(item.Signature) == 0 { if item == nil || len(item.Signature) == 0 {
...@@ -338,8 +358,8 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height ...@@ -338,8 +358,8 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx) return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx)
} }
_, val := valSet.GetByIndex(idx) _, val := valSet.GetByIndex(idx)
// Validate signature
// Validate signature
precommitSignBytes := SignBytes(chainID, precommit) precommitSignBytes := SignBytes(chainID, precommit)
sig, err := ConsensusCrypto.SignatureFromBytes(precommit.Signature) sig, err := ConsensusCrypto.SignatureFromBytes(precommit.Signature)
if err != nil { if err != nil {
...@@ -358,6 +378,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height ...@@ -358,6 +378,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
// Good precommit! // Good precommit!
talliedVotingPower += val.VotingPower talliedVotingPower += val.VotingPower
} }
}
if talliedVotingPower > valSet.TotalVotingPower()*2/3 { if talliedVotingPower > valSet.TotalVotingPower()*2/3 {
return nil return nil
......
...@@ -8,7 +8,9 @@ import ( ...@@ -8,7 +8,9 @@ import (
"bytes" "bytes"
"strings" "strings"
"sync" "sync"
"time"
"github.com/33cn/chain33/common/crypto"
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types" tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -63,6 +65,7 @@ type VoteSet struct { ...@@ -63,6 +65,7 @@ type VoteSet struct {
maj23 *tmtypes.BlockID // First 2/3 majority seen maj23 *tmtypes.BlockID // First 2/3 majority seen
votesByBlock map[string]*blockVotes // string(blockHash|blockParts) -> blockVotes votesByBlock map[string]*blockVotes // string(blockHash|blockParts) -> blockVotes
peerMaj23s map[string]*tmtypes.BlockID // Maj23 for each peer 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. // 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 * ...@@ -82,6 +85,7 @@ func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *
maj23: nil, maj23: nil,
votesByBlock: make(map[string]*blockVotes, valSet.Size()), votesByBlock: make(map[string]*blockVotes, valSet.Size()),
peerMaj23s: make(map[string]*tmtypes.BlockID), peerMaj23s: make(map[string]*tmtypes.BlockID),
aggVote: nil,
} }
} }
...@@ -133,7 +137,7 @@ func (voteSet *VoteSet) Size() int { ...@@ -133,7 +137,7 @@ func (voteSet *VoteSet) Size() int {
// NOTE: Vote must not be nil // NOTE: Vote must not be nil
func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) { func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
if voteSet == nil { if voteSet == nil {
PanicSanity("AddVote() on nil VoteSet") return false, errors.New("nil vote set")
} }
voteSet.mtx.Lock() voteSet.mtx.Lock()
defer voteSet.mtx.Unlock() defer voteSet.mtx.Unlock()
...@@ -291,6 +295,146 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower ...@@ -291,6 +295,146 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
return true, conflicting 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. // 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, // NOTE: if there are too many peers, or too much peer churn,
// this can cause memory issues. // this can cause memory issues.
...@@ -446,12 +590,12 @@ func (voteSet *VoteSet) StringIndented(indent string) string { ...@@ -446,12 +590,12 @@ func (voteSet *VoteSet) StringIndented(indent string) string {
} }
} }
return Fmt(`VoteSet{ 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 %v
%s %v %s %v
%s}`, %s}`,
indent, voteSet.height, voteSet.round, voteSet.voteType, indent, voteSet.height, voteSet.round, voteSet.voteType, voteSet.maj23,
indent, strings.Join(voteStrings, "\n"+indent+" "), indent, strings.Join(voteStrings, "\n"+indent+" "),
indent, voteSet.votesBitArray, indent, voteSet.votesBitArray,
indent, voteSet.peerMaj23s, indent, voteSet.peerMaj23s,
...@@ -491,10 +635,15 @@ func (voteSet *VoteSet) MakeCommit() *tmtypes.TendermintCommit { ...@@ -491,10 +635,15 @@ func (voteSet *VoteSet) MakeCommit() *tmtypes.TendermintCommit {
votesCopy[i] = &tmtypes.Vote{} 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{ return &tmtypes.TendermintCommit{
BlockID: voteSet.maj23, BlockID: voteSet.maj23,
Precommits: votesCopy, Precommits: votesCopy,
AggVote: aggVote,
} }
} }
...@@ -549,4 +698,5 @@ type VoteSetReader interface { ...@@ -549,4 +698,5 @@ type VoteSetReader interface {
BitArray() *BitArray BitArray() *BitArray
GetByIndex(int) *Vote GetByIndex(int) *Vote
IsCommit() bool IsCommit() bool
GetAggVote() *AggVote
} }
// 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)
}
// 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
}
}
package init package init
import ( 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/ecdsa" //auto gen
_ "github.com/33cn/plugin/plugin/crypto/sm2" //auto gen _ "github.com/33cn/plugin/plugin/crypto/sm2" //auto gen
) )
...@@ -25,6 +25,7 @@ var ( ...@@ -25,6 +25,7 @@ var (
strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
genFile = "genesis_file.json" genFile = "genesis_file.json"
pvFile = "priv_validator_" pvFile = "priv_validator_"
AuthBLS = 259
) )
// ValCmd valnode cmd register // ValCmd valnode cmd register
...@@ -164,8 +165,9 @@ func CreateCmd() *cobra.Command { ...@@ -164,8 +165,9 @@ func CreateCmd() *cobra.Command {
} }
func addCreateCmdFlags(cmd *cobra.Command) { func addCreateCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("num", "n", "", "Num of the keyfile to create") cmd.Flags().StringP("num", "n", "", "num of the keyfile to create")
cmd.MarkFlagRequired("num") cmd.MarkFlagRequired("num")
cmd.Flags().StringP("type", "t", "ed25519", "sign type of the keyfile (secp256k1, ed25519, sm2, bls)")
} }
// RandStr ... // RandStr ...
...@@ -192,10 +194,11 @@ MAIN_LOOP: ...@@ -192,10 +194,11 @@ MAIN_LOOP:
return string(chars) return string(chars)
} }
func initCryptoImpl() error { func initCryptoImpl(signType int) error {
cr, err := crypto.New(types.GetSignName("", types.ED25519)) ttypes.CryptoName = types.GetSignName("", signType)
cr, err := crypto.New(ttypes.CryptoName)
if err != nil { if err != nil {
fmt.Printf("New crypto impl failed err: %v", err) fmt.Printf("Init crypto fail: %v", err)
return err return err
} }
ttypes.ConsensusCrypto = cr ttypes.ConsensusCrypto = cr
...@@ -204,7 +207,13 @@ func initCryptoImpl() error { ...@@ -204,7 +207,13 @@ func initCryptoImpl() error {
func createFiles(cmd *cobra.Command, args []string) { func createFiles(cmd *cobra.Command, args []string) {
// init crypto instance // 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 { if err != nil {
return return
} }
...@@ -232,7 +241,7 @@ func createFiles(cmd *cobra.Command, args []string) { ...@@ -232,7 +241,7 @@ func createFiles(cmd *cobra.Command, args []string) {
// create genesis validator by the pubkey of private validator // create genesis validator by the pubkey of private validator
gv := ttypes.GenesisValidator{ gv := ttypes.GenesisValidator{
PubKey: ttypes.KeyText{Kind: "ed25519", Data: privValidator.GetPubKey().KeyString()}, PubKey: ttypes.KeyText{Kind: ttypes.CryptoName, Data: privValidator.GetPubKey().KeyString()},
Power: 10, Power: 10,
} }
genDoc.Validators = append(genDoc.Validators, gv) genDoc.Validators = append(genDoc.Validators, gv)
......
...@@ -35,11 +35,22 @@ func (val *ValNode) Exec_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types ...@@ -35,11 +35,22 @@ func (val *ValNode) Exec_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types
return receipt, nil 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) { func getManageKey(key string, db dbm.KV) ([]byte, error) {
manageKey := types.ManageKey(key) manageKey := types.ManageKey(key)
value, err := db.Get([]byte(manageKey)) value, err := db.Get([]byte(manageKey))
if err != nil { if err != nil {
return nil, err clog.Info("getManageKey not find", "manageKey", manageKey, "err", err)
return getConfigKey(key, db)
} }
return value, nil return value, nil
} }
......
...@@ -5,86 +5,88 @@ import "blockchain.proto"; ...@@ -5,86 +5,88 @@ import "blockchain.proto";
package types; package types;
message BlockID { message BlockID {
bytes Hash = 1; bytes hash = 1;
} }
message TendermintBitArray { message TendermintBitArray {
int32 Bits = 1; int32 bits = 1;
repeated uint64 Elems = 2; repeated uint64 elems = 2;
} }
message Vote { message Vote {
bytes ValidatorAddress = 1; bytes validatorAddress = 1;
int32 ValidatorIndex = 2; int32 validatorIndex = 2;
int64 Height = 3; int64 height = 3;
int32 Round = 4; int32 round = 4;
int64 Timestamp = 5; int64 timestamp = 5;
uint32 Type = 6; uint32 type = 6;
BlockID BlockID = 7; BlockID blockID = 7;
bytes Signature = 8; bytes signature = 8;
bool useAggSig = 9;
} }
message TendermintCommit { message TendermintCommit {
BlockID BlockID = 1; BlockID blockID = 1;
repeated Vote Precommits = 2; repeated Vote precommits = 2;
AggVote aggVote = 3;
} }
message TendermintBlockInfo { message TendermintBlockInfo {
State State = 2; State state = 2;
Proposal Proposal = 3; Proposal proposal = 3;
TendermintBlock block = 4; TendermintBlock block = 4;
} }
message BlockSize { message BlockSize {
int32 MaxBytes = 1; int32 maxBytes = 1;
int32 MaxTxs = 2; int32 maxTxs = 2;
int64 MaxGas = 3; int64 maxGas = 3;
} }
message TxSize { message TxSize {
int32 MaxBytes = 1; int32 maxBytes = 1;
int64 MaxGas = 2; int64 maxGas = 2;
} }
message BlockGossip { message BlockGossip {
int32 BlockPartSizeBytes = 1; int32 blockPartSizeBytes = 1;
} }
message EvidenceParams { message EvidenceParams {
int64 MaxAge = 1; int64 maxAge = 1;
} }
message ConsensusParams { message ConsensusParams {
BlockSize BlockSize = 1; BlockSize blockSize = 1;
TxSize TxSize = 2; TxSize txSize = 2;
BlockGossip BlockGossip = 3; BlockGossip blockGossip = 3;
EvidenceParams EvidenceParams = 4; EvidenceParams evidenceParams = 4;
} }
message Validator { message Validator {
bytes Address = 1; bytes address = 1;
bytes PubKey = 2; bytes pubKey = 2;
int64 VotingPower = 3; int64 votingPower = 3;
int64 Accum = 4; int64 accum = 4;
} }
message ValidatorSet { message ValidatorSet {
repeated Validator Validators = 1; repeated Validator validators = 1;
Validator Proposer = 2; Validator proposer = 2;
} }
message State { message State {
string ChainID = 1; string chainID = 1;
int64 LastBlockHeight = 2; int64 lastBlockHeight = 2;
int64 LastBlockTotalTx = 3; int64 lastBlockTotalTx = 3;
BlockID LastBlockID = 4; BlockID lastBlockID = 4;
int64 LastBlockTime = 5; int64 lastBlockTime = 5;
ValidatorSet Validators = 6; ValidatorSet validators = 6;
ValidatorSet LastValidators = 7; ValidatorSet lastValidators = 7;
int64 LastHeightValidatorsChanged = 8; int64 lastHeightValidatorsChanged = 8;
ConsensusParams ConsensusParams = 9; ConsensusParams consensusParams = 9;
int64 LastHeightConsensusParamsChanged = 10; int64 lastHeightConsensusParamsChanged = 10;
bytes LastResultsHash = 11; bytes lastResultsHash = 11;
bytes AppHash = 12; bytes appHash = 12;
} }
message TendermintBlockHeader { message TendermintBlockHeader {
...@@ -174,3 +176,14 @@ message Heartbeat { ...@@ -174,3 +176,14 @@ message Heartbeat {
message IsHealthy { message IsHealthy {
bool isHealthy = 1; 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
...@@ -23,7 +23,7 @@ var _ = math.Inf ...@@ -23,7 +23,7 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type BlockID struct { type BlockID struct {
Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"` Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -62,8 +62,8 @@ func (m *BlockID) GetHash() []byte { ...@@ -62,8 +62,8 @@ func (m *BlockID) GetHash() []byte {
} }
type TendermintBitArray struct { type TendermintBitArray struct {
Bits int32 `protobuf:"varint,1,opt,name=Bits,proto3" json:"Bits,omitempty"` Bits int32 `protobuf:"varint,1,opt,name=bits,proto3" json:"bits,omitempty"`
Elems []uint64 `protobuf:"varint,2,rep,packed,name=Elems,proto3" json:"Elems,omitempty"` Elems []uint64 `protobuf:"varint,2,rep,packed,name=elems,proto3" json:"elems,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -109,14 +109,15 @@ func (m *TendermintBitArray) GetElems() []uint64 { ...@@ -109,14 +109,15 @@ func (m *TendermintBitArray) GetElems() []uint64 {
} }
type Vote struct { type Vote struct {
ValidatorAddress []byte `protobuf:"bytes,1,opt,name=ValidatorAddress,proto3" json:"ValidatorAddress,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"` ValidatorIndex int32 `protobuf:"varint,2,opt,name=validatorIndex,proto3" json:"validatorIndex,omitempty"`
Height int64 `protobuf:"varint,3,opt,name=Height,proto3" json:"Height,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"` Round int32 `protobuf:"varint,4,opt,name=round,proto3" json:"round,omitempty"`
Timestamp int64 `protobuf:"varint,5,opt,name=Timestamp,proto3" json:"Timestamp,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"` Type uint32 `protobuf:"varint,6,opt,name=type,proto3" json:"type,omitempty"`
BlockID *BlockID `protobuf:"bytes,7,opt,name=BlockID,proto3" json:"BlockID,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"` 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_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -203,9 +204,17 @@ func (m *Vote) GetSignature() []byte { ...@@ -203,9 +204,17 @@ func (m *Vote) GetSignature() []byte {
return nil return nil
} }
func (m *Vote) GetUseAggSig() bool {
if m != nil {
return m.UseAggSig
}
return false
}
type TendermintCommit struct { type TendermintCommit struct {
BlockID *BlockID `protobuf:"bytes,1,opt,name=BlockID,proto3" json:"BlockID,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"` 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_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -250,9 +259,16 @@ func (m *TendermintCommit) GetPrecommits() []*Vote { ...@@ -250,9 +259,16 @@ func (m *TendermintCommit) GetPrecommits() []*Vote {
return nil return nil
} }
func (m *TendermintCommit) GetAggVote() *AggVote {
if m != nil {
return m.AggVote
}
return nil
}
type TendermintBlockInfo struct { type TendermintBlockInfo struct {
State *State `protobuf:"bytes,2,opt,name=State,proto3" json:"State,omitempty"` State *State `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"`
Proposal *Proposal `protobuf:"bytes,3,opt,name=Proposal,proto3" json:"Proposal,omitempty"` Proposal *Proposal `protobuf:"bytes,3,opt,name=proposal,proto3" json:"proposal,omitempty"`
Block *TendermintBlock `protobuf:"bytes,4,opt,name=block,proto3" json:"block,omitempty"` Block *TendermintBlock `protobuf:"bytes,4,opt,name=block,proto3" json:"block,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
...@@ -306,9 +322,9 @@ func (m *TendermintBlockInfo) GetBlock() *TendermintBlock { ...@@ -306,9 +322,9 @@ func (m *TendermintBlockInfo) GetBlock() *TendermintBlock {
} }
type BlockSize struct { type BlockSize struct {
MaxBytes int32 `protobuf:"varint,1,opt,name=MaxBytes,proto3" json:"MaxBytes,omitempty"` MaxBytes int32 `protobuf:"varint,1,opt,name=maxBytes,proto3" json:"maxBytes,omitempty"`
MaxTxs int32 `protobuf:"varint,2,opt,name=MaxTxs,proto3" json:"MaxTxs,omitempty"` MaxTxs int32 `protobuf:"varint,2,opt,name=maxTxs,proto3" json:"maxTxs,omitempty"`
MaxGas int64 `protobuf:"varint,3,opt,name=MaxGas,proto3" json:"MaxGas,omitempty"` MaxGas int64 `protobuf:"varint,3,opt,name=maxGas,proto3" json:"maxGas,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -361,8 +377,8 @@ func (m *BlockSize) GetMaxGas() int64 { ...@@ -361,8 +377,8 @@ func (m *BlockSize) GetMaxGas() int64 {
} }
type TxSize struct { type TxSize struct {
MaxBytes int32 `protobuf:"varint,1,opt,name=MaxBytes,proto3" json:"MaxBytes,omitempty"` MaxBytes int32 `protobuf:"varint,1,opt,name=maxBytes,proto3" json:"maxBytes,omitempty"`
MaxGas int64 `protobuf:"varint,2,opt,name=MaxGas,proto3" json:"MaxGas,omitempty"` MaxGas int64 `protobuf:"varint,2,opt,name=maxGas,proto3" json:"maxGas,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -408,7 +424,7 @@ func (m *TxSize) GetMaxGas() int64 { ...@@ -408,7 +424,7 @@ func (m *TxSize) GetMaxGas() int64 {
} }
type BlockGossip struct { type BlockGossip struct {
BlockPartSizeBytes int32 `protobuf:"varint,1,opt,name=BlockPartSizeBytes,proto3" json:"BlockPartSizeBytes,omitempty"` BlockPartSizeBytes int32 `protobuf:"varint,1,opt,name=blockPartSizeBytes,proto3" json:"blockPartSizeBytes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -447,7 +463,7 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 { ...@@ -447,7 +463,7 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 {
} }
type EvidenceParams struct { type EvidenceParams struct {
MaxAge int64 `protobuf:"varint,1,opt,name=MaxAge,proto3" json:"MaxAge,omitempty"` MaxAge int64 `protobuf:"varint,1,opt,name=maxAge,proto3" json:"maxAge,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -486,10 +502,10 @@ func (m *EvidenceParams) GetMaxAge() int64 { ...@@ -486,10 +502,10 @@ func (m *EvidenceParams) GetMaxAge() int64 {
} }
type ConsensusParams struct { type ConsensusParams struct {
BlockSize *BlockSize `protobuf:"bytes,1,opt,name=BlockSize,proto3" json:"BlockSize,omitempty"` BlockSize *BlockSize `protobuf:"bytes,1,opt,name=blockSize,proto3" json:"blockSize,omitempty"`
TxSize *TxSize `protobuf:"bytes,2,opt,name=TxSize,proto3" json:"TxSize,omitempty"` TxSize *TxSize `protobuf:"bytes,2,opt,name=txSize,proto3" json:"txSize,omitempty"`
BlockGossip *BlockGossip `protobuf:"bytes,3,opt,name=BlockGossip,proto3" json:"BlockGossip,omitempty"` BlockGossip *BlockGossip `protobuf:"bytes,3,opt,name=blockGossip,proto3" json:"blockGossip,omitempty"`
EvidenceParams *EvidenceParams `protobuf:"bytes,4,opt,name=EvidenceParams,proto3" json:"EvidenceParams,omitempty"` EvidenceParams *EvidenceParams `protobuf:"bytes,4,opt,name=evidenceParams,proto3" json:"evidenceParams,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -549,10 +565,10 @@ func (m *ConsensusParams) GetEvidenceParams() *EvidenceParams { ...@@ -549,10 +565,10 @@ func (m *ConsensusParams) GetEvidenceParams() *EvidenceParams {
} }
type Validator struct { type Validator struct {
Address []byte `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty"` Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
PubKey []byte `protobuf:"bytes,2,opt,name=PubKey,proto3" json:"PubKey,omitempty"` PubKey []byte `protobuf:"bytes,2,opt,name=pubKey,proto3" json:"pubKey,omitempty"`
VotingPower int64 `protobuf:"varint,3,opt,name=VotingPower,proto3" json:"VotingPower,omitempty"` VotingPower int64 `protobuf:"varint,3,opt,name=votingPower,proto3" json:"votingPower,omitempty"`
Accum int64 `protobuf:"varint,4,opt,name=Accum,proto3" json:"Accum,omitempty"` Accum int64 `protobuf:"varint,4,opt,name=accum,proto3" json:"accum,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -612,8 +628,8 @@ func (m *Validator) GetAccum() int64 { ...@@ -612,8 +628,8 @@ func (m *Validator) GetAccum() int64 {
} }
type ValidatorSet struct { type ValidatorSet struct {
Validators []*Validator `protobuf:"bytes,1,rep,name=Validators,proto3" json:"Validators,omitempty"` Validators []*Validator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"`
Proposer *Validator `protobuf:"bytes,2,opt,name=Proposer,proto3" json:"Proposer,omitempty"` Proposer *Validator `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -659,18 +675,18 @@ func (m *ValidatorSet) GetProposer() *Validator { ...@@ -659,18 +675,18 @@ func (m *ValidatorSet) GetProposer() *Validator {
} }
type State struct { type State struct {
ChainID string `protobuf:"bytes,1,opt,name=ChainID,proto3" json:"ChainID,omitempty"` ChainID string `protobuf:"bytes,1,opt,name=chainID,proto3" json:"chainID,omitempty"`
LastBlockHeight int64 `protobuf:"varint,2,opt,name=LastBlockHeight,proto3" json:"LastBlockHeight,omitempty"` LastBlockHeight int64 `protobuf:"varint,2,opt,name=lastBlockHeight,proto3" json:"lastBlockHeight,omitempty"`
LastBlockTotalTx int64 `protobuf:"varint,3,opt,name=LastBlockTotalTx,proto3" json:"LastBlockTotalTx,omitempty"` LastBlockTotalTx int64 `protobuf:"varint,3,opt,name=lastBlockTotalTx,proto3" json:"lastBlockTotalTx,omitempty"`
LastBlockID *BlockID `protobuf:"bytes,4,opt,name=LastBlockID,proto3" json:"LastBlockID,omitempty"` LastBlockID *BlockID `protobuf:"bytes,4,opt,name=lastBlockID,proto3" json:"lastBlockID,omitempty"`
LastBlockTime int64 `protobuf:"varint,5,opt,name=LastBlockTime,proto3" json:"LastBlockTime,omitempty"` LastBlockTime int64 `protobuf:"varint,5,opt,name=lastBlockTime,proto3" json:"lastBlockTime,omitempty"`
Validators *ValidatorSet `protobuf:"bytes,6,opt,name=Validators,proto3" json:"Validators,omitempty"` Validators *ValidatorSet `protobuf:"bytes,6,opt,name=validators,proto3" json:"validators,omitempty"`
LastValidators *ValidatorSet `protobuf:"bytes,7,opt,name=LastValidators,proto3" json:"LastValidators,omitempty"` LastValidators *ValidatorSet `protobuf:"bytes,7,opt,name=lastValidators,proto3" json:"lastValidators,omitempty"`
LastHeightValidatorsChanged int64 `protobuf:"varint,8,opt,name=LastHeightValidatorsChanged,proto3" json:"LastHeightValidatorsChanged,omitempty"` LastHeightValidatorsChanged int64 `protobuf:"varint,8,opt,name=lastHeightValidatorsChanged,proto3" json:"lastHeightValidatorsChanged,omitempty"`
ConsensusParams *ConsensusParams `protobuf:"bytes,9,opt,name=ConsensusParams,proto3" json:"ConsensusParams,omitempty"` ConsensusParams *ConsensusParams `protobuf:"bytes,9,opt,name=consensusParams,proto3" json:"consensusParams,omitempty"`
LastHeightConsensusParamsChanged int64 `protobuf:"varint,10,opt,name=LastHeightConsensusParamsChanged,proto3" json:"LastHeightConsensusParamsChanged,omitempty"` LastHeightConsensusParamsChanged int64 `protobuf:"varint,10,opt,name=lastHeightConsensusParamsChanged,proto3" json:"lastHeightConsensusParamsChanged,omitempty"`
LastResultsHash []byte `protobuf:"bytes,11,opt,name=LastResultsHash,proto3" json:"LastResultsHash,omitempty"` LastResultsHash []byte `protobuf:"bytes,11,opt,name=lastResultsHash,proto3" json:"lastResultsHash,omitempty"`
AppHash []byte `protobuf:"bytes,12,opt,name=AppHash,proto3" json:"AppHash,omitempty"` AppHash []byte `protobuf:"bytes,12,opt,name=appHash,proto3" json:"appHash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -1566,6 +1582,101 @@ func (m *IsHealthy) GetIsHealthy() bool { ...@@ -1566,6 +1582,101 @@ func (m *IsHealthy) GetIsHealthy() bool {
return false 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() { func init() {
proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*BlockID)(nil), "types.BlockID")
proto.RegisterType((*TendermintBitArray)(nil), "types.TendermintBitArray") proto.RegisterType((*TendermintBitArray)(nil), "types.TendermintBitArray")
...@@ -1591,6 +1702,7 @@ func init() { ...@@ -1591,6 +1702,7 @@ func init() {
proto.RegisterType((*VoteSetBitsMsg)(nil), "types.VoteSetBitsMsg") proto.RegisterType((*VoteSetBitsMsg)(nil), "types.VoteSetBitsMsg")
proto.RegisterType((*Heartbeat)(nil), "types.Heartbeat") proto.RegisterType((*Heartbeat)(nil), "types.Heartbeat")
proto.RegisterType((*IsHealthy)(nil), "types.IsHealthy") proto.RegisterType((*IsHealthy)(nil), "types.IsHealthy")
proto.RegisterType((*AggVote)(nil), "types.AggVote")
} }
func init() { func init() {
...@@ -1598,89 +1710,90 @@ func init() { ...@@ -1598,89 +1710,90 @@ func init() {
} }
var fileDescriptor_04f926c8da23c367 = []byte{ var fileDescriptor_04f926c8da23c367 = []byte{
// 1334 bytes of a gzipped FileDescriptorProto // 1352 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xdf, 0x6e, 0x1b, 0xc5, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xdd, 0x8e, 0x1b, 0x35,
0x17, 0xd6, 0xc6, 0x7f, 0x12, 0x1f, 0xe7, 0x9f, 0xa6, 0xbf, 0xf6, 0x67, 0x4a, 0x90, 0xac, 0x11, 0x14, 0xd6, 0x6c, 0x32, 0xf9, 0x39, 0xc9, 0x26, 0x2b, 0xf7, 0x87, 0xb0, 0x14, 0x29, 0xb2, 0x00,
0x20, 0xd3, 0x56, 0xa1, 0x4a, 0x2b, 0x71, 0x51, 0x8a, 0x9a, 0xa4, 0x55, 0x13, 0x48, 0xa8, 0x35, 0x85, 0xb6, 0x5a, 0xaa, 0x6d, 0x25, 0x2e, 0x4a, 0x51, 0xb3, 0x2d, 0xea, 0x2e, 0xb4, 0x34, 0x72,
0xb6, 0xca, 0xf5, 0xc4, 0x1e, 0xec, 0x05, 0x7b, 0xd7, 0xec, 0x8c, 0x9d, 0x18, 0x89, 0x1b, 0xde, 0x56, 0xe5, 0xda, 0x49, 0x4c, 0x32, 0x90, 0xf9, 0x61, 0xec, 0x6c, 0x77, 0x91, 0x78, 0x08, 0x04,
0x00, 0x89, 0x27, 0xe0, 0x9e, 0x2b, 0x2e, 0x78, 0x04, 0x9e, 0x80, 0x4b, 0x78, 0x16, 0x74, 0xce, 0x0f, 0x80, 0xb8, 0xe7, 0x8a, 0x0b, 0x1e, 0x81, 0x27, 0xe0, 0x12, 0x9e, 0x05, 0xf9, 0xd8, 0xf3,
0xcc, 0xae, 0x67, 0xd7, 0x6e, 0x4a, 0x11, 0xe2, 0x6e, 0xcf, 0x37, 0xdf, 0xcc, 0xd9, 0x39, 0xe7, 0x9b, 0x34, 0xa5, 0x08, 0x21, 0xb8, 0x9b, 0xf3, 0xf9, 0xb3, 0x8f, 0xcf, 0x8f, 0x8f, 0x8f, 0x07,
0x3b, 0x67, 0x66, 0x60, 0xd7, 0xa8, 0xa8, 0xaf, 0x92, 0x71, 0x18, 0x99, 0xfd, 0x49, 0x12, 0x9b, 0xf6, 0x94, 0x08, 0x66, 0x22, 0xf6, 0xbd, 0x40, 0x1d, 0x44, 0x71, 0xa8, 0x42, 0xe2, 0xaa, 0x8b,
0x98, 0x55, 0xcc, 0x7c, 0xa2, 0xf4, 0xed, 0xdd, 0x8b, 0x51, 0xdc, 0xfb, 0xba, 0x37, 0x94, 0x61, 0x48, 0xc8, 0xfd, 0xbd, 0xc9, 0x32, 0x9c, 0x7e, 0x39, 0x5d, 0x70, 0x2f, 0x30, 0x03, 0xf4, 0x4d,
0x64, 0x07, 0xf8, 0x3b, 0xb0, 0x7e, 0x84, 0xd8, 0xe9, 0x53, 0xc6, 0xa0, 0x7c, 0x22, 0xf5, 0xb0, 0xa8, 0x1f, 0x69, 0xec, 0xe4, 0x21, 0x21, 0x50, 0x5d, 0x70, 0xb9, 0xe8, 0x39, 0x7d, 0x67, 0xd0,
0x11, 0x34, 0x83, 0xd6, 0xa6, 0xa0, 0x6f, 0xfe, 0x09, 0xb0, 0x6e, 0xb6, 0xd6, 0x51, 0x68, 0x0e, 0x66, 0xf8, 0x4d, 0x3f, 0x04, 0x72, 0x9a, 0xae, 0x75, 0xe4, 0xa9, 0x61, 0x1c, 0xf3, 0x0b, 0xcd,
0x93, 0x44, 0xce, 0x91, 0x79, 0x14, 0x1a, 0x4d, 0xcc, 0x8a, 0xa0, 0x6f, 0xf6, 0x3f, 0xa8, 0x3c, 0x9c, 0x78, 0x4a, 0x22, 0xd3, 0x65, 0xf8, 0x4d, 0x2e, 0x83, 0x2b, 0x96, 0xc2, 0x97, 0xbd, 0x9d,
0x1b, 0xa9, 0xb1, 0x6e, 0xac, 0x35, 0x4b, 0xad, 0xb2, 0xb0, 0x06, 0xff, 0x7e, 0x0d, 0xca, 0x2f, 0x7e, 0x65, 0x50, 0x65, 0x46, 0xa0, 0x3f, 0xec, 0x40, 0xf5, 0x59, 0xa8, 0x04, 0xb9, 0x0e, 0x7b,
0x63, 0xa3, 0xd8, 0x1d, 0xd8, 0x7d, 0x29, 0x47, 0x61, 0x5f, 0x9a, 0x38, 0x39, 0xec, 0xf7, 0x13, 0x67, 0x7c, 0xe9, 0xcd, 0xb8, 0x0a, 0xe3, 0xe1, 0x6c, 0x16, 0x0b, 0x29, 0xad, 0xa2, 0x35, 0x9c,
0xa5, 0xb5, 0x73, 0xb4, 0x84, 0xb3, 0xf7, 0x61, 0x3b, 0xc3, 0x4e, 0xa3, 0xbe, 0xba, 0x6a, 0xac, 0xbc, 0x03, 0x9d, 0x14, 0x3b, 0x09, 0x66, 0xe2, 0xbc, 0xb7, 0x83, 0x8a, 0x4a, 0x28, 0xb9, 0x0a,
0x91, 0xa3, 0x02, 0xca, 0x6e, 0x41, 0xf5, 0x44, 0x85, 0x83, 0xa1, 0x69, 0x94, 0x9a, 0x41, 0xab, 0xb5, 0x85, 0xf0, 0xe6, 0x0b, 0xd5, 0xab, 0xf4, 0x9d, 0x41, 0x85, 0x59, 0x49, 0x6f, 0x25, 0x0e,
0x24, 0x9c, 0x85, 0xbf, 0x22, 0xe2, 0x69, 0xd4, 0x6f, 0x94, 0x69, 0x9a, 0x35, 0xd8, 0x1e, 0xd4, 0x57, 0xc1, 0xac, 0x57, 0xc5, 0x69, 0x46, 0x20, 0xd7, 0xa0, 0xa9, 0x3c, 0x5f, 0x48, 0xc5, 0xfd,
0xba, 0xe1, 0x58, 0x69, 0x23, 0xc7, 0x93, 0x46, 0x85, 0x26, 0x2c, 0x00, 0xdc, 0x52, 0x77, 0x3e, 0xa8, 0xe7, 0xe2, 0x84, 0x0c, 0xd0, 0x26, 0x69, 0x17, 0xf5, 0x6a, 0x7d, 0x67, 0xb0, 0xcb, 0xf0,
0x51, 0x8d, 0x6a, 0x33, 0x68, 0x6d, 0x09, 0xfa, 0x66, 0xad, 0x2c, 0x36, 0x8d, 0xf5, 0x66, 0xd0, 0x9b, 0x0c, 0xa0, 0x3e, 0x31, 0xbe, 0xe9, 0xd5, 0xfb, 0xce, 0xa0, 0x75, 0xd8, 0x39, 0x40, 0x37,
0xaa, 0x1f, 0x6c, 0xef, 0x53, 0x18, 0xf7, 0x1d, 0x2a, 0xb2, 0xd0, 0xed, 0x41, 0xad, 0x13, 0x0e, 0x1e, 0x58, 0x8f, 0xb1, 0x64, 0x58, 0xaf, 0x2d, 0xbd, 0x79, 0xc0, 0xd5, 0x2a, 0x16, 0xbd, 0x06,
0x22, 0x69, 0xa6, 0x89, 0x6a, 0x6c, 0xd0, 0xb6, 0x16, 0x00, 0x0f, 0x61, 0x77, 0x11, 0xc4, 0xe3, 0x9a, 0x95, 0x01, 0x7a, 0x74, 0x25, 0xc5, 0x70, 0x3e, 0x1f, 0x7b, 0xf3, 0x5e, 0xb3, 0xef, 0x0c,
0x78, 0x3c, 0x0e, 0x8d, 0xbf, 0x76, 0x70, 0xfd, 0xda, 0x77, 0x01, 0xda, 0x89, 0xea, 0xd1, 0x34, 0x1a, 0x2c, 0x03, 0xe8, 0x77, 0x0e, 0xec, 0x65, 0x3e, 0x7e, 0x10, 0xfa, 0xbe, 0xa7, 0xf2, 0xaa,
0x1b, 0xdd, 0xfa, 0x41, 0xdd, 0x91, 0x31, 0xb4, 0xc2, 0x1b, 0xe6, 0x3f, 0x06, 0x70, 0xc3, 0x4b, 0x9d, 0xed, 0xaa, 0x6f, 0x00, 0x44, 0xb1, 0x98, 0xe2, 0x34, 0xe3, 0xfc, 0xd6, 0x61, 0xcb, 0x92,
0x18, 0x2d, 0x11, 0x7d, 0x19, 0x33, 0x0e, 0x95, 0x8e, 0x91, 0x46, 0x51, 0x24, 0xeb, 0x07, 0x9b, 0xb5, 0xe7, 0x59, 0x6e, 0x58, 0x2f, 0xcb, 0xe7, 0x73, 0x0d, 0xa3, 0xcb, 0xb2, 0x65, 0x87, 0x06,
0x6e, 0x3e, 0x61, 0xc2, 0x0e, 0xb1, 0xbb, 0xb0, 0xd1, 0x4e, 0xe2, 0x49, 0xac, 0xe5, 0x88, 0x02, 0x65, 0xc9, 0x30, 0xfd, 0xde, 0x81, 0x4b, 0xb9, 0xc8, 0xa3, 0xb2, 0xe0, 0xf3, 0x90, 0x50, 0x70,
0x5a, 0x3f, 0xd8, 0x71, 0xb4, 0x14, 0x16, 0x19, 0x81, 0xdd, 0x83, 0x0a, 0x69, 0x89, 0x62, 0x5c, 0xa5, 0xe2, 0x4a, 0x60, 0x48, 0x5a, 0x87, 0x6d, 0x3b, 0x7f, 0xac, 0x31, 0x66, 0x86, 0xc8, 0x0d,
0x3f, 0xb8, 0xe5, 0x98, 0x05, 0xdf, 0xc2, 0x92, 0xf8, 0x17, 0x50, 0x23, 0xbb, 0x13, 0x7e, 0xab, 0x68, 0x44, 0x71, 0x18, 0x85, 0x92, 0x2f, 0xad, 0x9a, 0xae, 0xa5, 0x8d, 0x2c, 0xcc, 0x52, 0x02,
0xd8, 0x6d, 0xd8, 0x38, 0x97, 0x57, 0x47, 0x73, 0xa3, 0x52, 0x05, 0x65, 0x36, 0xa6, 0xf4, 0x5c, 0xb9, 0x09, 0x2e, 0x9a, 0x82, 0xc1, 0x6a, 0x1d, 0x5e, 0xb5, 0xcc, 0x92, 0x6e, 0x66, 0x48, 0xf4,
0x5e, 0x75, 0xaf, 0xb4, 0x4b, 0xb9, 0xb3, 0x1c, 0xfe, 0x5c, 0xea, 0x34, 0xd5, 0xd6, 0xe2, 0x1f, 0x33, 0x68, 0xa2, 0x3c, 0xf6, 0xbe, 0x16, 0x64, 0x1f, 0x1a, 0x3e, 0x3f, 0x3f, 0xba, 0x50, 0x22,
0x43, 0xb5, 0x7b, 0xf5, 0x37, 0x57, 0xc5, 0xd9, 0x6b, 0xb9, 0xd9, 0x8f, 0xa1, 0x4e, 0xbf, 0xf5, 0x49, 0xc5, 0x54, 0xd6, 0xb9, 0xe1, 0xf3, 0xf3, 0xd3, 0x73, 0x69, 0x73, 0xc7, 0x4a, 0x16, 0x7f,
0x3c, 0xd6, 0x3a, 0x9c, 0xb0, 0x7d, 0x60, 0x64, 0xb6, 0x65, 0x62, 0x70, 0x4d, 0x7f, 0xb1, 0x15, 0xc4, 0x65, 0x92, 0x33, 0x46, 0xa2, 0x1f, 0x40, 0xed, 0xf4, 0xfc, 0x2f, 0xae, 0xaa, 0x67, 0xef,
0x23, 0xbc, 0x05, 0xdb, 0xcf, 0x66, 0x61, 0x5f, 0x45, 0x3d, 0xd5, 0x96, 0x89, 0x1c, 0xa7, 0x8e, 0x14, 0x66, 0xdf, 0x83, 0x16, 0x6e, 0xeb, 0x51, 0x28, 0xa5, 0x17, 0x91, 0x03, 0x20, 0xb8, 0xdd,
0x0e, 0x07, 0x8a, 0x66, 0x59, 0x47, 0x87, 0x03, 0xc5, 0xff, 0x08, 0x60, 0xe7, 0x38, 0x8e, 0xb4, 0x11, 0x8f, 0x95, 0x5e, 0x33, 0xbf, 0xd8, 0x86, 0x11, 0x3a, 0x80, 0xce, 0x47, 0x67, 0xde, 0x4c,
0x8a, 0xf4, 0x54, 0x3b, 0xee, 0xbe, 0x17, 0x13, 0xa7, 0x81, 0x5d, 0x5f, 0x03, 0x88, 0x0b, 0x2f, 0x04, 0x53, 0x31, 0xe2, 0x31, 0xf7, 0x13, 0x45, 0xc3, 0xb9, 0xc0, 0x59, 0x46, 0xd1, 0x70, 0x2e,
0x6c, 0xef, 0xa5, 0x5b, 0x75, 0x39, 0xdc, 0x4a, 0x43, 0x4e, 0xa0, 0x48, 0xe3, 0xf0, 0x30, 0xb7, 0xe8, 0xef, 0x0e, 0x74, 0x1f, 0x84, 0x81, 0x14, 0x81, 0x5c, 0x49, 0xcb, 0x3d, 0x80, 0xe6, 0x24,
0x27, 0x97, 0x48, 0xe6, 0x2f, 0x6c, 0x47, 0x44, 0x6e, 0xeb, 0x8f, 0x8b, 0x5b, 0x71, 0x79, 0xbd, 0xf1, 0x89, 0xcd, 0x96, 0xbd, 0x7c, 0xb6, 0x68, 0x9c, 0x65, 0x14, 0xf2, 0x36, 0xd4, 0x14, 0x9a,
0xe9, 0x26, 0xe6, 0x07, 0x45, 0x81, 0xcc, 0xa7, 0x50, 0xcb, 0x6a, 0x93, 0x35, 0x60, 0x3d, 0x5f, 0x6a, 0x63, 0xb8, 0x9b, 0xb8, 0x1c, 0x41, 0x66, 0x07, 0xc9, 0x1d, 0x68, 0x4d, 0x32, 0x9b, 0x6c,
0xe1, 0xa9, 0x89, 0xe1, 0x69, 0x4f, 0x2f, 0x3e, 0x53, 0x73, 0xda, 0xc2, 0xa6, 0x70, 0x16, 0x6b, 0x20, 0x49, 0x7e, 0x61, 0x33, 0xc2, 0xf2, 0x34, 0x72, 0x0f, 0x3a, 0xa2, 0x60, 0x8a, 0x8d, 0xeb,
0x42, 0xfd, 0x65, 0x6c, 0xc2, 0x68, 0xd0, 0x8e, 0x2f, 0x55, 0xe2, 0x52, 0xec, 0x43, 0x58, 0xd2, 0x15, 0x3b, 0xb1, 0x68, 0x27, 0x2b, 0x91, 0xe9, 0x0a, 0x9a, 0xcf, 0x92, 0x43, 0x4e, 0x7a, 0x50,
0x87, 0xbd, 0xde, 0x74, 0x4c, 0xbf, 0x55, 0x12, 0xd6, 0xe0, 0x11, 0x6c, 0x66, 0x6e, 0x3b, 0xca, 0xe7, 0x85, 0x52, 0x91, 0x88, 0xda, 0x3d, 0xd1, 0x6a, 0xf2, 0x89, 0xb8, 0x40, 0x13, 0xda, 0xcc,
0xb0, 0xfb, 0x00, 0x99, 0x8d, 0xce, 0x4b, 0x5e, 0x4c, 0xb3, 0x01, 0xe1, 0x71, 0xd8, 0xbd, 0x54, 0x4a, 0xa4, 0x0f, 0xad, 0xb3, 0x50, 0x79, 0xc1, 0x7c, 0x14, 0x3e, 0x17, 0xb1, 0x0d, 0x71, 0x1e,
0xf3, 0x2a, 0x71, 0x61, 0x5d, 0xe6, 0x67, 0x0c, 0xfe, 0x7b, 0xd9, 0x95, 0x11, 0xee, 0xf1, 0x18, 0xd2, 0xb5, 0x81, 0x4f, 0xa7, 0x2b, 0x1f, 0xb7, 0x55, 0x61, 0x46, 0xa0, 0x01, 0xb4, 0x53, 0xb5,
0xbb, 0xa8, 0x2b, 0xdf, 0x9a, 0x48, 0x4d, 0xd6, 0x82, 0x9d, 0x33, 0xa9, 0xad, 0xfc, 0x5d, 0x77, 0x63, 0xa1, 0xc8, 0x2d, 0x80, 0xb4, 0xd6, 0x68, 0xe5, 0x95, 0x9c, 0x4f, 0x53, 0x22, 0xcb, 0x71,
0xb2, 0xa2, 0x2b, 0xc2, 0xd8, 0x12, 0x33, 0xa8, 0x1b, 0x1b, 0x39, 0xea, 0x5e, 0xb9, 0xad, 0x2f, 0xc8, 0xcd, 0x24, 0xe7, 0x45, 0x6c, 0xdd, 0xba, 0xce, 0x4f, 0x19, 0xf4, 0xb7, 0x2a, 0xb8, 0x78,
0xe1, 0xec, 0x3e, 0xd4, 0x33, 0xec, 0xf4, 0xa9, 0x4b, 0x4e, 0xb1, 0x65, 0xf8, 0x14, 0xf6, 0x2e, 0x64, 0xb4, 0x8d, 0x58, 0x8e, 0xed, 0x41, 0x6f, 0xb2, 0x44, 0x24, 0x03, 0xe8, 0x2e, 0xb9, 0x34,
0x6c, 0x2d, 0x56, 0x09, 0xc7, 0xca, 0xb5, 0xbc, 0x3c, 0xc8, 0x1e, 0xe4, 0x22, 0x56, 0xa5, 0x65, 0xe9, 0x7f, 0x6c, 0xca, 0x9c, 0x49, 0xba, 0x32, 0xac, 0x6b, 0x6b, 0x0a, 0x9d, 0x86, 0x8a, 0x2f,
0x6f, 0x14, 0x23, 0xd0, 0x51, 0x26, 0x17, 0xb4, 0x47, 0xb0, 0x8d, 0xab, 0x78, 0x13, 0xd7, 0x5f, 0x4f, 0xcf, 0xad, 0xe9, 0x6b, 0x38, 0xb9, 0x05, 0xad, 0x14, 0x3b, 0x79, 0x68, 0x83, 0x53, 0x2e,
0x3d, 0xb1, 0x40, 0x65, 0x4f, 0xe0, 0x6d, 0x44, 0x6c, 0x0c, 0x16, 0xf8, 0xf1, 0x50, 0x46, 0x03, 0x2e, 0x79, 0x0a, 0x79, 0x0b, 0x76, 0xb3, 0x55, 0x3c, 0x5f, 0xd8, 0xda, 0x59, 0x04, 0xc9, 0xed,
0xd5, 0xa7, 0xe6, 0x59, 0x12, 0xd7, 0x51, 0xd8, 0x93, 0xa5, 0x5a, 0x6a, 0xd4, 0x72, 0x4d, 0xa8, 0x82, 0xc7, 0x6a, 0xb8, 0xec, 0xa5, 0xb2, 0x07, 0xc6, 0x42, 0x15, 0x9c, 0x76, 0x17, 0x3a, 0x7a,
0x30, 0x2a, 0x96, 0x4a, 0xef, 0x53, 0x68, 0x2e, 0x1c, 0x14, 0x06, 0xd3, 0x1f, 0x01, 0xfa, 0x91, 0x95, 0x67, 0xd9, 0xc4, 0xfa, 0x8b, 0x27, 0x96, 0xa8, 0xe4, 0x3e, 0xbc, 0xa1, 0x11, 0xe3, 0x83,
0xd7, 0xf2, 0xd2, 0x7c, 0x0b, 0xa5, 0xa7, 0x23, 0xa3, 0xe9, 0x00, 0xad, 0x93, 0xb8, 0x8b, 0x30, 0x0c, 0x7f, 0xb0, 0xe0, 0xc1, 0x5c, 0xcc, 0xb0, 0x0a, 0x57, 0xd8, 0x36, 0x0a, 0xb9, 0x0f, 0xdd,
0xd5, 0xc5, 0x64, 0x42, 0x8c, 0x4d, 0x57, 0x17, 0xd6, 0xe4, 0xbf, 0x96, 0xe0, 0x66, 0xa1, 0x73, 0x69, 0xf1, 0x2c, 0x61, 0x75, 0xce, 0x8a, 0x50, 0xe9, 0xa4, 0xb1, 0x32, 0x9d, 0x7c, 0x0c, 0xfd,
0x9e, 0x28, 0xd9, 0x57, 0x54, 0x4b, 0xbd, 0xbc, 0xce, 0x9c, 0x89, 0xb5, 0x34, 0xf4, 0xe5, 0xe5, 0x4c, 0x41, 0x89, 0x9d, 0x6c, 0x04, 0x70, 0x23, 0x2f, 0xe5, 0x25, 0xf1, 0x66, 0x42, 0xae, 0x96,
0x2c, 0xac, 0x94, 0x84, 0x0e, 0x3f, 0x2b, 0x25, 0x6b, 0xe0, 0xf1, 0x66, 0x50, 0x04, 0xb6, 0x7c, 0x4a, 0x1e, 0xeb, 0x9b, 0xb8, 0x85, 0xc9, 0x5d, 0x86, 0xf1, 0x5c, 0x44, 0x11, 0x32, 0xda, 0xf6,
0xe8, 0x1b, 0x57, 0x88, 0xa6, 0x63, 0xec, 0xb5, 0x56, 0x1a, 0xce, 0x42, 0xad, 0x8d, 0x3c, 0xad, 0x5c, 0x18, 0x91, 0xfe, 0x52, 0x81, 0x2b, 0xa5, 0xca, 0x79, 0x2c, 0xf8, 0x4c, 0xc4, 0x5b, 0xf2,
0x55, 0x57, 0x6b, 0xcd, 0xa3, 0x60, 0xef, 0x35, 0x56, 0xa8, 0x56, 0x0a, 0x25, 0x91, 0xd9, 0x78, 0x2c, 0xbb, 0x45, 0x77, 0x36, 0xdf, 0xa2, 0x26, 0x95, 0xec, 0x2d, 0xaa, 0xef, 0x49, 0x9d, 0x04,
0x98, 0x23, 0xd5, 0x1e, 0x7b, 0xb4, 0x79, 0x7b, 0x3e, 0x16, 0x50, 0xe4, 0xcd, 0xb2, 0x54, 0x13, 0xe6, 0xf8, 0xe0, 0xb7, 0x5e, 0x21, 0x58, 0xf9, 0xba, 0xd6, 0x9a, 0xd4, 0xb0, 0x52, 0x39, 0xd7,
0xaf, 0x66, 0x79, 0x79, 0x14, 0x75, 0xdd, 0x4b, 0x33, 0x41, 0x34, 0x20, 0x5a, 0x1e, 0xc4, 0xb8, 0x6a, 0x2f, 0xcf, 0xb5, 0x7d, 0x68, 0x28, 0x93, 0xa8, 0x26, 0x15, 0x2a, 0x2c, 0x95, 0x75, 0x57,
0x49, 0x17, 0x6b, 0x9b, 0x8d, 0xd4, 0xc4, 0x7c, 0x8d, 0x0a, 0xf9, 0xb2, 0xd9, 0x28, 0xc2, 0x8c, 0xa0, 0xa9, 0xe6, 0x82, 0x44, 0xe3, 0xcd, 0x45, 0x5b, 0x42, 0x0b, 0xdd, 0x83, 0x71, 0x63, 0xd3,
0xc3, 0xe6, 0xc4, 0x55, 0x3e, 0x36, 0xb0, 0xc6, 0x16, 0xd1, 0x72, 0x18, 0xff, 0x29, 0x80, 0x9d, 0xf0, 0x8a, 0xa8, 0xce, 0xeb, 0x34, 0x9c, 0x48, 0x03, 0xa4, 0x15, 0xc1, 0xbc, 0xaf, 0x5b, 0x05,
0x42, 0xe6, 0xd8, 0x43, 0xcc, 0x0c, 0x66, 0xcf, 0x75, 0xf5, 0xbd, 0xd5, 0x67, 0xa3, 0xcd, 0xb0, 0x5f, 0x6f, 0x8a, 0x57, 0x7b, 0x73, 0xbc, 0x28, 0xb4, 0x93, 0x93, 0xaf, 0x5b, 0x9c, 0xde, 0x2e,
0x70, 0x5c, 0xd6, 0x84, 0x72, 0x5f, 0x1a, 0x59, 0x38, 0xa0, 0xed, 0x29, 0x4a, 0x23, 0xec, 0x23, 0xd2, 0x0a, 0x18, 0xfd, 0xd1, 0x81, 0x6e, 0x29, 0x72, 0xe4, 0x8e, 0x8e, 0x8c, 0x8e, 0x9e, 0xad,
0x80, 0x45, 0xcc, 0x5c, 0x0b, 0xf8, 0xff, 0xd2, 0xda, 0x76, 0x58, 0x78, 0x54, 0xfe, 0x67, 0xb0, 0xea, 0xd7, 0x36, 0xdf, 0x8d, 0x26, 0xc2, 0xcc, 0x72, 0x49, 0x1f, 0xaa, 0x33, 0xae, 0x78, 0xe9,
0x38, 0xd9, 0x3d, 0xdd, 0x04, 0xab, 0x75, 0x63, 0x0f, 0x5e, 0xa7, 0x9b, 0x3d, 0xa8, 0x99, 0xec, 0x82, 0x36, 0xb7, 0x28, 0x8e, 0x90, 0xf7, 0x01, 0x32, 0x9f, 0xd9, 0x12, 0xf0, 0xda, 0xda, 0xda,
0xd2, 0x64, 0x15, 0xb5, 0x00, 0x30, 0xef, 0xed, 0x17, 0x67, 0xfe, 0x5d, 0x2b, 0xb3, 0xd9, 0x3e, 0x66, 0x98, 0xe5, 0xa8, 0xf4, 0x0f, 0x07, 0x1a, 0xc9, 0x15, 0x9e, 0xcb, 0x1b, 0x67, 0x73, 0xde,
0x40, 0xfb, 0xc5, 0x59, 0x2a, 0xa2, 0xca, 0x4a, 0x11, 0x79, 0x0c, 0xf4, 0xa4, 0xb3, 0x2b, 0x54, 0xec, 0xbc, 0xb0, 0xfb, 0xaa, 0x94, 0xbb, 0xaf, 0x7d, 0x68, 0x8c, 0x9e, 0x3e, 0x66, 0xb9, 0xa6,
0xd5, 0x5e, 0xa1, 0x32, 0x00, 0x47, 0xe9, 0x26, 0x31, 0xc4, 0x7c, 0xad, 0xdb, 0xd1, 0x0c, 0xe0, 0x2d, 0x95, 0xc9, 0x01, 0xc0, 0xe8, 0xe9, 0xe3, 0x24, 0x89, 0xdc, 0x8d, 0x49, 0x94, 0x63, 0x14,
0xbf, 0x04, 0xb0, 0xf3, 0xb9, 0xba, 0x24, 0xc7, 0x1d, 0xa3, 0x26, 0xe7, 0x7a, 0xf0, 0x86, 0xfb, 0x7b, 0xb1, 0xda, 0x86, 0x5e, 0x0c, 0xaf, 0x2b, 0xec, 0x74, 0xeb, 0x66, 0x34, 0x05, 0xe8, 0xcf,
0x64, 0x50, 0xd6, 0x46, 0xd9, 0x2d, 0x56, 0x04, 0x7d, 0xb3, 0x87, 0x70, 0x53, 0xab, 0x5e, 0x1c, 0x0e, 0x74, 0x3f, 0x15, 0xcf, 0x51, 0xf1, 0x58, 0x89, 0xe8, 0x89, 0x9c, 0xbf, 0xa2, 0x9d, 0x04,
0xf5, 0x75, 0x27, 0x8c, 0x7a, 0xaa, 0x63, 0x64, 0x62, 0xba, 0x69, 0x11, 0x55, 0xc4, 0xea, 0xc1, 0xaa, 0x52, 0x09, 0x63, 0xa2, 0xcb, 0xf0, 0x9b, 0xdc, 0x81, 0x2b, 0x52, 0x4c, 0xc3, 0x60, 0x26,
0x54, 0x5f, 0x2e, 0x0d, 0xe4, 0xa9, 0x42, 0xfc, 0x22, 0xcc, 0x2f, 0x61, 0x8b, 0x9a, 0x1b, 0x45, 0xc7, 0x5e, 0x30, 0x15, 0x63, 0xc5, 0x63, 0x75, 0x9a, 0x1c, 0x22, 0x97, 0x6d, 0x1e, 0x4c, 0xf2,
0xe0, 0xcd, 0x7f, 0x39, 0x17, 0x92, 0x52, 0x21, 0x24, 0x98, 0x9a, 0x50, 0x7b, 0x52, 0xd9, 0x10, 0xcb, 0x86, 0x01, 0x35, 0xb9, 0xc8, 0x2f, 0xc3, 0xf4, 0x39, 0xec, 0x62, 0x71, 0x43, 0x0f, 0xbc,
0x99, 0xcd, 0x7f, 0x08, 0x60, 0x3b, 0xd5, 0x43, 0xfb, 0xc5, 0xd9, 0x75, 0xae, 0xef, 0xc0, 0xee, 0xfa, 0x96, 0x0b, 0x2e, 0xa9, 0x94, 0x5c, 0xa2, 0x43, 0xe3, 0xc9, 0x5c, 0xaa, 0x34, 0x58, 0x2a,
0x64, 0xc1, 0x14, 0xde, 0x5f, 0x2c, 0xe1, 0xec, 0x11, 0xd4, 0x3d, 0xcc, 0xdd, 0x3c, 0xde, 0x5a, 0xd3, 0x6f, 0x1d, 0xe8, 0x24, 0xf9, 0x30, 0x7a, 0xfa, 0x78, 0x9b, 0xea, 0xeb, 0xb0, 0x17, 0x65,
0x16, 0xbf, 0x7b, 0x45, 0x08, 0x9f, 0xcd, 0xfb, 0x00, 0x27, 0x52, 0xe3, 0x7d, 0xf6, 0x1f, 0x25, 0x4c, 0x96, 0xdb, 0xc5, 0x1a, 0x4e, 0xee, 0x42, 0x2b, 0x87, 0xd9, 0xce, 0xe3, 0xf5, 0xf5, 0xe4,
0x0f, 0x9d, 0xa4, 0xc9, 0xc3, 0x6f, 0x64, 0x86, 0xf4, 0x74, 0x70, 0x6f, 0x00, 0x32, 0xf8, 0x77, 0xb7, 0xcf, 0x11, 0x96, 0x67, 0xd3, 0x19, 0xc0, 0x31, 0x97, 0xba, 0x87, 0xfd, 0x5b, 0xc1, 0xc3,
0xb0, 0x83, 0x2e, 0x3a, 0xca, 0x9c, 0xcb, 0xaf, 0x0e, 0x1e, 0xfc, 0x3b, 0xae, 0x5a, 0xb0, 0x7e, 0x47, 0x80, 0x0d, 0x1e, 0x3e, 0x02, 0x2e, 0x83, 0xeb, 0xe1, 0x1b, 0xc4, 0x3e, 0x26, 0x50, 0xa0,
0x71, 0xed, 0xb9, 0x9c, 0x0e, 0xf3, 0x9f, 0x03, 0xd8, 0x76, 0xfe, 0xf1, 0xcd, 0xf4, 0x1f, 0xbb, 0xdf, 0x40, 0x57, 0xab, 0x18, 0x0b, 0xf5, 0x84, 0x7f, 0x71, 0x78, 0xfb, 0x9f, 0x51, 0x95, 0x6b,
0x67, 0x1f, 0x42, 0x65, 0x16, 0xe3, 0x95, 0xb6, 0xf2, 0xba, 0xd4, 0x58, 0x1e, 0xff, 0x2d, 0x80, 0xfa, 0xab, 0x5b, 0x9b, 0x7e, 0xfa, 0x93, 0x03, 0x1d, 0xab, 0xff, 0xc8, 0x53, 0xf2, 0x5f, 0x56,
0xda, 0x89, 0x92, 0x89, 0xb9, 0x50, 0x92, 0xb4, 0x30, 0x7b, 0xc5, 0x13, 0x6e, 0xb6, 0xe2, 0x09, 0x4f, 0xde, 0x03, 0xf7, 0x2c, 0xd4, 0x2d, 0xad, 0xfb, 0xb2, 0xd0, 0x18, 0x1e, 0xfd, 0xd5, 0x81,
0x37, 0x5b, 0xf9, 0x84, 0x9b, 0x2d, 0x3d, 0xe1, 0x86, 0xb9, 0x27, 0x5c, 0x71, 0xfb, 0x65, 0x7f, 0xe6, 0xb1, 0xe0, 0xb1, 0x9a, 0x08, 0xae, 0xfe, 0x03, 0x6f, 0xc1, 0x7d, 0x68, 0x48, 0xf1, 0xd5,
0xfb, 0xb7, 0x61, 0x43, 0xab, 0x6f, 0xa6, 0x78, 0xf1, 0x74, 0x45, 0x95, 0xd9, 0xd7, 0xf7, 0x0f, 0x4a, 0x37, 0x9e, 0xf6, 0x50, 0xa5, 0xf2, 0xf6, 0xfa, 0x41, 0xdf, 0x85, 0xe6, 0x89, 0x3c, 0x16,
0xfe, 0x01, 0xd4, 0x4e, 0xf5, 0x89, 0x92, 0x23, 0x33, 0x9c, 0x23, 0x35, 0x4c, 0x0d, 0xda, 0xc1, 0x7c, 0xa9, 0x16, 0x17, 0x9a, 0xea, 0x25, 0x02, 0x5a, 0xd0, 0x60, 0x19, 0xa0, 0xdf, 0xbe, 0x75,
0x86, 0x58, 0x00, 0x17, 0x55, 0x7a, 0x18, 0x3f, 0xf8, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x0d, 0xfb, 0xae, 0x7a, 0x25, 0x93, 0x87, 0x39, 0x93, 0xd1, 0x8b, 0xb6, 0x94, 0x6f, 0x71, 0x73, 0x69,
0x4d, 0x91, 0x45, 0x0f, 0x00, 0x00, 0xc2, 0xff, 0xe5, 0x65, 0x3c, 0xa9, 0xe1, 0x4f, 0x88, 0xdb, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff,
0xfd, 0xb0, 0x20, 0xb2, 0xb1, 0x10, 0x00, 0x00,
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment