Allow access to contract address builder

This commit is contained in:
Alex Peters
2021-06-01 10:42:07 +02:00
parent ed60864bf2
commit 2f2d59a151
8 changed files with 71 additions and 36 deletions

View File

@@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/CosmWasm/wasmd/x/wasm/types"
"github.com/cosmos/cosmos-sdk/client"
@@ -317,7 +318,7 @@ func getAllContracts(state *types.GenesisState) []contractMeta {
for _, m := range state.GenMsgs {
if msg := m.GetInstantiateContract(); msg != nil {
all = append(all, contractMeta{
ContractAddress: contractAddress(msg.CodeID, seq).String(),
ContractAddress: keeper.BuildContractAddress(msg.CodeID, seq).String(),
Info: types.ContractInfo{
CodeID: msg.CodeID,
Creator: msg.Sender,
@@ -358,7 +359,7 @@ func hasContract(state *types.GenesisState, contractAddr string) bool {
seq := contractSeqValue(state)
for _, m := range state.GenMsgs {
if msg := m.GetInstantiateContract(); msg != nil {
if contractAddress(msg.CodeID, seq).String() == contractAddr {
if keeper.BuildContractAddress(msg.CodeID, seq).String() == contractAddr {
return true
}
seq++
@@ -511,14 +512,6 @@ func getActorAddress(cmd *cobra.Command) (sdk.AccAddress, error) {
return info.GetAddress(), nil
}
// contractAddress builds a contract address. copied from keeper
func contractAddress(codeID, instanceID uint64) sdk.AccAddress {
// 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.
contractID := codeID<<32 + instanceID
return addrFromUint64(contractID)
}
// addrFromUint64 is a helper for address generation, copied from keeper
func addrFromUint64(id uint64) sdk.AccAddress {
addr := make([]byte, 20)

View File

@@ -552,11 +552,11 @@ func TestGetAllContracts(t *testing.T) {
},
exp: []contractMeta{
{
ContractAddress: contractAddress(0, 1).String(),
ContractAddress: keeper.BuildContractAddress(0, 1).String(),
Info: types.ContractInfo{Label: "first"},
},
{
ContractAddress: contractAddress(0, 2).String(),
ContractAddress: keeper.BuildContractAddress(0, 2).String(),
Info: types.ContractInfo{Label: "second"},
},
},
@@ -572,7 +572,7 @@ func TestGetAllContracts(t *testing.T) {
},
exp: []contractMeta{
{
ContractAddress: contractAddress(0, 100).String(),
ContractAddress: keeper.BuildContractAddress(0, 100).String(),
Info: types.ContractInfo{Label: "hundred"},
},
},
@@ -598,7 +598,7 @@ func TestGetAllContracts(t *testing.T) {
Info: types.ContractInfo{Label: "first"},
},
{
ContractAddress: contractAddress(0, 100).String(),
ContractAddress: keeper.BuildContractAddress(0, 100).String(),
Info: types.ContractInfo{Label: "hundred"},
},
},

View File

@@ -260,7 +260,7 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
@@ -281,10 +281,10 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
}, {
ContractAddress: contractAddress(1, 2).String(),
ContractAddress: BuildContractAddress(1, 2).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
@@ -300,7 +300,7 @@ func TestGenesisInit(t *testing.T) {
src: types.GenesisState{
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
@@ -316,10 +316,10 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
}, {
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
@@ -335,7 +335,7 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractState: []types.Model{
{
@@ -383,7 +383,7 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1).String(),
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
@@ -595,7 +595,7 @@ func TestSupportedGenMsgTypes(t *testing.T) {
Sum: &types.GenesisState_GenMsgs_ExecuteContract{
ExecuteContract: &types.MsgExecuteContract{
Sender: verifierAddress.String(),
Contract: contractAddress(1, 1).String(),
Contract: BuildContractAddress(1, 1).String(),
Msg: []byte(`{"release":{}}`),
},
},
@@ -619,7 +619,7 @@ func TestSupportedGenMsgTypes(t *testing.T) {
require.NotNil(t, codeInfo)
// verify contract instantiated
cInfo := keeper.GetContractInfo(ctx, contractAddress(1, 1))
cInfo := keeper.GetContractInfo(ctx, BuildContractAddress(1, 1))
require.NotNil(t, cInfo)
// verify contract executed

View File

@@ -40,7 +40,7 @@ func TestBindingPortForIBCContractOnInstantiate(t *testing.T) {
}
func TestContractFromPortID(t *testing.T) {
contractAddr := contractAddress(1, 100)
contractAddr := BuildContractAddress(1, 100)
specs := map[string]struct {
srcPort string
expAddr sdk.AccAddress

View File

@@ -15,6 +15,7 @@ import (
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/log"
"math"
"path/filepath"
"time"
)
@@ -267,7 +268,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
info := types.NewInfo(creator, deposit)
// create prefixed data store
// 0x03 | contractAddress (sdk.AccAddress)
// 0x03 | BuildContractAddress (sdk.AccAddress)
prefixStoreKey := types.GetContractStorePrefix(contractAddress)
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
@@ -840,14 +841,16 @@ func consumeGas(ctx sdk.Context, gas uint64) {
// generates a contract address from codeID + instanceID
func (k Keeper) generateContractAddress(ctx sdk.Context, codeID uint64) sdk.AccAddress {
instanceID := k.autoIncrementID(ctx, types.KeyLastInstanceID)
return contractAddress(codeID, instanceID)
return BuildContractAddress(codeID, instanceID)
}
// contractAddress builds an sdk account address for a contract.
// Intentionally kept private as this is module internal logic.
func contractAddress(codeID, instanceID uint64) sdk.AccAddress {
// 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.
// 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 := codeID<<32 + instanceID
return addrFromUint64(contractID)
}

View File

@@ -9,6 +9,7 @@ import (
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"io/ioutil"
"math"
"testing"
"time"
@@ -1471,5 +1472,43 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) {
assert.Equal(t, spec.expData, gotData)
})
}
}
func TestBuildContractAddress(t *testing.T) {
specs := map[string]struct {
srcCodeID uint64
srcInstanceID uint64
expPanic bool
}{
"both empty": {},
"both below max": {
srcCodeID: math.MaxUint32 - 1,
srcInstanceID: math.MaxUint32 - 1,
},
"both at max": {
srcCodeID: math.MaxUint32,
srcInstanceID: math.MaxUint32,
},
"codeID > max": {
srcCodeID: math.MaxUint32 + 1,
expPanic: true,
},
"instanceID > max": {
srcInstanceID: math.MaxUint32 + 1,
expPanic: true,
},
}
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))
})
}
}

View File

@@ -134,7 +134,7 @@ func TestMigrateProposal(t *testing.T) {
var (
anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen)
otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen)
contractAddr = contractAddress(1, 1)
contractAddr = BuildContractAddress(1, 1)
)
contractInfoFixture := types.ContractInfoFixture(func(c *types.ContractInfo) {
@@ -194,7 +194,7 @@ func TestMigrateProposal(t *testing.T) {
func TestAdminProposals(t *testing.T) {
var (
otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen)
contractAddr = contractAddress(1, 1)
contractAddr = BuildContractAddress(1, 1)
)
wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

View File

@@ -152,7 +152,7 @@ func TestQuerySmartContractState(t *testing.T) {
func TestQuerySmartContractPanics(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures)
contractAddr := contractAddress(1, 1)
contractAddr := BuildContractAddress(1, 1)
keepers.WasmKeeper.storeCodeInfo(ctx, 1, types.CodeInfo{})
keepers.WasmKeeper.storeContractInfo(ctx, contractAddr, &types.ContractInfo{
CodeID: 1,