Skip to content

Commit

Permalink
Merge pull request #1462 from CosmWasm/history_position
Browse files Browse the repository at this point in the history
Ensure history position does not conflict
  • Loading branch information
alpe authored Jun 29, 2023
2 parents 30f956b + b2214cf commit c376c93
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
23 changes: 16 additions & 7 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,11 @@ func (k Keeper) appendToContractHistory(ctx sdk.Context, contractAddr sdk.AccAdd
iter := prefixStore.ReverseIterator(nil, nil)
defer iter.Close()

if iter.Valid() {
pos = sdk.BigEndianToUint64(iter.Key())
for ; iter.Valid(); iter.Next() {
if len(iter.Key()) == 8 { // add extra safety in a mixed contract length environment
pos = sdk.BigEndianToUint64(iter.Key())
break
}
}
// then store with incrementing position
for _, e := range newEntries {
Expand All @@ -641,6 +644,10 @@ func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress)
defer iter.Close()

for ; iter.Valid(); iter.Next() {
if len(iter.Key()) != 8 { // add extra safety in a mixed contract length environment
continue
}

var e types.ContractCodeHistoryEntry
k.cdc.MustUnmarshal(iter.Value(), &e)
r = append(r, e)
Expand All @@ -655,12 +662,14 @@ func (k Keeper) getLastContractHistoryEntry(ctx sdk.Context, contractAddr sdk.Ac
defer iter.Close()

var r types.ContractCodeHistoryEntry
if !iter.Valid() {
// all contracts have a history
panic(fmt.Sprintf("no history for %s", contractAddr.String()))
for ; iter.Valid(); iter.Next() {
if len(iter.Key()) == 8 { // add extra safety in a mixed contract length environment
k.cdc.MustUnmarshal(iter.Value(), &r)
return r
}
}
k.cdc.MustUnmarshal(iter.Value(), &r)
return r
// all contracts have a history
panic(fmt.Sprintf("no history for %s", contractAddr.String()))
}

// QuerySmart queries the smart contract itself.
Expand Down
55 changes: 42 additions & 13 deletions x/wasm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import (
"encoding/json"
"errors"
"fmt"
stdrand "math/rand"
"os"
"strings"
"testing"
"time"

errorsmod "cosmossdk.io/errors"
abci "github.com/cometbft/cometbft/abci/types"

wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/rand"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/baseapp"
Expand Down Expand Up @@ -2161,20 +2162,48 @@ func TestSetAccessConfig(t *testing.T) {
}

func TestAppendToContractHistory(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
var contractAddr sdk.AccAddress = rand.Bytes(types.ContractAddrLen)
var orderedEntries []types.ContractCodeHistoryEntry

f := fuzz.New().Funcs(ModelFuzzers...)
for i := 0; i < 10; i++ {
var entry types.ContractCodeHistoryEntry
f.Fuzz(&entry)
keepers.WasmKeeper.appendToContractHistory(ctx, contractAddr, entry)
orderedEntries = append(orderedEntries, entry)
pCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
k := keepers.WasmKeeper

variableLengthAddresses := []sdk.AccAddress{
bytes.Repeat([]byte{0x1}, types.ContractAddrLen),
append([]byte{0x00}, bytes.Repeat([]byte{0x1}, types.ContractAddrLen-1)...),
append(bytes.Repeat([]byte{0x1}, types.ContractAddrLen-1), 0x00),
append([]byte{0xff}, bytes.Repeat([]byte{0x1}, types.ContractAddrLen-1)...),
append(bytes.Repeat([]byte{0x1}, types.ContractAddrLen-1), 0xff),
bytes.Repeat([]byte{0x1}, types.SDKAddrLen),
append([]byte{0x00}, bytes.Repeat([]byte{0x1}, types.SDKAddrLen-1)...),
append(bytes.Repeat([]byte{0x1}, types.SDKAddrLen-1), 0x00),
append([]byte{0xff}, bytes.Repeat([]byte{0x1}, types.SDKAddrLen-1)...),
append(bytes.Repeat([]byte{0x1}, types.SDKAddrLen-1), 0xff),
}
sRandom := stdrand.New(stdrand.NewSource(0))
for n := 0; n < 100; n++ {
t.Run(fmt.Sprintf("iteration %d", n), func(t *testing.T) {
sRandom.Seed(int64(n))
sRandom.Shuffle(len(variableLengthAddresses), func(i, j int) {
variableLengthAddresses[i], variableLengthAddresses[j] = variableLengthAddresses[j], variableLengthAddresses[i]
})
orderedEntries := make([][]types.ContractCodeHistoryEntry, len(variableLengthAddresses))

ctx, _ := pCtx.CacheContext()
for j, addr := range variableLengthAddresses {
for i := 0; i < 10; i++ {
var entry types.ContractCodeHistoryEntry
f.RandSource(sRandom).Fuzz(&entry)
k.appendToContractHistory(ctx, addr, entry)
orderedEntries[j] = append(orderedEntries[j], entry)
}
}
// when
for j, addr := range variableLengthAddresses {
gotHistory := k.GetContractHistory(ctx, addr)
assert.Equal(t, orderedEntries[j], gotHistory, "%d: %X", j, addr)
assert.Equal(t, orderedEntries[j][len(orderedEntries[j])-1], k.getLastContractHistoryEntry(ctx, addr))
}
})
}
// when
gotHistory := keepers.WasmKeeper.GetContractHistory(ctx, contractAddr)
assert.Equal(t, orderedEntries, gotHistory)
}

func TestCoinBurnerPruneBalances(t *testing.T) {
Expand Down

0 comments on commit c376c93

Please sign in to comment.