Test and fix the sorting and redacting of created at

This commit is contained in:
Ethan Frey 2020-02-27 19:05:40 +01:00
parent 4a2ee1ab9a
commit 340fa4c5b2
6 changed files with 102 additions and 11 deletions

View File

@ -151,9 +151,8 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddre
}
// persist instance
instance := types.NewContractInfo(codeID, creator, initMsg, label, types.NewCreatedAt(ctx))
// 0x02 | contractAddress (sdk.AccAddress) -> Instance
createdAt := types.NewCreatedAt(ctx)
instance := types.NewContractInfo(codeID, creator, initMsg, label, createdAt)
store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshalBinaryBare(instance))
return contractAddress, nil

View File

@ -151,7 +151,7 @@ func TestInstantiate(t *testing.T) {
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
gasAfter := ctx.GasMeter().GasConsumed()
require.Equal(t, uint64(24763), gasAfter-gasBefore)
require.Equal(t, uint64(24823), gasAfter-gasBefore)
// ensure it is stored properly
info := keeper.GetContractInfo(ctx, addr)
@ -244,7 +244,7 @@ func TestExecute(t *testing.T) {
// make sure gas is properly deducted from ctx
gasAfter := ctx.GasMeter().GasConsumed()
require.Equal(t, uint64(31156), gasAfter-gasBefore)
require.Equal(t, uint64(31162), gasAfter-gasBefore)
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)

View File

@ -2,6 +2,7 @@ package keeper
import (
"encoding/json"
"sort"
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -100,6 +101,16 @@ func queryContractListByCode(ctx sdk.Context, codeIDstr string, req abci.Request
}
return false
})
// now we sort them by CreatedAt
sort.Slice(contracts, func(i, j int) bool {
return contracts[i].ContractInfo.Created.LessThan(contracts[j].ContractInfo.Created)
})
// and remove that info for the final json (yes, the json:"-" tag doesn't work)
for i := range contracts {
contracts[i].Created = nil
}
bz, err := json.MarshalIndent(contracts, "", " ")
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())

View File

@ -2,6 +2,7 @@ package keeper
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"testing"
@ -141,3 +142,71 @@ func TestQueryContractState(t *testing.T) {
})
}
}
func TestListContractByCodeOrdering(t *testing.T) {
tempDir, err := ioutil.TempDir("", "wasm")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
ctx, accKeeper, keeper := CreateTestInput(t, false, tempDir)
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 500))
creator := createFakeFundedAccount(ctx, accKeeper, deposit)
anyAddr := createFakeFundedAccount(ctx, accKeeper, topUp)
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
require.NoError(t, err)
codeID, err := keeper.Create(ctx, creator, wasmCode, "", "")
require.NoError(t, err)
_, _, bob := keyPubAddr()
initMsg := InitMsg{
Verifier: anyAddr,
Beneficiary: bob,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
// manage some realistic block settings
var h int64 = 10
setBlock := func(ctx sdk.Context, height int64) sdk.Context {
ctx = ctx.WithBlockHeight(height)
meter := sdk.NewGasMeter(1000000)
ctx = ctx.WithGasMeter(meter)
ctx = ctx.WithBlockGasMeter(meter)
return ctx
}
// create 10 contracts with real block/gas setup
for i := range [10]int{} {
// 3 tx per block, so we ensure both comparisons work
if i%3 == 0 {
ctx = setBlock(ctx, h)
h++
}
_, err = keeper.Instantiate(ctx, codeID, creator, initMsgBz, fmt.Sprintf("contract %d", i), topUp)
require.NoError(t, err)
}
// query and check the results are properly sorted
q := NewQuerier(keeper)
query := []string{QueryListContractByCode, fmt.Sprintf("%d", codeID)}
data := abci.RequestQuery{}
res, err := q(ctx, query, data)
require.NoError(t, err)
var contracts []ContractInfoWithAddress
err = json.Unmarshal(res, &contracts)
require.NoError(t, err)
require.Equal(t, 10, len(contracts))
for i, contract := range contracts {
assert.Equal(t, fmt.Sprintf("contract %d", i), contract.Label)
assert.NotEmpty(t, contract.Address)
// ensure these are not shown
assert.Nil(t, contract.InitMsg)
assert.Nil(t, contract.Created)
}
}

View File

@ -93,7 +93,7 @@ type MsgInstantiateContract struct {
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
Code uint64 `json:"code_id" yaml:"code_id"`
Label string `json:"label" yaml:"label"`
InitMsg json.RawMessage `json:"init_msg,omitempty" yaml:"init_msg"`
InitMsg json.RawMessage `json:"init_msg" yaml:"init_msg"`
InitFunds sdk.Coins `json:"init_funds" yaml:"init_funds"`
}

View File

@ -44,9 +44,10 @@ type ContractInfo struct {
CodeID uint64 `json:"code_id"`
Creator sdk.AccAddress `json:"creator"`
Label string `json:"label"`
InitMsg json.RawMessage `json:"init_msg"`
InitMsg json.RawMessage `json:"init_msg,omitempty"`
// never show this in query results, just use for sorting
Created CreatedAt `json:"-"`
// (Note: when using json tag "-" amino refused to serialize it...)
Created *CreatedAt `json:"created,omitempty"`
}
// CreatedAt can be used to sort contracts
@ -57,22 +58,33 @@ type CreatedAt struct {
TxIndex uint64
}
// LessThan can be used to sort
func (a *CreatedAt) LessThan(b *CreatedAt) bool {
if a == nil {
return true
}
if b == nil {
return false
}
return a.BlockHeight < b.BlockHeight || (a.BlockHeight == b.BlockHeight && a.TxIndex < b.TxIndex)
}
// NewCreatedAt gets a timestamp from the context
func NewCreatedAt(ctx sdk.Context) CreatedAt {
func NewCreatedAt(ctx sdk.Context) *CreatedAt {
// we must safely handle nil gas meters
var index uint64
meter := ctx.BlockGasMeter()
if meter != nil {
index = meter.GasConsumed()
}
return CreatedAt{
return &CreatedAt{
BlockHeight: ctx.BlockHeight(),
TxIndex: index,
}
}
// NewContractInfo creates a new instance of a given WASM contract info
func NewContractInfo(codeID uint64, creator sdk.AccAddress, initMsg []byte, label string, createdAt CreatedAt) ContractInfo {
func NewContractInfo(codeID uint64, creator sdk.AccAddress, initMsg []byte, label string, createdAt *CreatedAt) ContractInfo {
return ContractInfo{
CodeID: codeID,
Creator: creator,