Merge pull request #123 from CosmWasm/0.9

Tracking PR for 0.9
This commit is contained in:
Ethan Frey
2020-06-09 14:16:42 +02:00
committed by GitHub
28 changed files with 833 additions and 89 deletions

View File

@@ -37,6 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
## [Unreleased]
### Features
* (wasmd) [\#122](https://github.com/CosmWasm/wasmd/pull/122]) Migrate contract backend functionality with go-cosmwasm stub impl
* (wasmd)[\#2](https://github.com/cosmwasm/wasmd/pull/22) Improve wasm contract queries (all, raw, smart)
* (wasmd) [\#119](https://github.com/cosmwasm/wasmd/pull/119) Add support for the `--inter-block-cache` CLI
flag and configuration.
@@ -49,7 +50,9 @@ Base64 encoded transactions.
- `raw-bytes` convert raw-bytes to hex
* (wasmcli) [\#191](https://github.com/cosmwasm/wasmd/pull/191) Add cmd `decode-tx`, decodes a tx from hex or base64
* (wasmd) [\#9](https://github.com/cosmwasm/wasmd/pull/9) Allow gzip data in tx body on Create
* (wasmd) [\#124](https://github.com/CosmWasm/wasmd/pull/124) Update contract admin
* (wasmd) [\#131](https://github.com/CosmWasm/wasmd/pull/131) Implement REST server support for new messages
## [v2.0.3] - 2019-11-04
### Improvements

4
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/CosmWasm/wasmd
go 1.13
require (
github.com/CosmWasm/go-cosmwasm v0.8.1
github.com/CosmWasm/go-cosmwasm v0.8.1-0.20200604114456-1b2359bb7eb9
github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a // indirect
github.com/cosmos/cosmos-sdk v0.38.3
github.com/golang/mock v1.4.3 // indirect
@@ -23,7 +23,9 @@ require (
github.com/tendermint/go-amino v0.15.1
github.com/tendermint/tendermint v0.33.3
github.com/tendermint/tm-db v0.5.1
go.etcd.io/bbolt v1.3.4 // indirect
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect
)
replace github.com/keybase/go-keychain => github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4

38
go.sum
View File

@@ -9,24 +9,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f h1:4O1om+UVU+Hfcihr1timk8YNXHxzZWgCo7ofnrZRApw=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
github.com/CosmWasm/go-cosmwasm v0.7.3-0.20200506091810-b5d72f383001 h1:QvYlAMha7Wcmjn2e/D0Vk1/EFqHcnH3I01laQrSKIgk=
github.com/CosmWasm/go-cosmwasm v0.7.3-0.20200506091810-b5d72f383001/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2 h1:CRITYzG25XuBFfoft+zuRKtJk37/PxNXXKXAje7iv1Q=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200518132754-acf959da37ac h1:8iIQdsex6lXfwxGf/ju82M0VoYu6apmclJAuAtRUCzc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200518132754-acf959da37ac/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200518133220-76a4987de98b h1:AKCZCqgZAQnmJdCh4mnk23NoLzoyKQIowckBLnhrLlM=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200518133220-76a4987de98b/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200519190110-12d4e604d491 h1:nyFnbmORZp79X7NTJluPqr/ZL8+2julXqbnDzRWDTA4=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200519190110-12d4e604d491/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200519190609-972a954b9b43 h1:K+yLK6FsvVnY+FPu/SYx/WOtDUfLrSbHCA7G9ZvKsCI=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha2.0.20200519190609-972a954b9b43/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha3 h1:pa1gVDCGvM+5TBYepUhP1JHnpfOXwpBbFNSzYcXGXOU=
github.com/CosmWasm/go-cosmwasm v0.8.0-alpha3/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.0 h1:xoufklhgJQ7Sy6xwZw9hRbnXl79ylvxlpGJDcPz9Ipo=
github.com/CosmWasm/go-cosmwasm v0.8.0/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.1 h1:zoFRyB78CyInPFoC6AtY2cRSqew5P0cD0CP/cvVRBXk=
github.com/CosmWasm/go-cosmwasm v0.8.1/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/CosmWasm/go-cosmwasm v0.8.1-0.20200604114456-1b2359bb7eb9 h1:UJOWFHfh2SG47GJcQsjbcEnfw7JM4HPM2cFO1fjjqEs=
github.com/CosmWasm/go-cosmwasm v0.8.1-0.20200604114456-1b2359bb7eb9/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
@@ -120,7 +104,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
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=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
@@ -137,7 +120,6 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
@@ -167,7 +149,6 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
@@ -194,7 +175,6 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -363,7 +343,6 @@ github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
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/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
@@ -435,7 +414,6 @@ github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -458,7 +436,6 @@ github.com/tendermint/tendermint v0.33.2/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICf
github.com/tendermint/tendermint v0.33.3 h1:6lMqjEoCGejCzAghbvfQgmw87snGSqEhDTo/jw+W8CI=
github.com/tendermint/tendermint v0.33.3/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk=
github.com/tendermint/tm-db v0.4.1/go.mod h1:JsJ6qzYkCGiGwm5GHl/H5GLI9XLb6qZX7PRe425dHAY=
github.com/tendermint/tm-db v0.5.0 h1:qtM5UTr1dlRnHtDY6y7MZO5Di8XAE2j3lc/pCnKJ5hQ=
github.com/tendermint/tm-db v0.5.0/go.mod h1:lSq7q5WRR/njf1LnhiZ/lIJHk2S8Y1Zyq5oP/3o9C2U=
github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY=
github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
@@ -472,8 +449,9 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -547,10 +525,11 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -597,7 +576,6 @@ google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
@@ -629,9 +607,7 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

View File

@@ -93,10 +93,12 @@ type (
MsgStoreCode = types.MsgStoreCode
MsgInstantiateContract = types.MsgInstantiateContract
MsgExecuteContract = types.MsgExecuteContract
MsgMigrateContract = types.MsgMigrateContract
MsgUpdateAdministrator = types.MsgUpdateAdministrator
Model = types.Model
CodeInfo = types.CodeInfo
ContractInfo = types.ContractInfo
CreatedAt = types.CreatedAt
CreatedAt = types.AbsoluteTxPosition
WasmConfig = types.WasmConfig
MessageHandler = keeper.MessageHandler
BankEncoder = keeper.BankEncoder

View File

@@ -0,0 +1,94 @@
package cli
import (
"bufio"
"errors"
"strconv"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// MigrateContractCmd will migrate a contract to a new code version
func MigrateContractCmd(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "migrate [contract_addr_bech32] [new_code_id_int64] [json_encoded_migration_args]",
Short: "Migrate a wasm contract to a new code version",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
contractAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return sdkerrors.Wrap(err, "contract")
}
// get the id of the code to instantiate
codeID, err := strconv.ParseUint(args[1], 10, 64)
if err != nil {
return sdkerrors.Wrap(err, "code id")
}
migrateMsg := args[2]
msg := types.MsgMigrateContract{
Sender: cliCtx.GetFromAddress(),
Contract: contractAddr,
Code: codeID,
MigrateMsg: []byte(migrateMsg),
}
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
}
return cmd
}
// UpdateContractAdminCmd sets or clears an admin for a contract
func UpdateContractAdminCmd(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "set-contract-admin [contract_addr_bech32] [new_admin_addr_bech32]",
Short: "Set new admin for a contract. Can be empty to prevent further migrations",
Args: cobra.RangeArgs(1, 2),
RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
contractAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return sdkerrors.Wrap(err, "contract")
}
var newAdmin sdk.AccAddress
if len(args) > 1 && len(args[1]) != 0 {
newAdmin, err = sdk.AccAddressFromBech32(args[1])
if err != nil {
return sdkerrors.Wrap(err, "new admin")
}
} else {
// safety net to not accidentally clear an admin
clearAdmin := viper.GetBool(flagNoAdmin)
if !clearAdmin {
return errors.New("new admin address required or no admin flag")
}
}
msg := types.MsgUpdateAdministrator{
Sender: cliCtx.GetFromAddress(),
Contract: contractAddr,
NewAdmin: newAdmin,
}
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
}
cmd.Flags().Bool(flagNoAdmin, false, "Remove admin which disables future admin updates and migrations")
return cmd
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
@@ -27,6 +28,8 @@ const (
flagSource = "source"
flagBuilder = "builder"
flagLabel = "label"
flagAdmin = "admin"
flagNoAdmin = "no-admin"
)
// GetTxCmd returns the transaction commands for this module
@@ -42,6 +45,8 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command {
StoreCodeCmd(cdc),
InstantiateContractCmd(cdc),
ExecuteContractCmd(cdc),
MigrateContractCmd(cdc),
UpdateContractAdminCmd(cdc),
)...)
return txCmd
}
@@ -106,7 +111,7 @@ func InstantiateContractCmd(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "instantiate [code_id_int64] [json_encoded_init_args]",
Short: "Instantiate a wasm contract",
Args: cobra.ExactArgs(2),
Args: cobra.RangeArgs(2, 3),
RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
@@ -131,6 +136,15 @@ func InstantiateContractCmd(cdc *codec.Codec) *cobra.Command {
initMsg := args[1]
adminStr := viper.GetString(flagAdmin)
var adminAddr sdk.AccAddress
if len(adminStr) != 0 {
adminAddr, err = sdk.AccAddressFromBech32(adminStr)
if err != nil {
return sdkerrors.Wrap(err, "admin")
}
}
// build and sign the transaction, then broadcast to Tendermint
msg := types.MsgInstantiateContract{
Sender: cliCtx.GetFromAddress(),
@@ -138,6 +152,7 @@ func InstantiateContractCmd(cdc *codec.Codec) *cobra.Command {
Label: label,
InitFunds: amount,
InitMsg: []byte(initMsg),
Admin: adminAddr,
}
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
@@ -145,6 +160,7 @@ func InstantiateContractCmd(cdc *codec.Codec) *cobra.Command {
cmd.Flags().String(flagAmount, "", "Coins to send to the contract during instantiation")
cmd.Flags().String(flagLabel, "", "A human-readable name for this contract in lists")
cmd.Flags().String(flagAdmin, "", "Address of an admin")
return cmd
}

View File

@@ -0,0 +1,97 @@
package rest
import (
"net/http"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
"github.com/gorilla/mux"
)
func registerNewTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/wasm/contract/{contractAddr}/admin", setContractAdminHandlerFn(cliCtx)).Methods("PUT")
r.HandleFunc("/wasm/contract/{contractAddr}/code", migrateContractHandlerFn(cliCtx)).Methods("PUT")
}
type migrateContractReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
Admin sdk.AccAddress `json:"admin,omitempty" yaml:"admin"`
codeID uint64 `json:"code_id" yaml:"code_id"`
MigrateMsg []byte `json:"migrate_msg,omitempty" yaml:"migrate_msg"`
}
type updateContractAdministrateReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
Admin sdk.AccAddress `json:"admin,omitempty" yaml:"admin"`
}
func setContractAdminHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req updateContractAdministrateReq
if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) {
return
}
vars := mux.Vars(r)
contractAddr := vars["contractAddr"]
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
contractAddress, err := sdk.AccAddressFromBech32(contractAddr)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
msg := types.MsgUpdateAdministrator{
Sender: cliCtx.GetFromAddress(),
NewAdmin: req.Admin,
Contract: contractAddress,
}
if err = msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
}
}
func migrateContractHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req migrateContractReq
if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) {
return
}
vars := mux.Vars(r)
contractAddr := vars["contractAddr"]
req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}
contractAddress, err := sdk.AccAddressFromBech32(contractAddr)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
msg := types.MsgMigrateContract{
Sender: cliCtx.GetFromAddress(),
Contract: contractAddress,
Code: req.codeID,
MigrateMsg: req.MigrateMsg,
}
if err = msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
}
}

View File

@@ -10,4 +10,5 @@ import (
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
registerQueryRoutes(cliCtx, r)
registerTxRoutes(cliCtx, r)
registerNewTxRoutes(cliCtx, r)
}

View File

@@ -29,9 +29,10 @@ type storeCodeReq struct {
}
type instantiateContractReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
Deposit sdk.Coins `json:"deposit" yaml:"deposit"`
InitMsg []byte `json:"init_msg" yaml:"init_msg"`
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
Deposit sdk.Coins `json:"deposit" yaml:"deposit"`
Admin sdk.AccAddress `json:"admin,omitempty" yaml:"admin"`
InitMsg []byte `json:"init_msg" yaml:"init_msg"`
}
type executeContractReq struct {
@@ -117,6 +118,7 @@ func instantiateContractHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
Code: codeID,
InitFunds: req.Deposit,
InitMsg: req.InitMsg,
Admin: req.Admin,
}
err = msg.ValidateBasic()

View File

@@ -34,6 +34,16 @@ func NewHandler(k Keeper) sdk.Handler {
case *MsgExecuteContract:
return handleExecute(ctx, k, msg)
case *MsgMigrateContract:
return handleMigration(ctx, k, msg)
case MsgMigrateContract:
return handleMigration(ctx, k, &msg)
case *MsgUpdateAdministrator:
return handleUpdateContractAdmin(ctx, k, msg)
case MsgUpdateAdministrator:
return handleUpdateContractAdmin(ctx, k, &msg)
default:
errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
@@ -80,7 +90,7 @@ func handleStoreCode(ctx sdk.Context, k Keeper, msg *MsgStoreCode) (*sdk.Result,
}
func handleInstantiate(ctx sdk.Context, k Keeper, msg *MsgInstantiateContract) (*sdk.Result, error) {
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.InitMsg, msg.Label, msg.InitFunds)
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.Admin, msg.InitMsg, msg.Label, msg.InitFunds)
if err != nil {
return nil, err
}
@@ -117,3 +127,36 @@ func handleExecute(ctx sdk.Context, k Keeper, msg *MsgExecuteContract) (*sdk.Res
res.Events = append(events, ourEvent)
return &res, nil
}
func handleMigration(ctx sdk.Context, k Keeper, msg *MsgMigrateContract) (*sdk.Result, error) {
res, err := k.Migrate(ctx, msg.Contract, msg.Sender, msg.Code, msg.MigrateMsg)
if err != nil {
return nil, err
}
events := filterMessageEvents(ctx.EventManager())
ourEvent := sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(AttributeSigner, msg.Sender.String()),
sdk.NewAttribute(AttributeKeyContract, msg.Contract.String()),
)
res.Events = append(events, ourEvent)
return res, nil
}
func handleUpdateContractAdmin(ctx sdk.Context, k Keeper, msg *MsgUpdateAdministrator) (*sdk.Result, error) {
if err := k.UpdateContractAdmin(ctx, msg.Contract, msg.Sender, msg.NewAdmin); err != nil {
return nil, err
}
events := ctx.EventManager().Events()
ourEvent := sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(AttributeSigner, msg.Sender.String()),
sdk.NewAttribute(AttributeKeyContract, msg.Contract.String()),
)
return &sdk.Result{
Events: append(events, ourEvent),
}, nil
}

View File

@@ -25,7 +25,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
}
for _, contract := range data.Contracts {
keeper.setContractInfo(ctx, contract.ContractAddress, contract.ContractInfo)
keeper.setContractInfo(ctx, contract.ContractAddress, &contract.ContractInfo)
keeper.setContractState(ctx, contract.ContractAddress, contract.ContractState)
}

View File

@@ -2,9 +2,10 @@ package keeper
import (
"encoding/binary"
"github.com/cosmos/cosmos-sdk/x/staking"
"path/filepath"
"github.com/cosmos/cosmos-sdk/x/staking"
wasm "github.com/CosmWasm/go-cosmwasm"
wasmTypes "github.com/CosmWasm/go-cosmwasm/types"
"github.com/cosmos/cosmos-sdk/codec"
@@ -92,7 +93,7 @@ func isSimulationMode(ctx sdk.Context) bool {
}
// Instantiate creates an instance of a WASM contract
func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.AccAddress, error) {
func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.AccAddress, error) {
// create contract address
contractAddress := k.generateContractAddress(ctx, codeID)
existingAcct := k.accountKeeper.GetAccount(ctx, contractAddress)
@@ -138,15 +139,11 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddre
// instantiate wasm contract
gas := gasForContract(ctx)
res, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, querier, gas)
res, gasUsed, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if err != nil {
// TODO: wasmer doesn't return wasm gas used on error. we should consume it (for error on metering failure)
// Note: OutOfGas panics (from storage) are caught by go-cosmwasm, subtract one more gas to check if
// this contract died due to gas limit in Storage
consumeGas(ctx, GasMultiplier)
return contractAddress, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error())
}
consumeGas(ctx, res.GasUsed)
// emit all events from this contract itself
value := types.CosmosResult(*res, contractAddress)
@@ -159,7 +156,7 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddre
// persist instance
createdAt := types.NewCreatedAt(ctx)
instance := types.NewContractInfo(codeID, creator, initMsg, label, createdAt)
instance := types.NewContractInfo(codeID, creator, admin, initMsg, label, createdAt)
store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshalBinaryBare(instance))
return contractAddress, nil
@@ -189,15 +186,11 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
}
gas := gasForContract(ctx)
res, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, gas)
res, gasUsed, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
// TODO: wasmer doesn't return wasm gas used on error. we should consume it (for error on metering failure)
// Note: OutOfGas panics (from storage) are caught by go-cosmwasm, subtract one more gas to check if
// this contract died due to gas limit in Storage
consumeGas(ctx, GasMultiplier)
return sdk.Result{}, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
}
consumeGas(ctx, res.GasUsed)
// emit all events from this contract itself
value := types.CosmosResult(*res, contractAddress)
@@ -212,6 +205,73 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
return value, nil
}
// Migrate allows to upgrade a contract to a new code with data migration.
func (k Keeper) Migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte) (*sdk.Result, error) {
contractInfo := k.GetContractInfo(ctx, contractAddress)
if contractInfo == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
}
if contractInfo.Admin == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "migration not supported by this contract")
}
if !contractInfo.Admin.Equals(caller) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "no permission")
}
newCodeInfo := k.GetCodeInfo(ctx, newCodeID)
if newCodeInfo == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown code")
}
var noDeposit sdk.Coins
params := types.NewEnv(ctx, caller, noDeposit, contractAddress)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
prefixStoreKey := types.GetContractStorePrefixKey(contractAddress)
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
gas := gasForContract(ctx)
res, gasUsed, err := k.wasmer.Migrate(newCodeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if err != nil {
return nil, sdkerrors.Wrap(types.ErrMigrationFailed, err.Error())
}
// emit all events from this contract migration itself
value := types.CosmosResult(*res, contractAddress)
ctx.EventManager().EmitEvents(value.Events)
value.Events = nil
contractInfo.UpdateCodeID(ctx, newCodeID)
k.setContractInfo(ctx, contractAddress, contractInfo)
if err := k.dispatchMessages(ctx, contractAddress, res.Messages); err != nil {
return nil, sdkerrors.Wrap(err, "dispatch")
}
return &value, nil
}
// UpdateContractAdmin sets the admin value on the ContractInfo. New admin can be nil to disable further migrations/ updates.
func (k Keeper) UpdateContractAdmin(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newAdmin sdk.AccAddress) error {
contractInfo := k.GetContractInfo(ctx, contractAddress)
if contractInfo == nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
}
if contractInfo.Admin == nil {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "migration not supported by this contract")
}
if !contractInfo.Admin.Equals(caller) {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "no permission")
}
contractInfo.Admin = newAdmin
k.setContractInfo(ctx, contractAddress, contractInfo)
return nil
}
// QuerySmart queries the smart contract itself.
func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) {
ctx = ctx.WithGasMeter(sdk.NewGasMeter(k.queryGasLimit))
@@ -225,15 +285,15 @@ func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []b
Ctx: ctx,
Plugins: k.queryPlugins,
}
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, querier, gasForContract(ctx))
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gasForContract(ctx))
consumeGas(ctx, gasUsed)
if qErr != nil {
return nil, sdkerrors.Wrap(types.ErrQueryFailed, qErr.Error())
}
consumeGas(ctx, gasUsed)
return queryResult, nil
}
// QueryRaw returns the contract's state for give key. For a `nil` key a empty slice` result is returned.
// QueryRaw returns the contract's state for give key. For a `nil` key a empty slice result is returned.
func (k Keeper) QueryRaw(ctx sdk.Context, contractAddress sdk.AccAddress, key []byte) []types.Model {
result := make([]types.Model, 0)
if key == nil {
@@ -283,7 +343,7 @@ func (k Keeper) GetContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress)
return &contract
}
func (k Keeper) setContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress, contract types.ContractInfo) {
func (k Keeper) setContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress, contract *types.ContractInfo) {
store := ctx.KVStore(k.storeKey)
store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshalBinaryBare(contract))
}

View File

@@ -1,6 +1,7 @@
package keeper
import (
"bytes"
"encoding/binary"
"encoding/json"
"io/ioutil"
@@ -11,6 +12,7 @@ import (
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
stypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -195,12 +197,12 @@ func TestInstantiate(t *testing.T) {
gasBefore := ctx.GasMeter().GasConsumed()
// create with no balance is also legal
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract 1", nil)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 1", nil)
require.NoError(t, err)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
gasAfter := ctx.GasMeter().GasConsumed()
require.Equal(t, uint64(0x61f7), gasAfter-gasBefore)
require.Equal(t, uint64(0x78c3), gasAfter-gasBefore)
// ensure it is stored properly
info := keeper.GetContractInfo(ctx, addr)
@@ -228,7 +230,7 @@ func TestInstantiateWithNonExistingCodeID(t *testing.T) {
require.NoError(t, err)
const nonExistingCodeID = 9999
addr, err := keeper.Instantiate(ctx, nonExistingCodeID, creator, initMsgBz, "demo contract 2", nil)
addr, err := keeper.Instantiate(ctx, nonExistingCodeID, creator, nil, initMsgBz, "demo contract 2", nil)
require.True(t, types.ErrNotFound.Is(err), err)
require.Nil(t, addr)
}
@@ -259,7 +261,7 @@ func TestExecute(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract 3", deposit)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
@@ -295,7 +297,7 @@ func TestExecute(t *testing.T) {
// make sure gas is properly deducted from ctx
gasAfter := ctx.GasMeter().GasConsumed()
require.Equal(t, uint64(0x7b22), gasAfter-gasBefore)
require.Equal(t, uint64(0x7fa1), gasAfter-gasBefore)
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)
@@ -353,7 +355,7 @@ func TestExecuteWithPanic(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract 4", deposit)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 4", deposit)
require.NoError(t, err)
// let's make sure we get a reasonable error, no panic/crash
@@ -387,7 +389,7 @@ func TestExecuteWithCpuLoop(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract 5", deposit)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 5", deposit)
require.NoError(t, err)
// make sure we set a limit before calling
@@ -429,7 +431,7 @@ func TestExecuteWithStorageLoop(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract 6", deposit)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 6", deposit)
require.NoError(t, err)
// make sure we set a limit before calling
@@ -451,6 +453,199 @@ func TestExecuteWithStorageLoop(t *testing.T) {
require.True(t, false, "We must panic before this line")
}
func TestMigrate(t *testing.T) {
tempDir, err := ioutil.TempDir("", "wasm")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
ctx, keepers := CreateTestInput(t, false, tempDir, SupportedFeatures, nil, nil)
accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(ctx, accKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(ctx, accKeeper, topUp)
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
require.NoError(t, err)
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
require.NoError(t, err)
newContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
require.NoError(t, err)
require.NotEqual(t, originalContractID, newContractID)
_, _, anyAddr := keyPubAddr()
initMsg := InitMsg{
Verifier: fred,
Beneficiary: anyAddr,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
specs := map[string]struct {
admin sdk.AccAddress
overrideContractAddr sdk.AccAddress
caller sdk.AccAddress
codeID uint64
migrateMsg []byte
expErr *sdkerrors.Error
}{
"all good with same code id": {
admin: creator,
caller: creator,
codeID: originalContractID,
},
"all good with new code id": {
admin: creator,
caller: creator,
codeID: newContractID,
},
"all good with admin set": {
admin: fred,
caller: fred,
codeID: newContractID,
},
"prevent migration when admin was not set on instantiate": {
caller: creator,
codeID: originalContractID,
expErr: sdkerrors.ErrUnauthorized,
},
"prevent migration when not admin": {
caller: creator,
admin: fred,
codeID: originalContractID,
expErr: sdkerrors.ErrUnauthorized,
},
"fail with non existing code id": {
admin: creator,
caller: creator,
codeID: 99999,
expErr: sdkerrors.ErrInvalidRequest,
},
"fail with non existing contract addr": {
admin: creator,
caller: creator,
overrideContractAddr: anyAddr,
codeID: originalContractID,
expErr: sdkerrors.ErrInvalidRequest,
},
"fail when migration caused error": {
admin: creator,
caller: creator,
codeID: originalContractID,
migrateMsg: bytes.Repeat([]byte{0x1}, 7), // condition hard coded in stub: >6 = error
expErr: types.ErrMigrationFailed,
},
}
var (
builtIntoGoCosmWasmStubGas = sdk.Gas(10000)
builtIntoGoCosmWasmStubData = []byte(("my-migration-response-data"))
)
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
addr, err := keeper.Instantiate(ctx, originalContractID, creator, spec.admin, initMsgBz, "demo contract", nil)
require.NoError(t, err)
if spec.overrideContractAddr != nil {
addr = spec.overrideContractAddr
}
gasBefore := ctx.GasMeter().GasConsumed()
res, err := keeper.Migrate(ctx, addr, spec.caller, spec.codeID, spec.migrateMsg)
require.True(t, spec.expErr.Is(err), "expected %v but got %+v", spec.expErr, err)
if spec.expErr != nil {
return
}
gasAfter := ctx.GasMeter().GasConsumed()
assert.Greater(t, gasAfter-gasBefore, builtIntoGoCosmWasmStubGas/GasMultiplier)
assert.Equal(t, builtIntoGoCosmWasmStubData, res.Data)
cInfo := keeper.GetContractInfo(ctx, addr)
assert.Equal(t, spec.codeID, cInfo.CodeID)
assert.Equal(t, originalContractID, cInfo.PreviousCodeID)
assert.Equal(t, types.NewCreatedAt(ctx), cInfo.LastUpdated)
// TODO: check contract store was updated by migration code (impl also in contract)
// TODO: check any messages dispatched proper
// TODO: check events?
})
}
}
func TestUpdateContractAdmin(t *testing.T) {
tempDir, err := ioutil.TempDir("", "wasm")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
ctx, keepers := CreateTestInput(t, false, tempDir, SupportedFeatures, nil, nil)
accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(ctx, accKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(ctx, accKeeper, topUp)
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
require.NoError(t, err)
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
require.NoError(t, err)
_, _, anyAddr := keyPubAddr()
initMsg := InitMsg{
Verifier: fred,
Beneficiary: anyAddr,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
specs := map[string]struct {
instAdmin sdk.AccAddress
newAdmin sdk.AccAddress
overrideContractAddr sdk.AccAddress
caller sdk.AccAddress
expErr *sdkerrors.Error
}{
"all good with admin set": {
instAdmin: fred,
newAdmin: anyAddr,
caller: fred,
},
"all good with new admin empty": {
instAdmin: fred,
newAdmin: nil,
caller: fred,
},
"prevent update when admin was not set on instantiate": {
caller: creator,
newAdmin: fred,
expErr: sdkerrors.ErrUnauthorized,
},
"prevent updates from non admin address": {
instAdmin: creator,
newAdmin: fred,
caller: fred,
expErr: sdkerrors.ErrUnauthorized,
},
"fail with non existing contract addr": {
instAdmin: creator,
caller: creator,
overrideContractAddr: anyAddr,
expErr: sdkerrors.ErrInvalidRequest,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
addr, err := keeper.Instantiate(ctx, originalContractID, creator, spec.instAdmin, initMsgBz, "demo contract", nil)
require.NoError(t, err)
if spec.overrideContractAddr != nil {
addr = spec.overrideContractAddr
}
err = keeper.UpdateContractAdmin(ctx, addr, spec.caller, spec.newAdmin)
require.True(t, spec.expErr.Is(err), "expected %v but got %+v", spec.expErr, err)
if spec.expErr != nil {
return
}
cInfo := keeper.GetContractInfo(ctx, addr)
assert.Equal(t, spec.newAdmin, cInfo.Admin)
})
}
}
type InitMsg struct {
Verifier sdk.AccAddress `json:"verifier"`
Beneficiary sdk.AccAddress `json:"beneficiary"`

View File

@@ -71,6 +71,8 @@ func queryContractInfo(ctx sdk.Context, bech string, req abci.RequestQuery, keep
}
// redact the Created field (just used for sorting, not part of public API)
info.Created = nil
info.LastUpdated = nil
info.PreviousCodeID = 0
infoWithAddress := ContractInfoWithAddress{
Address: addr,
@@ -104,7 +106,7 @@ func queryContractListByCode(ctx sdk.Context, codeIDstr string, req abci.Request
return false
})
// now we sort them by CreatedAt
// now we sort them by AbsoluteTxPosition
sort.Slice(contracts, func(i, j int) bool {
return contracts[i].ContractInfo.Created.LessThan(contracts[j].ContractInfo.Created)
})

View File

@@ -41,7 +41,7 @@ func TestQueryContractState(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
addr, err := keeper.Instantiate(ctx, contractID, creator, initMsgBz, "demo contract to query", deposit)
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract to query", deposit)
require.NoError(t, err)
contractModel := []types.Model{
@@ -187,7 +187,7 @@ func TestListContractByCodeOrdering(t *testing.T) {
ctx = setBlock(ctx, h)
h++
}
_, err = keeper.Instantiate(ctx, codeID, creator, initMsgBz, fmt.Sprintf("contract %d", i), topUp)
_, err = keeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, fmt.Sprintf("contract %d", i), topUp)
require.NoError(t, err)
}

View File

@@ -32,6 +32,10 @@ func (q QueryHandler) Query(request wasmTypes.QueryRequest) ([]byte, error) {
return nil, wasmTypes.Unknown{}
}
func (q QueryHandler) GasConsumed() uint64 {
return q.Ctx.GasMeter().GasConsumed()
}
type CustomQuerier func(ctx sdk.Context, request json.RawMessage) ([]byte, error)
type QueryPlugins struct {

View File

@@ -78,7 +78,7 @@ func TestMaskReflectContractSend(t *testing.T) {
// creator instantiates a contract and gives it tokens
maskStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
maskAddr, err := keeper.Instantiate(ctx, maskID, creator, []byte("{}"), "mask contract 2", maskStart)
maskAddr, err := keeper.Instantiate(ctx, maskID, creator, nil, []byte("{}"), "mask contract 2", maskStart)
require.NoError(t, err)
require.NotEmpty(t, maskAddr)
@@ -90,7 +90,7 @@ func TestMaskReflectContractSend(t *testing.T) {
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
escrowStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 25000))
escrowAddr, err := keeper.Instantiate(ctx, escrowID, creator, initMsgBz, "escrow contract 2", escrowStart)
escrowAddr, err := keeper.Instantiate(ctx, escrowID, creator, nil, initMsgBz, "escrow contract 2", escrowStart)
require.NoError(t, err)
require.NotEmpty(t, escrowAddr)
@@ -156,7 +156,7 @@ func TestMaskReflectCustomMsg(t *testing.T) {
// creator instantiates a contract and gives it tokens
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, []byte("{}"), "mask contract 1", contractStart)
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, nil, []byte("{}"), "mask contract 1", contractStart)
require.NoError(t, err)
require.NotEmpty(t, contractAddr)
@@ -250,7 +250,7 @@ func TestMaskReflectCustomQuery(t *testing.T) {
// creator instantiates a contract and gives it tokens
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, []byte("{}"), "mask contract 1", contractStart)
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, nil, []byte("{}"), "mask contract 1", contractStart)
require.NoError(t, err)
require.NotEmpty(t, contractAddr)

View File

@@ -22,8 +22,8 @@ type StakingInitMsg struct {
Decimals uint8 `json:"decimals"`
Validator sdk.ValAddress `json:"validator"`
ExitTax sdk.Dec `json:"exit_tax"`
// MinWithdrawl is uint128 encoded as a string (use sdk.Int?)
MinWithdrawl string `json:"min_withdrawl"`
// MinWithdrawal is uint128 encoded as a string (use sdk.Int?)
MinWithdrawl string `json:"min_withdrawal"`
}
// StakingHandleMsg is used to encode handle messages
@@ -119,7 +119,7 @@ func TestInitializeStaking(t *testing.T) {
initBz, err := json.Marshal(&initMsg)
require.NoError(t, err)
stakingAddr, err := keeper.Instantiate(ctx, stakingID, creator, initBz, "staking derivates - DRV", nil)
stakingAddr, err := keeper.Instantiate(ctx, stakingID, creator, nil, initBz, "staking derivates - DRV", nil)
require.NoError(t, err)
require.NotEmpty(t, stakingAddr)
@@ -139,7 +139,7 @@ func TestInitializeStaking(t *testing.T) {
badBz, err := json.Marshal(&badInitMsg)
require.NoError(t, err)
_, err = keeper.Instantiate(ctx, stakingID, creator, badBz, "missing validator", nil)
_, err = keeper.Instantiate(ctx, stakingID, creator, nil, badBz, "missing validator", nil)
require.Error(t, err)
// no changes to bonding shares
@@ -203,7 +203,7 @@ func initializeStaking(t *testing.T) initInfo {
initBz, err := json.Marshal(&initMsg)
require.NoError(t, err)
stakingAddr, err := keeper.Instantiate(ctx, stakingID, creator, initBz, "staking derivates - DRV", nil)
stakingAddr, err := keeper.Instantiate(ctx, stakingID, creator, nil, initBz, "staking derivates - DRV", nil)
require.NoError(t, err)
require.NotEmpty(t, stakingAddr)

View File

@@ -198,7 +198,7 @@ func TestHandler(k Keeper) sdk.Handler {
}
func handleInstantiate(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgInstantiateContract) (*sdk.Result, error) {
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.InitMsg, msg.Label, msg.InitFunds)
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.Admin, msg.InitMsg, msg.Label, msg.InitFunds)
if err != nil {
return nil, err
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -10,6 +10,8 @@ func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(&MsgStoreCode{}, "wasm/store-code", nil)
cdc.RegisterConcrete(&MsgInstantiateContract{}, "wasm/instantiate", nil)
cdc.RegisterConcrete(&MsgExecuteContract{}, "wasm/execute", nil)
cdc.RegisterConcrete(&MsgMigrateContract{}, "wasm/migrate", nil)
cdc.RegisterConcrete(&MsgUpdateAdministrator{}, "wasm/update-contract-admin", nil)
}
// ModuleCdc generic sealed codec to be used throughout module

View File

@@ -34,4 +34,7 @@ var (
// ErrInvalidMsg error when we cannot process the error returned from the contract
ErrInvalidMsg = sdkErrors.Register(DefaultCodespace, 9, "invalid CosmosMsg from the contract")
// ErrMigrationFailed error for rust execution contract failure
ErrMigrationFailed = sdkErrors.Register(DefaultCodespace, 10, "migrate wasm contract failed")
)

View File

@@ -102,7 +102,9 @@ func validateBuilder(buildTag string) error {
}
type MsgInstantiateContract struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
// Admin is an optional address that can execute migrations
Admin sdk.AccAddress `json:"admin,omitempty" yaml:"admin"`
Code uint64 `json:"code_id" yaml:"code_id"`
Label string `json:"label" yaml:"label"`
InitMsg json.RawMessage `json:"init_msg" yaml:"init_msg"`
@@ -135,6 +137,13 @@ func (msg MsgInstantiateContract) ValidateBasic() error {
if msg.InitFunds.IsAnyNegative() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "negative InitFunds")
}
if len(msg.Admin) != 0 {
if err := sdk.VerifyAddressFormat(msg.Admin); err != nil {
return err
}
}
return nil
}
@@ -182,3 +191,79 @@ func (msg MsgExecuteContract) GetSignBytes() []byte {
func (msg MsgExecuteContract) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Sender}
}
type MsgMigrateContract struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
Contract sdk.AccAddress `json:"contract" yaml:"contract"`
Code uint64 `json:"code_id" yaml:"code_id"`
MigrateMsg json.RawMessage `json:"msg" yaml:"msg"`
}
func (msg MsgMigrateContract) Route() string {
return RouterKey
}
func (msg MsgMigrateContract) Type() string {
return "migrate"
}
func (msg MsgMigrateContract) ValidateBasic() error {
if msg.Code == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "code_id is required")
}
if err := sdk.VerifyAddressFormat(msg.Sender); err != nil {
return sdkerrors.Wrap(err, "sender")
}
if err := sdk.VerifyAddressFormat(msg.Contract); err != nil {
return sdkerrors.Wrap(err, "contract")
}
return nil
}
func (msg MsgMigrateContract) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}
func (msg MsgMigrateContract) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Sender}
}
type MsgUpdateAdministrator struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
NewAdmin sdk.AccAddress `json:"new_admin,omitempty" yaml:"new_admin"`
Contract sdk.AccAddress `json:"contract" yaml:"contract"`
}
func (msg MsgUpdateAdministrator) Route() string {
return RouterKey
}
func (msg MsgUpdateAdministrator) Type() string {
return "update-contract-admin"
}
func (msg MsgUpdateAdministrator) ValidateBasic() error {
if err := sdk.VerifyAddressFormat(msg.Sender); err != nil {
return sdkerrors.Wrap(err, "sender")
}
if err := sdk.VerifyAddressFormat(msg.Contract); err != nil {
return sdkerrors.Wrap(err, "contract")
}
if len(msg.NewAdmin) != 0 {
if err := sdk.VerifyAddressFormat(msg.NewAdmin); err != nil {
return sdkerrors.Wrap(err, "new admin")
}
if msg.Sender.Equals(msg.NewAdmin) {
return sdkerrors.Wrap(ErrInvalidMsg, "new admin is the same as the old")
}
}
return nil
}
func (msg MsgUpdateAdministrator) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}
func (msg MsgUpdateAdministrator) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Sender}
}

View File

@@ -1,6 +1,7 @@
package types
import (
"bytes"
"strings"
"testing"
@@ -208,5 +209,150 @@ func TestInstantiateContractValidation(t *testing.T) {
}
})
}
}
func TestMsgUpdateAdministrator(t *testing.T) {
badAddress, err := sdk.AccAddressFromHex("012345")
require.NoError(t, err)
// proper address size
goodAddress := sdk.AccAddress(make([]byte, 20))
otherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x1}, 20))
anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20))
specs := map[string]struct {
src MsgUpdateAdministrator
expErr bool
}{
"all good": {
src: MsgUpdateAdministrator{
Sender: goodAddress,
NewAdmin: otherGoodAddress,
Contract: anotherGoodAddress,
},
},
"new admin optional": {
src: MsgUpdateAdministrator{
Sender: goodAddress,
Contract: anotherGoodAddress,
},
},
"bad sender": {
src: MsgUpdateAdministrator{
Sender: badAddress,
NewAdmin: otherGoodAddress,
Contract: anotherGoodAddress,
},
expErr: true,
},
"bad new admin": {
src: MsgUpdateAdministrator{
Sender: goodAddress,
NewAdmin: badAddress,
Contract: anotherGoodAddress,
},
expErr: true,
},
"bad contract addr": {
src: MsgUpdateAdministrator{
Sender: goodAddress,
NewAdmin: otherGoodAddress,
Contract: badAddress,
},
expErr: true,
},
"new admin same as old admin": {
src: MsgUpdateAdministrator{
Sender: goodAddress,
NewAdmin: goodAddress,
Contract: anotherGoodAddress,
},
expErr: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
err := spec.src.ValidateBasic()
if spec.expErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
func TestMsgMigrateContract(t *testing.T) {
badAddress, err := sdk.AccAddressFromHex("012345")
require.NoError(t, err)
// proper address size
goodAddress := sdk.AccAddress(make([]byte, 20))
anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20))
specs := map[string]struct {
src MsgMigrateContract
expErr bool
}{
"all good": {
src: MsgMigrateContract{
Sender: goodAddress,
Contract: anotherGoodAddress,
Code: 1,
MigrateMsg: []byte{1},
},
},
"MigrateMsg optional": {
src: MsgMigrateContract{
Sender: goodAddress,
Contract: anotherGoodAddress,
Code: 1,
},
},
"bad sender": {
src: MsgMigrateContract{
Sender: badAddress,
Contract: anotherGoodAddress,
Code: 1,
},
expErr: true,
},
"empty sender": {
src: MsgMigrateContract{
Contract: anotherGoodAddress,
Code: 1,
},
expErr: true,
},
"empty code": {
src: MsgMigrateContract{
Sender: goodAddress,
Contract: anotherGoodAddress,
},
expErr: true,
},
"bad contract addr": {
src: MsgMigrateContract{
Sender: goodAddress,
Contract: badAddress,
Code: 1,
},
expErr: true,
},
"empty contract addr": {
src: MsgMigrateContract{
Sender: goodAddress,
Code: 1,
},
expErr: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
err := spec.src.ValidateBasic()
if spec.expErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}

View File

@@ -2,6 +2,7 @@ package types
import (
"encoding/json"
tmBytes "github.com/tendermint/tendermint/libs/bytes"
wasmTypes "github.com/CosmWasm/go-cosmwasm/types"
@@ -41,15 +42,24 @@ func NewCodeInfo(codeHash []byte, creator sdk.AccAddress, source string, builder
type ContractInfo struct {
CodeID uint64 `json:"code_id"`
Creator sdk.AccAddress `json:"creator"`
Admin sdk.AccAddress `json:"admin,omitempty"`
Label string `json:"label"`
InitMsg json.RawMessage `json:"init_msg,omitempty"`
// never show this in query results, just use for sorting
// (Note: when using json tag "-" amino refused to serialize it...)
Created *CreatedAt `json:"created,omitempty"`
Created *AbsoluteTxPosition `json:"created,omitempty"`
LastUpdated *AbsoluteTxPosition `json:"last_updated,omitempty"`
PreviousCodeID uint64 `json:"previous_code_id,omitempty"`
}
// CreatedAt can be used to sort contracts
type CreatedAt struct {
func (c *ContractInfo) UpdateCodeID(ctx sdk.Context, newCodeID uint64) {
c.PreviousCodeID = c.CodeID
c.CodeID = newCodeID
c.LastUpdated = NewCreatedAt(ctx)
}
// AbsoluteTxPosition can be used to sort contracts
type AbsoluteTxPosition struct {
// BlockHeight is the block the contract was created at
BlockHeight int64
// TxIndex is a monotonic counter within the block (actual transaction index, or gas consumed)
@@ -57,7 +67,7 @@ type CreatedAt struct {
}
// LessThan can be used to sort
func (a *CreatedAt) LessThan(b *CreatedAt) bool {
func (a *AbsoluteTxPosition) LessThan(b *AbsoluteTxPosition) bool {
if a == nil {
return true
}
@@ -68,24 +78,25 @@ func (a *CreatedAt) LessThan(b *CreatedAt) bool {
}
// NewCreatedAt gets a timestamp from the context
func NewCreatedAt(ctx sdk.Context) *CreatedAt {
func NewCreatedAt(ctx sdk.Context) *AbsoluteTxPosition {
// we must safely handle nil gas meters
var index uint64
meter := ctx.BlockGasMeter()
if meter != nil {
index = meter.GasConsumed()
}
return &CreatedAt{
return &AbsoluteTxPosition{
BlockHeight: ctx.BlockHeight(),
TxIndex: index,
}
}
// NewContractInfo creates a new instance of a given WASM contract info
func NewContractInfo(codeID uint64, creator sdk.AccAddress, initMsg []byte, label string, createdAt *CreatedAt) ContractInfo {
func NewContractInfo(codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, createdAt *AbsoluteTxPosition) ContractInfo {
return ContractInfo{
CodeID: codeID,
Creator: creator,
Admin: admin,
InitMsg: initMsg,
Label: label,
Created: createdAt,