mirror of https://github.com/certusone/wasmd.git
Use prefix store for contract history
This commit is contained in:
parent
1c4d4d8f0e
commit
72a1a45030
|
@ -37,6 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
## [Unreleased]
|
||||
|
||||
### Features
|
||||
* (wasmd) [\#196](https://github.com/CosmWasm/wasmd/issues/196) Move history of contract code migrations to their own prefix store
|
||||
* (wasmd) [\#130](https://github.com/CosmWasm/wasmd/issues/130) Full history of contract code migrations
|
||||
* (wasmd) [\#187](https://github.com/CosmWasm/wasmd/issues/187) Introduce wasmgovd binary
|
||||
* (wasmd) [\#178](https://github.com/CosmWasm/wasmd/issues/178) Add cli support for wasm gov proposals
|
||||
|
|
|
@ -82,7 +82,6 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
|||
}
|
||||
// redact contract info
|
||||
contract.Created = nil
|
||||
contract.ContractCodeHistory = nil
|
||||
|
||||
genState.Contracts = append(genState.Contracts, types.Contract{
|
||||
ContractAddress: addr,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
|
@ -39,15 +40,18 @@ func TestGenesisExportImport(t *testing.T) {
|
|||
codeInfo types.CodeInfo
|
||||
contract types.ContractInfo
|
||||
stateModels []types.Model
|
||||
history []types.ContractCodeHistoryEntry
|
||||
)
|
||||
f.Fuzz(&codeInfo)
|
||||
f.Fuzz(&contract)
|
||||
f.Fuzz(&stateModels)
|
||||
f.NilChance(0).Fuzz(&history)
|
||||
codeID, err := srcKeeper.Create(srcCtx, codeInfo.Creator, wasmCode, codeInfo.Source, codeInfo.Builder, &codeInfo.InstantiateConfig)
|
||||
require.NoError(t, err)
|
||||
contract.CodeID = codeID
|
||||
contractAddr := srcKeeper.generateContractAddress(srcCtx, codeID)
|
||||
srcKeeper.setContractInfo(srcCtx, contractAddr, &contract)
|
||||
srcKeeper.appendToContractHistory(srcCtx, contractAddr, history...)
|
||||
srcKeeper.importContractState(srcCtx, contractAddr, stateModels)
|
||||
}
|
||||
var wasmParams types.Params
|
||||
|
@ -93,11 +97,17 @@ func TestGenesisExportImport(t *testing.T) {
|
|||
for i := 0; srcIT.Valid(); i++ {
|
||||
require.True(t, dstIT.Valid(), "[%s] destination DB has less elements than source. Missing: %s", srcStoreKeys[j].Name(), srcIT.Key())
|
||||
require.Equal(t, srcIT.Key(), dstIT.Key(), i)
|
||||
require.Equal(t, srcIT.Value(), dstIT.Value(), "[%s] element (%d): %s", srcStoreKeys[j].Name(), i, srcIT.Key())
|
||||
|
||||
isContractHistory := srcStoreKeys[j].Name() == types.StoreKey && bytes.HasPrefix(srcIT.Key(), types.ContractHistoryStorePrefix)
|
||||
if !isContractHistory { // only skip history entries because we know they are different
|
||||
require.Equal(t, srcIT.Value(), dstIT.Value(), "[%s] element (%d): %X", srcStoreKeys[j].Name(), i, srcIT.Key())
|
||||
}
|
||||
srcIT.Next()
|
||||
dstIT.Next()
|
||||
}
|
||||
require.False(t, dstIT.Valid())
|
||||
if !assert.False(t, dstIT.Valid()) {
|
||||
t.Fatalf("dest Iterator still has key :%X", dstIT.Key())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,53 +358,6 @@ func TestFailFastImport(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestExportShouldNotContainContractCodeHistory(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
|
||||
|
||||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
var (
|
||||
deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
creator = createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
anyAddr = make([]byte, sdk.AddrLen)
|
||||
)
|
||||
|
||||
firstCodeID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", &types.AllowEverybody)
|
||||
require.NoError(t, err)
|
||||
secondCodeID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", &types.AllowEverybody)
|
||||
require.NoError(t, err)
|
||||
initMsg := InitMsg{
|
||||
Verifier: anyAddr,
|
||||
Beneficiary: anyAddr,
|
||||
}
|
||||
initMsgBz, err := json.Marshal(initMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// create instance
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
contractAddr, err := keeper.Instantiate(ctx, firstCodeID, creator, creator, initMsgBz, "demo contract 1", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// and migrate to second code id
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
_, err = keeper.Migrate(ctx, contractAddr, creator, secondCodeID, initMsgBz)
|
||||
require.NoError(t, err)
|
||||
// and contract contains 2 history elements
|
||||
contractInfo := keeper.GetContractInfo(ctx, contractAddr)
|
||||
require.NotNil(t, contractInfo)
|
||||
require.Len(t, contractInfo.ContractCodeHistory, 2)
|
||||
// when exported
|
||||
state := ExportGenesis(ctx, keeper)
|
||||
require.NoError(t, state.ValidateBasic())
|
||||
require.Len(t, state.Contracts, 1)
|
||||
assert.Len(t, state.Contracts[0].ContractInfo.ContractCodeHistory, 0)
|
||||
assert.Nil(t, state.Contracts[0].ContractInfo.Created)
|
||||
}
|
||||
|
||||
func TestImportContractWithCodeHistoryReset(t *testing.T) {
|
||||
genesis := `
|
||||
{
|
||||
|
@ -482,14 +445,16 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
|
|||
Admin: adminAddr,
|
||||
Label: "ȀĴnZV芢毤",
|
||||
Created: &types.AbsoluteTxPosition{BlockHeight: 0, TxIndex: 0},
|
||||
ContractCodeHistory: []types.ContractCodeHistoryEntry{{
|
||||
Operation: types.GenesisContractCodeHistoryType,
|
||||
CodeID: 1,
|
||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expContractInfo, *gotContractInfo)
|
||||
|
||||
expHistory := []types.ContractCodeHistoryEntry{{
|
||||
Operation: types.GenesisContractCodeHistoryType,
|
||||
CodeID: 1,
|
||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expHistory, keeper.getContractHistory(ctx, contractAddr))
|
||||
}
|
||||
|
||||
func setupKeeper(t *testing.T) (Keeper, sdk.Context, []sdk.StoreKey, func()) {
|
||||
|
|
|
@ -242,9 +242,9 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
|
|||
|
||||
// persist instance
|
||||
createdAt := types.NewAbsoluteTxPosition(ctx)
|
||||
instance := types.NewContractInfo(codeID, creator, admin, initMsg, label, createdAt)
|
||||
instance := types.NewContractInfo(codeID, creator, admin, label, createdAt)
|
||||
store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshalBinaryBare(instance))
|
||||
|
||||
k.appendToContractHistory(ctx, contractAddress, instance.InitialHistory(initMsg))
|
||||
return contractAddress, nil
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,8 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
|
|||
events := types.ParseEvents(res.Log, contractAddress)
|
||||
ctx.EventManager().EmitEvents(events)
|
||||
|
||||
contractInfo.AddMigration(ctx, newCodeID, msg)
|
||||
historyEntry := contractInfo.AddMigration(ctx, newCodeID, msg)
|
||||
k.appendToContractHistory(ctx, contractAddress, historyEntry)
|
||||
k.setContractInfo(ctx, contractAddress, contractInfo)
|
||||
|
||||
if err := k.dispatchMessages(ctx, contractAddress, res.Messages); err != nil {
|
||||
|
@ -376,6 +377,27 @@ func (k Keeper) setContractAdmin(ctx sdk.Context, contractAddress, caller, newAd
|
|||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) appendToContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, newEntries ...types.ContractCodeHistoryEntry) {
|
||||
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.ContractHistoryStorePrefix)
|
||||
var entries []types.ContractCodeHistoryEntry
|
||||
bz := prefixStore.Get(contractAddr)
|
||||
if bz != nil {
|
||||
k.cdc.MustUnmarshalBinaryBare(bz, &entries)
|
||||
}
|
||||
entries = append(entries, newEntries...)
|
||||
prefixStore.Set(contractAddr, k.cdc.MustMarshalBinaryBare(&entries))
|
||||
}
|
||||
|
||||
func (k Keeper) getContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress) []types.ContractCodeHistoryEntry {
|
||||
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.ContractHistoryStorePrefix)
|
||||
var entries []types.ContractCodeHistoryEntry
|
||||
bz := prefixStore.Get(contractAddr)
|
||||
if bz != nil {
|
||||
k.cdc.MustUnmarshalBinaryBare(bz, &entries)
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
// QuerySmart queries the smart contract itself.
|
||||
func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) {
|
||||
ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: query")
|
||||
|
@ -613,17 +635,18 @@ func (k Keeper) importAutoIncrementID(ctx sdk.Context, lastIDKey []byte, val uin
|
|||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) importContract(ctx sdk.Context, address sdk.AccAddress, c *types.ContractInfo, state []types.Model) error {
|
||||
func (k Keeper) importContract(ctx sdk.Context, contractAddr sdk.AccAddress, c *types.ContractInfo, state []types.Model) error {
|
||||
if !k.containsCodeInfo(ctx, c.CodeID) {
|
||||
return errors.Wrapf(types.ErrNotFound, "code id: %d", c.CodeID)
|
||||
}
|
||||
if k.containsContractInfo(ctx, address) {
|
||||
return errors.Wrapf(types.ErrDuplicate, "contract: %s", address)
|
||||
if k.containsContractInfo(ctx, contractAddr) {
|
||||
return errors.Wrapf(types.ErrDuplicate, "contract: %s", contractAddr)
|
||||
}
|
||||
|
||||
c.ResetFromGenesis(ctx)
|
||||
k.setContractInfo(ctx, address, c)
|
||||
return k.importContractState(ctx, address, state)
|
||||
historyEntry := c.ResetFromGenesis(ctx)
|
||||
k.appendToContractHistory(ctx, contractAddr, historyEntry)
|
||||
k.setContractInfo(ctx, contractAddr, c)
|
||||
return k.importContractState(ctx, contractAddr, state)
|
||||
}
|
||||
|
||||
func addrFromUint64(id uint64) sdk.AccAddress {
|
||||
|
|
|
@ -285,7 +285,7 @@ func TestInstantiate(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", nil)
|
||||
codeID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -301,28 +301,27 @@ func TestInstantiate(t *testing.T) {
|
|||
gasBefore := ctx.GasMeter().GasConsumed()
|
||||
|
||||
// create with no balance is also legal
|
||||
addr, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 1", nil)
|
||||
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, "demo contract 1", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
|
||||
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", contractAddr.String())
|
||||
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x1175b), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x12313), gasAfter-gasBefore)
|
||||
|
||||
// ensure it is stored properly
|
||||
info := keeper.GetContractInfo(ctx, addr)
|
||||
info := keeper.GetContractInfo(ctx, contractAddr)
|
||||
require.NotNil(t, info)
|
||||
assert.Equal(t, info.Creator, creator)
|
||||
assert.Equal(t, info.CodeID, contractID)
|
||||
assert.Equal(t, info.CodeID, codeID)
|
||||
assert.Equal(t, info.Label, "demo contract 1")
|
||||
|
||||
exp := []types.ContractCodeHistoryEntry{{
|
||||
Operation: types.InitContractCodeHistoryType,
|
||||
CodeID: contractID,
|
||||
CodeID: codeID,
|
||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
Msg: json.RawMessage(initMsgBz),
|
||||
}}
|
||||
assert.Equal(t, exp, info.ContractCodeHistory)
|
||||
|
||||
assert.Equal(t, exp, keeper.getContractHistory(ctx, contractAddr))
|
||||
}
|
||||
|
||||
func TestInstantiateWithDeposit(t *testing.T) {
|
||||
|
@ -535,7 +534,7 @@ func TestExecute(t *testing.T) {
|
|||
|
||||
// make sure gas is properly deducted from ctx
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x11c49), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x11aa2), gasAfter-gasBefore)
|
||||
|
||||
// ensure bob now exists and got both payments released
|
||||
bobAcct = accKeeper.GetAccount(ctx, bob)
|
||||
|
@ -873,17 +872,17 @@ func TestMigrate(t *testing.T) {
|
|||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
addr, err := keeper.Instantiate(ctx, originalCodeID, creator, spec.admin, initMsgBz, "demo contract", nil)
|
||||
contractAddr, err := keeper.Instantiate(ctx, originalCodeID, creator, spec.admin, initMsgBz, "demo contract", nil)
|
||||
require.NoError(t, err)
|
||||
if spec.overrideContractAddr != nil {
|
||||
addr = spec.overrideContractAddr
|
||||
contractAddr = spec.overrideContractAddr
|
||||
}
|
||||
_, err = keeper.Migrate(ctx, addr, spec.caller, spec.codeID, spec.migrateMsg)
|
||||
_, err = keeper.Migrate(ctx, contractAddr, 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
|
||||
}
|
||||
cInfo := keeper.GetContractInfo(ctx, addr)
|
||||
cInfo := keeper.GetContractInfo(ctx, contractAddr)
|
||||
assert.Equal(t, spec.codeID, cInfo.CodeID)
|
||||
|
||||
expHistory := []types.ContractCodeHistoryEntry{{
|
||||
|
@ -897,9 +896,9 @@ func TestMigrate(t *testing.T) {
|
|||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
Msg: spec.migrateMsg,
|
||||
}}
|
||||
assert.Equal(t, expHistory, cInfo.ContractCodeHistory)
|
||||
assert.Equal(t, expHistory, keeper.getContractHistory(ctx, contractAddr))
|
||||
|
||||
m := keeper.QueryRaw(ctx, addr, []byte("config"))
|
||||
m := keeper.QueryRaw(ctx, contractAddr, []byte("config"))
|
||||
require.Len(t, m, 1)
|
||||
var stored map[string][]byte
|
||||
require.NoError(t, json.Unmarshal(m[0].Value, &stored))
|
||||
|
|
|
@ -110,8 +110,7 @@ func TestInstantiateProposal(t *testing.T) {
|
|||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
Msg: src.InitMsg,
|
||||
}}
|
||||
assert.Equal(t, expHistory, cInfo.ContractCodeHistory)
|
||||
|
||||
assert.Equal(t, expHistory, wasmKeeper.getContractHistory(ctx, contractAddr))
|
||||
}
|
||||
|
||||
func TestMigrateProposal(t *testing.T) {
|
||||
|
@ -188,7 +187,7 @@ func TestMigrateProposal(t *testing.T) {
|
|||
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||
Msg: src.MigrateMsg,
|
||||
}}
|
||||
assert.Equal(t, expHistory, cInfo.ContractCodeHistory)
|
||||
assert.Equal(t, expHistory, wasmKeeper.getContractHistory(ctx, contractAddr))
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -84,10 +84,6 @@ func queryContractInfo(ctx sdk.Context, bech string, req abci.RequestQuery, keep
|
|||
// redact clears all fields not in the public api
|
||||
func redact(info *types.ContractInfo) {
|
||||
info.Created = nil
|
||||
for i := range info.ContractCodeHistory {
|
||||
info.ContractCodeHistory[i].Updated = nil
|
||||
info.ContractCodeHistory[i].Msg = nil
|
||||
}
|
||||
}
|
||||
|
||||
func queryContractListByCode(ctx sdk.Context, codeIDstr string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
|
||||
|
|
|
@ -214,9 +214,5 @@ func TestListContractByCodeOrdering(t *testing.T) {
|
|||
assert.NotEmpty(t, contract.Address)
|
||||
// ensure these are not shown
|
||||
assert.Nil(t, contract.Created)
|
||||
for _, entry := range contract.ContractCodeHistory {
|
||||
assert.Nil(t, entry.Updated)
|
||||
assert.Nil(t, entry.Msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,6 @@ func FuzzContractInfo(m *types.ContractInfo, c fuzz.Continue) {
|
|||
FuzzAddr(&m.Admin, c)
|
||||
m.Label = c.RandString()
|
||||
c.Fuzz(&m.Created)
|
||||
historyElements := c.Int() % 128 // 128 should be enough for tests
|
||||
m.ContractCodeHistory = make([]types.ContractCodeHistoryEntry, historyElements)
|
||||
for i := range m.ContractCodeHistory {
|
||||
c.Fuzz(&m.ContractCodeHistory[i])
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzContractCodeHistory(m *types.ContractCodeHistoryEntry, c fuzz.Continue) {
|
||||
|
|
|
@ -86,9 +86,6 @@ func (c Contract) ValidateBasic() error {
|
|||
if c.ContractInfo.Created != nil {
|
||||
return sdkerrors.Wrap(ErrInvalid, "created must be empty")
|
||||
}
|
||||
if len(c.ContractInfo.ContractCodeHistory) != 0 {
|
||||
return sdkerrors.Wrap(ErrInvalid, "history must be empty")
|
||||
}
|
||||
for i := range c.ContractState {
|
||||
if err := c.ContractState[i].ValidateBasic(); err != nil {
|
||||
return sdkerrors.Wrapf(err, "contract state %d", i)
|
||||
|
|
|
@ -127,12 +127,6 @@ func TestContractValidateBasic(t *testing.T) {
|
|||
},
|
||||
expError: true,
|
||||
},
|
||||
"contract with history set": {
|
||||
srcMutator: func(c *Contract) {
|
||||
c.ContractInfo.ContractCodeHistory = []ContractCodeHistoryEntry{{}}
|
||||
},
|
||||
expError: true,
|
||||
},
|
||||
"contract state invalid": {
|
||||
srcMutator: func(c *Contract) {
|
||||
c.ContractState = append(c.ContractState, Model{})
|
||||
|
|
|
@ -31,12 +31,14 @@ const ( // event attributes
|
|||
|
||||
// nolint
|
||||
var (
|
||||
KeyLastCodeID = []byte("lastCodeId")
|
||||
KeyLastInstanceID = []byte("lastContractId")
|
||||
CodeKeyPrefix = []byte{0x01}
|
||||
ContractKeyPrefix = []byte{0x02}
|
||||
ContractStorePrefix = []byte{0x03}
|
||||
SequenceKeyPrefix = []byte{0x04}
|
||||
ContractHistoryStorePrefix = []byte{0x05}
|
||||
|
||||
CodeKeyPrefix = []byte{0x01}
|
||||
ContractKeyPrefix = []byte{0x02}
|
||||
ContractStorePrefix = []byte{0x03}
|
||||
KeyLastCodeID = append(SequenceKeyPrefix, []byte("lastCodeId")...)
|
||||
KeyLastInstanceID = append(SequenceKeyPrefix, []byte("lastContractId")...)
|
||||
)
|
||||
|
||||
// GetCodeKey constructs the key for retreiving the ID for the WASM code
|
||||
|
|
|
@ -88,7 +88,6 @@ func ContractFixture(mutators ...func(*Contract)) Contract {
|
|||
|
||||
func OnlyGenesisFields(info *ContractInfo) {
|
||||
info.Created = nil
|
||||
info.ContractCodeHistory = nil
|
||||
}
|
||||
|
||||
func ContractInfoFixture(mutators ...func(*ContractInfo)) ContractInfo {
|
||||
|
|
|
@ -2,7 +2,6 @@ package types
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
tmBytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
|
@ -93,24 +92,19 @@ type ContractInfo struct {
|
|||
Label string `json:"label"`
|
||||
// never show this in query results, just use for sorting
|
||||
// (Note: when using json tag "-" amino refused to serialize it...)
|
||||
Created *AbsoluteTxPosition `json:"created,omitempty"`
|
||||
ContractCodeHistory []ContractCodeHistoryEntry `json:"contract_code_history,omitempty"`
|
||||
Created *AbsoluteTxPosition `json:"created,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ContractInfo) AddMigration(ctx sdk.Context, codeID uint64, msg []byte) {
|
||||
h := ContractCodeHistoryEntry{
|
||||
Operation: MigrateContractCodeHistoryType,
|
||||
CodeID: codeID,
|
||||
Updated: NewAbsoluteTxPosition(ctx),
|
||||
Msg: msg,
|
||||
// NewContractInfo creates a new instance of a given WASM contract info
|
||||
func NewContractInfo(codeID uint64, creator, admin sdk.AccAddress, label string, createdAt *AbsoluteTxPosition) ContractInfo {
|
||||
return ContractInfo{
|
||||
CodeID: codeID,
|
||||
Creator: creator,
|
||||
Admin: admin,
|
||||
Label: label,
|
||||
Created: createdAt,
|
||||
}
|
||||
c.ContractCodeHistory = append(c.ContractCodeHistory, h)
|
||||
sort.Slice(c.ContractCodeHistory, func(i, j int) bool {
|
||||
return c.ContractCodeHistory[i].Updated.LessThan(c.ContractCodeHistory[j].Updated)
|
||||
})
|
||||
c.CodeID = codeID
|
||||
}
|
||||
|
||||
func (c *ContractInfo) ValidateBasic() error {
|
||||
if c.CodeID == 0 {
|
||||
return sdkerrors.Wrap(ErrEmpty, "code id")
|
||||
|
@ -129,15 +123,34 @@ func (c *ContractInfo) ValidateBasic() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ResetFromGenesis resets contracts timestamp and history.
|
||||
func (c *ContractInfo) ResetFromGenesis(ctx sdk.Context) {
|
||||
c.Created = NewAbsoluteTxPosition(ctx)
|
||||
func (c ContractInfo) InitialHistory(initMsg []byte) ContractCodeHistoryEntry {
|
||||
return ContractCodeHistoryEntry{
|
||||
Operation: InitContractCodeHistoryType,
|
||||
CodeID: c.CodeID,
|
||||
Updated: c.Created,
|
||||
Msg: initMsg,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ContractInfo) AddMigration(ctx sdk.Context, codeID uint64, msg []byte) ContractCodeHistoryEntry {
|
||||
h := ContractCodeHistoryEntry{
|
||||
Operation: MigrateContractCodeHistoryType,
|
||||
CodeID: codeID,
|
||||
Updated: NewAbsoluteTxPosition(ctx),
|
||||
Msg: msg,
|
||||
}
|
||||
c.CodeID = codeID
|
||||
return h
|
||||
}
|
||||
|
||||
// ResetFromGenesis resets contracts timestamp and history.
|
||||
func (c *ContractInfo) ResetFromGenesis(ctx sdk.Context) ContractCodeHistoryEntry {
|
||||
c.Created = NewAbsoluteTxPosition(ctx)
|
||||
return ContractCodeHistoryEntry{
|
||||
Operation: GenesisContractCodeHistoryType,
|
||||
CodeID: c.CodeID,
|
||||
Updated: c.Created,
|
||||
}
|
||||
c.ContractCodeHistory = []ContractCodeHistoryEntry{h}
|
||||
}
|
||||
|
||||
// AbsoluteTxPosition can be used to sort contracts
|
||||
|
@ -173,23 +186,6 @@ func NewAbsoluteTxPosition(ctx sdk.Context) *AbsoluteTxPosition {
|
|||
}
|
||||
}
|
||||
|
||||
// NewContractInfo creates a new instance of a given WASM contract info
|
||||
func NewContractInfo(codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, createdAt *AbsoluteTxPosition) ContractInfo {
|
||||
return ContractInfo{
|
||||
CodeID: codeID,
|
||||
Creator: creator,
|
||||
Admin: admin,
|
||||
Label: label,
|
||||
Created: createdAt,
|
||||
ContractCodeHistory: []ContractCodeHistoryEntry{{
|
||||
Operation: InitContractCodeHistoryType,
|
||||
CodeID: codeID,
|
||||
Updated: createdAt,
|
||||
Msg: initMsg,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// NewEnv initializes the environment for a contract instance
|
||||
func NewEnv(ctx sdk.Context, creator sdk.AccAddress, deposit sdk.Coins, contractAddr sdk.AccAddress) wasmTypes.Env {
|
||||
// safety checks before casting below
|
||||
|
|
Loading…
Reference in New Issue