Allow access to contract address builder
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user