Skip to content

Commit

Permalink
Merge pull request #565 from CosmWasm/410-standardize-address-derivation
Browse files Browse the repository at this point in the history
Standardize address derivation
  • Loading branch information
ethanfrey committed Jul 28, 2021
2 parents c84a086 + 6f720a4 commit 6f684d5
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 57 deletions.
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

0 comments on commit 6f684d5

Please sign in to comment.