mirror of https://github.com/certusone/wasmd.git
Add contract history query handler
This commit is contained in:
parent
72a1a45030
commit
00adcb4a58
|
@ -454,7 +454,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
|
||||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.Equal(t, expHistory, keeper.getContractHistory(ctx, contractAddr))
|
assert.Equal(t, expHistory, keeper.GetContractHistory(ctx, contractAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupKeeper(t *testing.T) (Keeper, sdk.Context, []sdk.StoreKey, func()) {
|
func setupKeeper(t *testing.T) (Keeper, sdk.Context, []sdk.StoreKey, func()) {
|
||||||
|
|
|
@ -388,7 +388,7 @@ func (k Keeper) appendToContractHistory(ctx sdk.Context, contractAddr sdk.AccAdd
|
||||||
prefixStore.Set(contractAddr, k.cdc.MustMarshalBinaryBare(&entries))
|
prefixStore.Set(contractAddr, k.cdc.MustMarshalBinaryBare(&entries))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Keeper) getContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress) []types.ContractCodeHistoryEntry {
|
func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress) []types.ContractCodeHistoryEntry {
|
||||||
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.ContractHistoryStorePrefix)
|
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.ContractHistoryStorePrefix)
|
||||||
var entries []types.ContractCodeHistoryEntry
|
var entries []types.ContractCodeHistoryEntry
|
||||||
bz := prefixStore.Get(contractAddr)
|
bz := prefixStore.Get(contractAddr)
|
||||||
|
|
|
@ -321,7 +321,7 @@ func TestInstantiate(t *testing.T) {
|
||||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
Msg: json.RawMessage(initMsgBz),
|
Msg: json.RawMessage(initMsgBz),
|
||||||
}}
|
}}
|
||||||
assert.Equal(t, exp, keeper.getContractHistory(ctx, contractAddr))
|
assert.Equal(t, exp, keeper.GetContractHistory(ctx, contractAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstantiateWithDeposit(t *testing.T) {
|
func TestInstantiateWithDeposit(t *testing.T) {
|
||||||
|
@ -896,7 +896,7 @@ func TestMigrate(t *testing.T) {
|
||||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
Msg: spec.migrateMsg,
|
Msg: spec.migrateMsg,
|
||||||
}}
|
}}
|
||||||
assert.Equal(t, expHistory, keeper.getContractHistory(ctx, contractAddr))
|
assert.Equal(t, expHistory, keeper.GetContractHistory(ctx, contractAddr))
|
||||||
|
|
||||||
m := keeper.QueryRaw(ctx, contractAddr, []byte("config"))
|
m := keeper.QueryRaw(ctx, contractAddr, []byte("config"))
|
||||||
require.Len(t, m, 1)
|
require.Len(t, m, 1)
|
||||||
|
|
|
@ -110,7 +110,7 @@ func TestInstantiateProposal(t *testing.T) {
|
||||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
Msg: src.InitMsg,
|
Msg: src.InitMsg,
|
||||||
}}
|
}}
|
||||||
assert.Equal(t, expHistory, wasmKeeper.getContractHistory(ctx, contractAddr))
|
assert.Equal(t, expHistory, wasmKeeper.GetContractHistory(ctx, contractAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateProposal(t *testing.T) {
|
func TestMigrateProposal(t *testing.T) {
|
||||||
|
@ -187,7 +187,7 @@ func TestMigrateProposal(t *testing.T) {
|
||||||
Updated: types.NewAbsoluteTxPosition(ctx),
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
Msg: src.MigrateMsg,
|
Msg: src.MigrateMsg,
|
||||||
}}
|
}}
|
||||||
assert.Equal(t, expHistory, wasmKeeper.getContractHistory(ctx, contractAddr))
|
assert.Equal(t, expHistory, wasmKeeper.GetContractHistory(ctx, contractAddr))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ const (
|
||||||
QueryGetContractState = "contract-state"
|
QueryGetContractState = "contract-state"
|
||||||
QueryGetCode = "code"
|
QueryGetCode = "code"
|
||||||
QueryListCode = "list-code"
|
QueryListCode = "list-code"
|
||||||
|
QueryContractHistory = "contract-history"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -54,6 +55,8 @@ func NewQuerier(keeper Keeper) sdk.Querier {
|
||||||
return queryCode(ctx, path[1], req, keeper)
|
return queryCode(ctx, path[1], req, keeper)
|
||||||
case QueryListCode:
|
case QueryListCode:
|
||||||
return queryCodeList(ctx, req, keeper)
|
return queryCodeList(ctx, req, keeper)
|
||||||
|
case QueryContractHistory:
|
||||||
|
return queryContractHistory(ctx, path[1], keeper)
|
||||||
default:
|
default:
|
||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint")
|
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint")
|
||||||
}
|
}
|
||||||
|
@ -226,3 +229,26 @@ func queryCodeList(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byt
|
||||||
}
|
}
|
||||||
return bz, nil
|
return bz, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func queryContractHistory(ctx sdk.Context, bech string, keeper Keeper) ([]byte, error) {
|
||||||
|
contractAddr, err := sdk.AccAddressFromBech32(bech)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, err.Error())
|
||||||
|
}
|
||||||
|
entries := keeper.GetContractHistory(ctx, contractAddr)
|
||||||
|
if entries == nil {
|
||||||
|
// nil, nil leads to 404 in rest handler
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// redact response
|
||||||
|
for i := range entries {
|
||||||
|
entries[i].Updated = nil
|
||||||
|
entries[i].Msg = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := json.MarshalIndent(entries, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -216,3 +217,100 @@ func TestListContractByCodeOrdering(t *testing.T) {
|
||||||
assert.Nil(t, contract.Created)
|
assert.Nil(t, contract.Created)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQueryContractHistory(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)
|
||||||
|
keeper := keepers.WasmKeeper
|
||||||
|
|
||||||
|
var (
|
||||||
|
otherAddr sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen)
|
||||||
|
)
|
||||||
|
|
||||||
|
specs := map[string]struct {
|
||||||
|
srcQueryAddr sdk.AccAddress
|
||||||
|
srcHistory []types.ContractCodeHistoryEntry
|
||||||
|
expContent []types.ContractCodeHistoryEntry
|
||||||
|
}{
|
||||||
|
"response with internal fields cleared": {
|
||||||
|
srcHistory: []types.ContractCodeHistoryEntry{{
|
||||||
|
Operation: types.GenesisContractCodeHistoryType,
|
||||||
|
CodeID: 1,
|
||||||
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
|
Msg: []byte(`"init message"`),
|
||||||
|
}},
|
||||||
|
expContent: []types.ContractCodeHistoryEntry{{
|
||||||
|
Operation: types.GenesisContractCodeHistoryType,
|
||||||
|
CodeID: 1,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"response with multiple entries": {
|
||||||
|
srcHistory: []types.ContractCodeHistoryEntry{{
|
||||||
|
Operation: types.InitContractCodeHistoryType,
|
||||||
|
CodeID: 1,
|
||||||
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
|
Msg: []byte(`"init message"`),
|
||||||
|
}, {
|
||||||
|
Operation: types.MigrateContractCodeHistoryType,
|
||||||
|
CodeID: 2,
|
||||||
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
|
Msg: []byte(`"migrate message 1"`),
|
||||||
|
}, {
|
||||||
|
Operation: types.MigrateContractCodeHistoryType,
|
||||||
|
CodeID: 3,
|
||||||
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
|
Msg: []byte(`"migrate message 2"`),
|
||||||
|
}},
|
||||||
|
expContent: []types.ContractCodeHistoryEntry{{
|
||||||
|
Operation: types.InitContractCodeHistoryType,
|
||||||
|
CodeID: 1,
|
||||||
|
}, {
|
||||||
|
Operation: types.MigrateContractCodeHistoryType,
|
||||||
|
CodeID: 2,
|
||||||
|
}, {
|
||||||
|
Operation: types.MigrateContractCodeHistoryType,
|
||||||
|
CodeID: 3,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"unknown contract address": {
|
||||||
|
srcQueryAddr: otherAddr,
|
||||||
|
srcHistory: []types.ContractCodeHistoryEntry{{
|
||||||
|
Operation: types.GenesisContractCodeHistoryType,
|
||||||
|
CodeID: 1,
|
||||||
|
Updated: types.NewAbsoluteTxPosition(ctx),
|
||||||
|
Msg: []byte(`"init message"`),
|
||||||
|
}},
|
||||||
|
expContent: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for msg, spec := range specs {
|
||||||
|
t.Run(msg, func(t *testing.T) {
|
||||||
|
_, _, myContractAddr := keyPubAddr()
|
||||||
|
keeper.appendToContractHistory(ctx, myContractAddr, spec.srcHistory...)
|
||||||
|
q := NewQuerier(keeper)
|
||||||
|
queryContractAddr := spec.srcQueryAddr
|
||||||
|
if queryContractAddr == nil {
|
||||||
|
queryContractAddr = myContractAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
query := []string{QueryContractHistory, queryContractAddr.String()}
|
||||||
|
data := abci.RequestQuery{}
|
||||||
|
resData, err := q(ctx, query, data)
|
||||||
|
|
||||||
|
// then
|
||||||
|
require.NoError(t, err)
|
||||||
|
if spec.expContent == nil {
|
||||||
|
require.Nil(t, resData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var got []types.ContractCodeHistoryEntry
|
||||||
|
err = json.Unmarshal(resData, &got)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, spec.expContent, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue