Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize address derivation #565

Merged
merged 6 commits into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

## [Unreleased](https://github.com/CosmWasm/wasmd/tree/HEAD)

**Api Breaking:**

- Move Proto version from `v1beta1` to `v1` for all cosmwasm.wasm.* types
[\#563](https://github.com/CosmWasm/wasmd/pull/563)
- Renamed InitMsg and MigrateMsg fields to Msg. This applies to protobuf Msg
and Proposals, as well as REST and CLI [\#563](https://github.com/CosmWasm/wasmd/pull/563)
- Removed source and builder fields from StoreCode and CodeInfo. They were rarely used.
[\#564](https://github.com/CosmWasm/wasmd/pull/564)
- Changed contract address derivation function. If you hardcoded the first contract
addresses anywhere (in scripts?), please update them.
[\#565](https://github.com/CosmWasm/wasmd/pull/565)

**Implemented Enhancements:**

- Reject invalid events/attributes returned from contracts [\#560](https://github.com/CosmWasm/wasmd/pull/560)
- IBC Query methods from Wasm contracts only return OPEN channels [\#568](https://github.com/CosmWasm/wasmd/pull/568)

[Full Changelog](https://github.com/CosmWasm/wasmd/compare/v0.17.0...HEAD)

**Api Breaking:**

- Renamed InitMsg and MigrateMsg fields to Msg. This applies to protobuf Msg
and Proposals, as well as REST and CLI [\#563](https://github.com/CosmWasm/wasmd/pull/563)
- Move Proto version from `v1beta1` to `v1` for all cosmwasm.wasm.* types
[\#563](https://github.com/CosmWasm/wasmd/pull/563)

## [v0.17.0](https://github.com/CosmWasm/wasmd/tree/v0.17.0) (2021-05-26)

[Full Changelog](https://github.com/CosmWasm/wasmd/compare/v0.17.0...v0.16.0)
Expand Down
14 changes: 7 additions & 7 deletions x/wasm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ was sent:
},
{
"key": "_contract_address",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
}
]
}
Expand All @@ -70,7 +70,7 @@ provide a initial balance in the same `MsgInstantiateContract`. We see the follo
"Attr": [
{
"key": "recipient",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
},
{
"key": "sender",
Expand All @@ -97,7 +97,7 @@ Here is an example from the escrow contract successfully releasing funds to the
"Attr": [
{
"key": "_contract_address",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
},
{
"key": "action",
Expand Down Expand Up @@ -131,7 +131,7 @@ was executed (which always appears, while 2 is optional and has information as r
"Attr": [
{
"key": "recipient",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
},
{
"key": "sender",
Expand All @@ -148,7 +148,7 @@ was executed (which always appears, while 2 is optional and has information as r
"Attr": [
{
"key": "_contract_address",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
},
{
"key": "action",
Expand All @@ -169,7 +169,7 @@ was executed (which always appears, while 2 is optional and has information as r
},
{
"key": "sender",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
},
{
"key": "amount",
Expand All @@ -194,7 +194,7 @@ was executed (which always appears, while 2 is optional and has information as r
},
{
"key": "_contract_address",
"value": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
"value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
}
]
}
Expand Down
5 changes: 3 additions & 2 deletions x/wasm/client/cli/genesis_msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func TestInstantiateContractCmd(t *testing.T) {
}

func TestExecuteContractCmd(t *testing.T) {
const firstContractAddress = "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"
const firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6"
minimalWasmGenesis := types.GenesisState{
Params: types.DefaultParams(),
}
Expand Down Expand Up @@ -396,7 +396,8 @@ func TestExecuteContractCmd(t *testing.T) {
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{"cosmos1weh0k0l6t6v4jkmkde8e90tzkw2c59g42ccl62", `{}`})
// See TestBuildContractAddress in keeper_test.go
cmd.SetArgs([]string{"cosmos1mujpjkwhut9yjw4xueyugc02evfv46y04aervg", `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", myWellFundedAccount)
},
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/client/proposal_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func TestGovRestHandlers(t *testing.T) {
"title": "Test Proposal",
"description": "My proposal",
"type": "migrate",
"contract": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
"contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6",
"code_id": "1",
"msg": dict{"foo": "bar"},
"run_as": "cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz",
Expand All @@ -188,7 +188,7 @@ func TestGovRestHandlers(t *testing.T) {
"title": "Test Proposal",
"description": "My proposal",
"type": "migrate",
"contract": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
"contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6",
"new_admin": "cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz",
"deposit": []dict{{"denom": "ustake", "amount": "10"}},
"proposer": "cosmos1ve557a5g9yw2g2z57js3pdmcvd5my6g8ze20np",
Expand All @@ -202,7 +202,7 @@ func TestGovRestHandlers(t *testing.T) {
"title": "Test Proposal",
"description": "My proposal",
"type": "migrate",
"contract": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
"contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6",
"deposit": []dict{{"denom": "ustake", "amount": "10"}},
"proposer": "cosmos1ve557a5g9yw2g2z57js3pdmcvd5my6g8ze20np",
"base_req": aBaseReq,
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
],
"contracts": [
{
"contract_address": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
"contract_address": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6",
"contract_info": {
"code_id": "1",
"creator": "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x",
Expand Down Expand Up @@ -533,7 +533,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
assert.Equal(t, expCodeInfo, *gotCodeInfo)

// verify contract
contractAddr, _ := sdk.AccAddressFromBech32("cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5")
contractAddr, _ := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6")
gotContractInfo := keeper.GetContractInfo(ctx, contractAddr)
require.NotNil(t, gotContractInfo)
contractCreatorAddr := "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x"
Expand Down
45 changes: 39 additions & 6 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"github.com/CosmWasm/wasmd/x/wasm/types"
Expand Down Expand Up @@ -815,13 +816,45 @@ func (k Keeper) generateContractAddress(ctx sdk.Context, codeID uint64) sdk.AccA

// BuildContractAddress builds an sdk account address for a contract.
func BuildContractAddress(codeID, instanceID uint64) sdk.AccAddress {
if codeID > math.MaxUint32 || instanceID > math.MaxUint32 {
// NOTE: It is possible to get a duplicate address if either codeID or instanceID
// overflow 32 bits. This is highly improbable, but something that could be refactored.
panic(fmt.Sprintf("address uint32 reached: codeID: %d, instanceID: %d", codeID, instanceID))
contractID := make([]byte, 16)
binary.BigEndian.PutUint64(contractID[:8], codeID)
binary.BigEndian.PutUint64(contractID[8:], instanceID)
// 20 bytes to work with Cosmos SDK 0.42 (0.43 pushes for 32 bytes)
// TODO: remove truncate if we update to 0.43 before wasmd 1.0
return Module(types.ModuleName, contractID)[:20]
}

// Hash and Module is taken from https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-rc2/types/address/hash.go
// (PR #9088 included in Cosmos SDK 0.43 - can be swapped out for the sdk version when we upgrade)

// Hash creates a new address from address type and key
func Hash(typ string, key []byte) []byte {
hasher := sha256.New()
_, err := hasher.Write([]byte(typ))
// the error always nil, it's here only to satisfy the io.Writer interface
assertNil(err)
th := hasher.Sum(nil)

hasher.Reset()
_, err = hasher.Write(th)
assertNil(err)
_, err = hasher.Write(key)
assertNil(err)
return hasher.Sum(nil)
}

// Module is a specialized version of a composed address for modules. Each module account
// is constructed from a module name and module account key.
func Module(moduleName string, key []byte) []byte {
mKey := append([]byte(moduleName), 0)
return Hash("module", append(mKey, key...))
}

// Also from the 0.43 Cosmos SDK... sigh (sdkerrors.AssertNil)
func assertNil(err error) {
if err != nil {
panic(fmt.Errorf("logic error - this should never happen. %w", err))
}
contractID := codeID<<32 + instanceID
return addrFromUint64(contractID)
}

// GetNextCodeID reads the next sequence id used for storing wasm code.
Expand Down
40 changes: 24 additions & 16 deletions x/wasm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func TestInstantiate(t *testing.T) {
// create with no balance is also legal
gotContractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, "demo contract 1", nil)
require.NoError(t, err)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", gotContractAddr.String())
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", gotContractAddr.String())

gasAfter := ctx.GasMeter().GasConsumed()
if types.EnableGasVerification {
Expand Down Expand Up @@ -481,7 +481,7 @@ func TestExecute(t *testing.T) {

addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", addr.String())

// ensure bob doesn't exist
bobAcct := accKeeper.GetAccount(ctx, bob)
Expand Down Expand Up @@ -1163,7 +1163,7 @@ func TestSudo(t *testing.T) {

addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", addr.String())

// the community is broke
_, _, community := keyPubAddr()
Expand Down Expand Up @@ -1501,9 +1501,18 @@ func TestBuildContractAddress(t *testing.T) {
specs := map[string]struct {
srcCodeID uint64
srcInstanceID uint64
expPanic bool
expectedAddr string
}{
"both empty": {},
"initial contract": {
srcCodeID: 1,
srcInstanceID: 1,
expectedAddr: "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6",
},
"demo value": {
srcCodeID: 1,
srcInstanceID: 100,
expectedAddr: "cosmos1mujpjkwhut9yjw4xueyugc02evfv46y04aervg",
},
"both below max": {
srcCodeID: math.MaxUint32 - 1,
srcInstanceID: math.MaxUint32 - 1,
Expand All @@ -1512,26 +1521,25 @@ func TestBuildContractAddress(t *testing.T) {
srcCodeID: math.MaxUint32,
srcInstanceID: math.MaxUint32,
},
"codeID > max": {
srcCodeID: math.MaxUint32 + 1,
expPanic: true,
"codeID > max u32": {
srcCodeID: math.MaxUint32 + 1,
srcInstanceID: 17,
expectedAddr: "cosmos1673hrexz4h6s0ft04l96ygq667djzh2nvy7fsu",
},
"instanceID > max": {
"instanceID > max u32": {
srcCodeID: 22,
srcInstanceID: math.MaxUint32 + 1,
expPanic: true,
expectedAddr: "cosmos10q3pgfvmeyy0veekgtqhxujxkhz0vm9z65ckqh",
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
if spec.expPanic {
require.Panics(t, func() {
BuildContractAddress(spec.srcCodeID, spec.srcInstanceID)
})
return
}
gotAddr := BuildContractAddress(spec.srcCodeID, spec.srcInstanceID)
require.NotNil(t, gotAddr)
assert.Nil(t, sdk.VerifyAddressFormat(gotAddr))
if len(spec.expectedAddr) > 0 {
require.Equal(t, spec.expectedAddr, gotAddr.String())
}
})
}
}
2 changes: 1 addition & 1 deletion x/wasm/keeper/proposal_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func TestInstantiateProposal(t *testing.T) {
require.NoError(t, err)

// then
contractAddr, err := sdk.AccAddressFromBech32("cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5")
contractAddr, err := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6")
require.NoError(t, err)

cInfo := wasmKeeper.GetContractInfo(ctx, contractAddr)
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func TestHandleInstantiate(t *testing.T) {
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)

require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", contractBech32Addr)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr)
// this should be standard x/wasm init event, nothing from contract
require.Equal(t, 2, len(res.Events), prettyEvents(res.Events))
assert.Equal(t, "wasm", res.Events[0].Type)
Expand Down Expand Up @@ -234,7 +234,7 @@ func TestHandleExecute(t *testing.T) {
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)

require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", contractBech32Addr)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr)
// this should be standard x/wasm init event, plus a bank send event (2), with no custom contract events
require.Equal(t, 3, len(res.Events), prettyEvents(res.Events))
assert.Equal(t, "transfer", res.Events[0].Type)
Expand Down Expand Up @@ -354,7 +354,7 @@ func TestHandleExecuteEscrow(t *testing.T) {
res, err = h(data.ctx, &initCmd)
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", contractBech32Addr)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr)

handleMsg := map[string]interface{}{
"release": map[string]interface{}{},
Expand Down
12 changes: 6 additions & 6 deletions x/wasm/types/proposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ func TestProposalStrings(t *testing.T) {
exp: `Migrate Contract Proposal:
Title: Foo
Description: Bar
Contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
Code id: 1
Run as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du
Msg "{\"verifier\":\"cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du\"}"
Expand All @@ -520,7 +520,7 @@ func TestProposalStrings(t *testing.T) {
exp: `Update Contract Admin Proposal:
Title: Foo
Description: Bar
Contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
New Admin: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du
`,
},
Expand All @@ -529,7 +529,7 @@ func TestProposalStrings(t *testing.T) {
exp: `Clear Contract Admin Proposal:
Title: Foo
Description: Bar
Contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
`,
},
"pin codes": {
Expand Down Expand Up @@ -628,7 +628,7 @@ funds: []
src: MigrateContractProposalFixture(),
exp: `title: Foo
description: Bar
contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
code_id: 1
msg: '{"verifier":"cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du"}'
run_as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du
Expand All @@ -639,14 +639,14 @@ run_as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du
exp: `title: Foo
description: Bar
new_admin: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du
contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
`,
},
"clear admin": {
src: ClearAdminProposalFixture(),
exp: `title: Foo
description: Bar
contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6
`,
},
"pin codes": {
Expand Down
Loading