diff --git a/go.mod b/go.mod index 94b85b615..b83823401 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/CosmWasm/wasmd -go 1.24.0 +go 1.25.3 require ( github.com/CosmWasm/wasmvm/v3 v3.0.2 diff --git a/x/wasm/keeper/genesis_exports.go b/x/wasm/keeper/genesis_exports.go new file mode 100644 index 000000000..af9cb8f50 --- /dev/null +++ b/x/wasm/keeper/genesis_exports.go @@ -0,0 +1,33 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/CosmWasm/wasmd/x/wasm/types" +) + +// Genesis-specific exports for custom genesis tooling and external integrations. +// These wrap private keeper methods to enable external packages to perform +// genesis operations and state management. +// +// ImportCode wraps the private importCode method to allow external packages +// to import compiled Wasm code during genesis or state migrations. +func (k Keeper) ImportCode(ctx context.Context, codeID uint64, codeInfo types.CodeInfo, wasmCode []byte) error { + return k.importCode(ctx, codeID, codeInfo, wasmCode) +} + +// ImportContract wraps the private importContract method to allow external packages +// to import complete contract instances with their state and history during genesis. +// +// This uses the optimized appendToContractHistoryForGenesis internally for performance. +func (k Keeper) ImportContract(ctx context.Context, contractAddr sdk.AccAddress, c *types.ContractInfo, state []types.Model, historyEntries []types.ContractCodeHistoryEntry) error { + return k.importContract(ctx, contractAddr, c, state, historyEntries) +} + +// ImportAutoIncrementID wraps the private importAutoIncrementID method to allow +// external packages to set sequence counters for ID generation during genesis import. +func (k Keeper) ImportAutoIncrementID(ctx context.Context, sequenceKey []byte, val uint64) error { + return k.importAutoIncrementID(ctx, sequenceKey, val) +} diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 3e9f6c382..b119cbbd1 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -823,6 +823,26 @@ func (k Keeper) appendToContractHistory(ctx context.Context, contractAddr sdk.Ac return nil } +// appendToContractHistoryForGenesis is optimized for genesis import where +// contract history is known to be empty. It writes entries sequentially starting +// from position 0 without checking for existing entries. +// +// WARNING: Only use during genesis import via importContract(). For runtime operations, +// use appendToContractHistory() which safely handles existing history. +// +// Performance: Avoids O(N) iteration over existing entries when state is known to be empty. +// This provides significant speedup during genesis import with many contracts. +func (k Keeper) appendToContractHistoryForGenesis(ctx context.Context, contractAddr sdk.AccAddress, newEntries ...types.ContractCodeHistoryEntry) error { + store := k.storeService.OpenKVStore(ctx) + for pos, e := range newEntries { + key := types.GetContractCodeHistoryElementKey(contractAddr, uint64(pos)) + if err := store.Set(key, k.cdc.MustMarshal(&e)); err != nil { + return err + } + } + return nil +} + func (k Keeper) GetContractHistory(ctx context.Context, contractAddr sdk.AccAddress) []types.ContractCodeHistoryEntry { prefixStore := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.GetContractCodeHistoryElementPrefix(contractAddr)) r := make([]types.ContractCodeHistoryEntry, 0) @@ -1413,6 +1433,8 @@ func (k Keeper) importAutoIncrementID(ctx context.Context, sequenceKey []byte, v return store.Set(sequenceKey, bz) } +// importContract imports a contract instance during genesis initialization. +// Uses the optimized appendToContractHistoryForGenesis since contract history is known to be empty. func (k Keeper) importContract(ctx context.Context, contractAddr sdk.AccAddress, c *types.ContractInfo, state []types.Model, historyEntries []types.ContractCodeHistoryEntry) error { if !k.containsCodeInfo(ctx, c.CodeID) { return types.ErrNoSuchCodeFn(c.CodeID).Wrapf("code id %d", c.CodeID) @@ -1429,7 +1451,7 @@ func (k Keeper) importContract(ctx context.Context, contractAddr sdk.AccAddress, return err } - err = k.appendToContractHistory(ctx, contractAddr, historyEntries...) + err = k.appendToContractHistoryForGenesis(ctx, contractAddr, historyEntries...) if err != nil { return err }