@@ -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
4
go.mod
@@ -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
38
go.sum
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
94
x/wasm/client/cli/new_tx.go
Normal file
94
x/wasm/client/cli/new_tx.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
97
x/wasm/client/rest/new_tx.go
Normal file
97
x/wasm/client/rest/new_tx.go
Normal 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})
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,5 @@ import (
|
||||
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||
registerQueryRoutes(cliCtx, r)
|
||||
registerTxRoutes(cliCtx, r)
|
||||
registerNewTxRoutes(cliCtx, r)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
BIN
x/wasm/internal/keeper/testdata/contract.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/contract.wasm
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/contract.wasm.gzip
vendored
BIN
x/wasm/internal/keeper/testdata/contract.wasm.gzip
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/reflect.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/reflect.wasm
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/staking.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/staking.wasm
vendored
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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")
|
||||
)
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user