diff --git a/CHANGELOG.md b/CHANGELOG.md index 599e1918f95a..c12483633d83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,25 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## [v0.37.5] - TBD + +### Features + +* (types) [\#5360](https://github.com/cosmos/cosmos-sdk/pull/5360) Implement `SortableDecBytes` which + allows the `Dec` type be sortable. + +### Improvements + +* (tendermint) Bump Tendermint version to [v0.32.8](https://github.com/tendermint/tendermint/releases/tag/v0.32.8) + +### Bug Fixes + +* (iavl) [\#5276](https://github.com/cosmos/cosmos-sdk/issues/5276) Fix potential race condition in `iavlIterator#Close`. +* (baseapp) [\#5350](https://github.com/cosmos/cosmos-sdk/issues/5350) Allow a node to restart successfully + after a `halt-height` or `halt-time` has been triggered. +* (types) [\#5395](https://github.com/cosmos/cosmos-sdk/issues/5395) Fix `Uint#LTE`. +* (types) [\#5408](https://github.com/cosmos/cosmos-sdk/issues/5408) `NewDecCoins` constructor now sorts the coins. + ## [v0.37.4] - 2019-11-04 ### Improvements @@ -2578,7 +2597,8 @@ BUG FIXES: -[Unreleased]: https://github.com/cosmos/cosmos-sdk/compare/v0.37.4...HEAD +[Unreleased]: https://github.com/cosmos/cosmos-sdk/compare/v0.37.5...HEAD +[v0.37.5]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.5 [v0.37.4]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.4 [v0.37.3]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.3 [v0.37.1]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.1 diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 74db6e0813c5..ad50b100942e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -995,24 +995,6 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc func (app *BaseApp) Commit() (res abci.ResponseCommit) { header := app.deliverState.ctx.BlockHeader() - var halt bool - - switch { - case app.haltHeight > 0 && uint64(header.Height) >= app.haltHeight: - halt = true - - case app.haltTime > 0 && header.Time.Unix() >= int64(app.haltTime): - halt = true - } - - if halt { - app.halt() - - // Note: State is not actually committed when halted. Logs from Tendermint - // can be ignored. - return abci.ResponseCommit{} - } - // Write the DeliverTx state which is cache-wrapped and commit the MultiStore. // The write to the DeliverTx state writes all state transitions to the root // MultiStore (app.cms) so when Commit() is called is persists those values. @@ -1029,6 +1011,24 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // empty/reset the deliver state app.deliverState = nil + var halt bool + + switch { + case app.haltHeight > 0 && uint64(header.Height) >= app.haltHeight: + halt = true + + case app.haltTime > 0 && header.Time.Unix() >= int64(app.haltTime): + halt = true + } + + if halt { + // Halt the binary and allow Tendermint to receive the ResponseCommit + // response with the commit ID hash. This will allow the node to successfully + // restart and process blocks assuming the halt configuration has been + // reset or moved to a more distant value. + app.halt() + } + return abci.ResponseCommit{ Data: commitID.Hash, } diff --git a/go.mod b/go.mod index 6b33dad6ca87..778c13e0cc69 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8 github.com/cosmos/ledger-cosmos-go v0.10.3 - github.com/gogo/protobuf v1.3.0 + github.com/gogo/protobuf v1.3.1 github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 github.com/gorilla/mux v1.7.0 github.com/mattn/go-isatty v0.0.6 @@ -18,15 +18,14 @@ require ( github.com/spf13/afero v1.2.1 // indirect github.com/spf13/cobra v0.0.5 github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.3 - github.com/spf13/viper v1.4.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.6.1 github.com/stretchr/testify v1.4.0 - github.com/stumble/gorocksdb v0.0.3 // indirect github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 github.com/tendermint/go-amino v0.15.0 github.com/tendermint/iavl v0.12.4 - github.com/tendermint/tendermint v0.32.7 + github.com/tendermint/tendermint v0.32.8 github.com/tendermint/tm-db v0.2.0 - gopkg.in/yaml.v2 v2.2.2 + gopkg.in/yaml.v2 v2.2.7 ) diff --git a/go.sum b/go.sum index 37453c53b313..b16aba978cde 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,7 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -47,6 +48,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= @@ -73,8 +76,8 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -93,6 +96,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -113,6 +118,8 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -156,8 +163,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= @@ -176,6 +184,10 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -190,12 +202,14 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= +github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -204,6 +218,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stumble/gorocksdb v0.0.3 h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8kA= github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= @@ -216,8 +232,8 @@ github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8= github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= -github.com/tendermint/tendermint v0.32.7 h1:Szu5Fm1L3pvn3t4uQxPAcP+7ndZEQKgLie/yokM56rU= -github.com/tendermint/tendermint v0.32.7/go.mod h1:D2+A3pNjY+Po72X0mTfaXorFhiVI8dh/Zg640FGyGtE= +github.com/tendermint/tendermint v0.32.8 h1:eOaLJGRi5x/Rb23fiVsxq9c5fZ/6O5QplExlGjNPDVI= +github.com/tendermint/tendermint v0.32.8/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= @@ -241,12 +257,16 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= @@ -264,40 +284,50 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 h1:67iHsV9djwGdZpdZNbLuQj6FOzCaZe3w+vhLjn5AcFA= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= diff --git a/server/config/config.go b/server/config/config.go index 9b556b2124b5..d783bdb36376 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -21,16 +21,14 @@ type BaseConfig struct { // HaltHeight contains a non-zero block height at which a node will gracefully // halt and shutdown that can be used to assist upgrades and testing. // - // Note: State will not be committed on the corresponding height and any logs - // indicating such can be safely ignored. + // Note: Commitment of state will be attempted on the corresponding block. HaltHeight uint64 `mapstructure:"halt-height"` // HaltTime contains a non-zero minimum block time (in Unix seconds) at which // a node will gracefully halt and shutdown that can be used to assist // upgrades and testing. // - // Note: State will not be committed on the corresponding height and any logs - // indicating such can be safely ignored. + // Note: Commitment of state will be attempted on the corresponding block. HaltTime uint64 `mapstructure:"halt-time"` } diff --git a/server/config/toml.go b/server/config/toml.go index fc9e9bdd814f..f4b58012d72b 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -21,16 +21,14 @@ minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}" # HaltHeight contains a non-zero block height at which a node will gracefully # halt and shutdown that can be used to assist upgrades and testing. # -# Note: State will not be committed on the corresponding height and any logs -# indicating such can be safely ignored. +# Note: Commitment of state will be attempted on the corresponding block. halt-height = {{ .BaseConfig.HaltHeight }} # HaltTime contains a non-zero minimum block time (in Unix seconds) at which # a node will gracefully halt and shutdown that can be used to assist upgrades # and testing. # -# Note: State will not be committed on the corresponding height and any logs -# indicating such can be safely ignored. +# Note: Commitment of state will be attempted on the corresponding block. halt-time = {{ .BaseConfig.HaltTime }} ` diff --git a/store/iavl/store.go b/store/iavl/store.go index 01eed572990b..837314c29beb 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -420,9 +420,13 @@ func (iter *iavlIterator) Value() []byte { return val } -// Implements types.Iterator. +// Close closes the IAVL iterator by closing the quit channel and waiting for +// the iterCh to finish/close. func (iter *iavlIterator) Close() { close(iter.quitCh) + // wait iterCh to close + for range iter.iterCh { + } } //---------------------------------------- diff --git a/types/dec_coin.go b/types/dec_coin.go index 1ecfd82608a7..40bc3da391e6 100644 --- a/types/dec_coin.go +++ b/types/dec_coin.go @@ -11,17 +11,16 @@ import ( // ---------------------------------------------------------------------------- // Decimal Coin -// Coins which can have additional decimal points +// DecCoin defines a coin which can have additional decimal points type DecCoin struct { Denom string `json:"denom"` Amount Dec `json:"amount"` } +// NewDecCoin creates a new DecCoin instance from an Int. func NewDecCoin(denom string, amount Int) DecCoin { - mustValidateDenom(denom) - - if amount.LT(ZeroInt()) { - panic(fmt.Sprintf("negative coin amount: %v\n", amount)) + if err := validate(denom, amount); err != nil { + panic(err) } return DecCoin{ @@ -30,6 +29,7 @@ func NewDecCoin(denom string, amount Int) DecCoin { } } +// NewDecCoinFromDec creates a new DecCoin instance from a Dec. func NewDecCoinFromDec(denom string, amount Dec) DecCoin { mustValidateDenom(denom) @@ -43,12 +43,10 @@ func NewDecCoinFromDec(denom string, amount Dec) DecCoin { } } +// NewDecCoinFromCoin creates a new DecCoin from a Coin. func NewDecCoinFromCoin(coin Coin) DecCoin { - if coin.Amount.LT(ZeroInt()) { - panic(fmt.Sprintf("negative decimal coin amount: %v\n", coin.Amount)) - } - if strings.ToLower(coin.Denom) != coin.Denom { - panic(fmt.Sprintf("denom cannot contain upper case characters: %s\n", coin.Denom)) + if err := validate(coin.Denom, coin.Amount); err != nil { + panic(err) } return DecCoin{ @@ -97,7 +95,7 @@ func (coin DecCoin) IsEqual(other DecCoin) bool { return coin.Amount.Equal(other.Amount) } -// Adds amounts of two coins with same denom +// Add adds amounts of two decimal coins with same denom. func (coin DecCoin) Add(coinB DecCoin) DecCoin { if coin.Denom != coinB.Denom { panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom)) @@ -105,12 +103,16 @@ func (coin DecCoin) Add(coinB DecCoin) DecCoin { return DecCoin{coin.Denom, coin.Amount.Add(coinB.Amount)} } -// Subtracts amounts of two coins with same denom +// Sub subtracts amounts of two decimal coins with same denom. func (coin DecCoin) Sub(coinB DecCoin) DecCoin { if coin.Denom != coinB.Denom { panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom)) } - return DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)} + res := DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)} + if res.IsNegative() { + panic("negative decimal coin amount") + } + return res } // TruncateDecimal returns a Coin with a truncated decimal and a DecCoin for the @@ -118,7 +120,7 @@ func (coin DecCoin) Sub(coinB DecCoin) DecCoin { func (coin DecCoin) TruncateDecimal() (Coin, DecCoin) { truncated := coin.Amount.TruncateInt() change := coin.Amount.Sub(truncated.ToDec()) - return NewCoin(coin.Denom, truncated), DecCoin{coin.Denom, change} + return NewCoin(coin.Denom, truncated), NewDecCoinFromDec(coin.Denom, change) } // IsPositive returns true if coin amount is positive. @@ -141,18 +143,31 @@ func (coin DecCoin) String() string { return fmt.Sprintf("%v%v", coin.Amount, coin.Denom) } +// IsValid returns true if the DecCoin has a non-negative amount and the denom +// is valid. +func (coin DecCoin) IsValid() bool { + if err := validateDenom(coin.Denom); err != nil { + return false + } + return !coin.IsNegative() +} + // ---------------------------------------------------------------------------- // Decimal Coins -// coins with decimal +// DecCoins defines a slice of coins with decimal values type DecCoins []DecCoin +// NewDecCoins constructs a new coin set with decimal values +// from regular Coins. func NewDecCoins(coins Coins) DecCoins { - dcs := make(DecCoins, len(coins)) - for i, coin := range coins { - dcs[i] = NewDecCoinFromCoin(coin) + decCoins := make(DecCoins, len(coins)) + newCoins := NewCoins(coins...) + for i, coin := range newCoins { + decCoins[i] = NewDecCoinFromCoin(coin) } - return dcs + + return decCoins } // String implements the Stringer interface for DecCoins. It returns a @@ -177,7 +192,7 @@ func (coins DecCoins) TruncateDecimal() (truncatedCoins Coins, changeCoins DecCo for _, coin := range coins { truncated, change := coin.TruncateDecimal() if !truncated.IsZero() { - truncatedCoins = truncatedCoins.Add(Coins{truncated}) + truncatedCoins = truncatedCoins.Add(NewCoins(truncated)) } if !change.IsZero() { changeCoins = changeCoins.Add(DecCoins{change}) @@ -404,7 +419,7 @@ func (coins DecCoins) Empty() bool { return len(coins) == 0 } -// returns the amount of a denom from deccoins +// AmountOf returns the amount of a denom from deccoins func (coins DecCoins) AmountOf(denom string) Dec { mustValidateDenom(denom) @@ -451,7 +466,7 @@ func (coins DecCoins) IsEqual(coinsB DecCoins) bool { return true } -// return whether all coins are zero +// IsZero returns whether all coins are zero func (coins DecCoins) IsZero() bool { for _, coin := range coins { if !coin.Amount.IsZero() { diff --git a/types/dec_coin_test.go b/types/dec_coin_test.go index 7e904fe5dcf0..6a092c0b3a8d 100644 --- a/types/dec_coin_test.go +++ b/types/dec_coin_test.go @@ -96,6 +96,111 @@ func TestAddDecCoins(t *testing.T) { } } +func TestIsValid(t *testing.T) { + tests := []struct { + coin DecCoin + expectPass bool + msg string + }{ + { + NewDecCoin("mytoken", NewInt(10)), + true, + "valid coins should have passed", + }, + { + DecCoin{Denom: "BTC", Amount: NewDec(10)}, + false, + "invalid denoms", + }, + { + DecCoin{Denom: "BTC", Amount: NewDec(-10)}, + false, + "negative amount", + }, + } + + for _, tc := range tests { + tc := tc + if tc.expectPass { + require.True(t, tc.coin.IsValid(), tc.msg) + } else { + require.False(t, tc.coin.IsValid(), tc.msg) + } + } +} + +func TestSubDecCoin(t *testing.T) { + tests := []struct { + coin DecCoin + expectPass bool + msg string + }{ + { + NewDecCoin("mytoken", NewInt(20)), + true, + "valid coins should have passed", + }, + { + NewDecCoin("othertoken", NewInt(20)), + false, + "denom mismatch", + }, + { + NewDecCoin("mytoken", NewInt(9)), + false, + "negative amount", + }, + } + + decCoin := NewDecCoin("mytoken", NewInt(10)) + + for _, tc := range tests { + tc := tc + if tc.expectPass { + equal := tc.coin.Sub(decCoin) + require.Equal(t, equal, decCoin, tc.msg) + } else { + require.Panics(t, func() { tc.coin.Sub(decCoin) }, tc.msg) + } + } +} + +func TestSubDecCoins(t *testing.T) { + tests := []struct { + coins DecCoins + expectPass bool + msg string + }{ + { + NewDecCoins(Coins{NewCoin("mytoken", NewInt(10)), NewCoin("btc", NewInt(20)), NewCoin("eth", NewInt(30))}), + true, + "sorted coins should have passed", + }, + { + DecCoins{NewDecCoin("mytoken", NewInt(10)), NewDecCoin("btc", NewInt(20)), NewDecCoin("eth", NewInt(30))}, + false, + "unorted coins should panic", + }, + { + DecCoins{DecCoin{Denom: "BTC", Amount: NewDec(10)}, NewDecCoin("eth", NewInt(15)), NewDecCoin("mytoken", NewInt(5))}, + false, + "invalid denoms", + }, + } + + decCoins := NewDecCoins(Coins{NewCoin("btc", NewInt(10)), NewCoin("eth", NewInt(15)), NewCoin("mytoken", NewInt(5))}) + + for _, tc := range tests { + tc := tc + if tc.expectPass { + equal := tc.coins.Sub(decCoins) + require.Equal(t, equal, decCoins, tc.msg) + } else { + require.Panics(t, func() { tc.coins.Sub(decCoins) }, tc.msg) + } + } +} + func TestSortDecCoins(t *testing.T) { good := DecCoins{ NewInt64DecCoin("gas", 1), diff --git a/types/decimal.go b/types/decimal.go index 1a16cebc83fa..c7c5f197d83e 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -527,6 +527,42 @@ func (d Dec) Ceil() Dec { //___________________________________________________________________________________ +// MaxSortableDec is the largest Dec that can be passed into SortableDecBytes() +// Its negative form is the least Dec that can be passed in. +var MaxSortableDec = OneDec().Quo(SmallestDec()) + +// ValidSortableDec ensures that a Dec is within the sortable bounds, +// a Dec can't have a precision of less than 10^-18. +// Max sortable decimal was set to the reciprocal of SmallestDec. +func ValidSortableDec(dec Dec) bool { + return dec.Abs().LTE(MaxSortableDec) +} + +// SortableDecBytes returns a byte slice representation of a Dec that can be sorted. +// Left and right pads with 0s so there are 18 digits to left and right of the decimal point. +// For this reason, there is a maximum and minimum value for this, enforced by ValidSortableDec. +func SortableDecBytes(dec Dec) []byte { + if !ValidSortableDec(dec) { + panic("dec must be within bounds") + } + // Instead of adding an extra byte to all sortable decs in order to handle max sortable, we just + // makes its bytes be "max" which comes after all numbers in ASCIIbetical order + if dec.Equal(MaxSortableDec) { + return []byte("max") + } + // For the same reason, we make the bytes of minimum sortable dec be --, which comes before all numbers. + if dec.Equal(MaxSortableDec.Neg()) { + return []byte("--") + } + // We move the negative sign to the front of all the left padded 0s, to make negative numbers come before positive numbers + if dec.IsNegative() { + return append([]byte("-"), []byte(fmt.Sprintf(fmt.Sprintf("%%0%ds", Precision*2+1), dec.Abs().String()))...) + } + return []byte(fmt.Sprintf(fmt.Sprintf("%%0%ds", Precision*2+1), dec.String())) +} + +//___________________________________________________________________________________ + // reuse nil values var ( nilAmino string diff --git a/types/decimal_test.go b/types/decimal_test.go index 55aa31db9b58..301ddd0c4293 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -422,3 +422,28 @@ func TestDecCeil(t *testing.T) { require.Equal(t, tc.expected, res, "unexpected result for test case %d, input: %v", i, tc.input) } } + +func TestDecSortableBytes(t *testing.T) { + tests := []struct { + d Dec + want []byte + }{ + {NewDec(0), []byte("000000000000000000.000000000000000000")}, + {NewDec(1), []byte("000000000000000001.000000000000000000")}, + {NewDec(10), []byte("000000000000000010.000000000000000000")}, + {NewDec(12340), []byte("000000000000012340.000000000000000000")}, + {NewDecWithPrec(12340, 4), []byte("000000000000000001.234000000000000000")}, + {NewDecWithPrec(12340, 5), []byte("000000000000000000.123400000000000000")}, + {NewDecWithPrec(12340, 8), []byte("000000000000000000.000123400000000000")}, + {NewDecWithPrec(1009009009009009009, 17), []byte("000000000000000010.090090090090090090")}, + {NewDecWithPrec(-1009009009009009009, 17), []byte("-000000000000000010.090090090090090090")}, + {NewDec(1000000000000000000), []byte("max")}, + {NewDec(-1000000000000000000), []byte("--")}, + } + for tcIndex, tc := range tests { + assert.Equal(t, tc.want, SortableDecBytes(tc.d), "bad String(), index: %v", tcIndex) + } + + assert.Panics(t, func() { SortableDecBytes(NewDec(1000000000000000001)) }) + assert.Panics(t, func() { SortableDecBytes(NewDec(-1000000000000000001)) }) +} diff --git a/types/uint.go b/types/uint.go index 4bb71fff0436..da43f5fb9094 100644 --- a/types/uint.go +++ b/types/uint.go @@ -13,6 +13,11 @@ type Uint struct { i *big.Int } +// BigInt converts Uint to big.Int +func (u Uint) BigInt() *big.Int { + return new(big.Int).Set(u.i) +} + // NewUintFromBigUint constructs Uint from big.Uint func NewUintFromBigInt(i *big.Int) Uint { u, err := checkNewUint(i) @@ -69,7 +74,7 @@ func (u Uint) GTE(u2 Uint) bool { return u.GT(u2) || u.Equal(u2) } func (u Uint) LT(u2 Uint) bool { return lt(u.i, u2.i) } // LTE returns true if first Uint is lesser than or equal to the second -func (u Uint) LTE(u2 Uint) bool { return !u.GTE(u2) } +func (u Uint) LTE(u2 Uint) bool { return !u.GT(u2) } // Add adds Uint from another func (u Uint) Add(u2 Uint) Uint { return NewUintFromBigInt(new(big.Int).Add(u.i, u2.i)) } diff --git a/types/uint_test.go b/types/uint_test.go index a3115512bb95..0da5e084ec00 100644 --- a/types/uint_test.go +++ b/types/uint_test.go @@ -84,6 +84,7 @@ func TestIdentUint(t *testing.T) { cases := []uint64{ i.Uint64(), + i.BigInt().Uint64(), i.i.Uint64(), ifromstr.Uint64(), NewUintFromBigInt(new(big.Int).SetUint64(n)).Uint64(), @@ -140,7 +141,7 @@ func TestArithUint(t *testing.T) { } func TestCompUint(t *testing.T) { - for d := 0; d < 1000; d++ { + for d := 0; d < 10000; d++ { n1 := rand.Uint64() i1 := NewUint(n1) n2 := rand.Uint64() @@ -155,6 +156,8 @@ func TestCompUint(t *testing.T) { {i1.LT(i2), n1 < n2}, {i1.GTE(i2), !i1.LT(i2)}, {!i1.GTE(i2), i1.LT(i2)}, + {i1.LTE(i2), n1 <= n2}, + {i2.LTE(i1), n2 <= n1}, } for tcnum, tc := range cases {