Skip to content

Commit

Permalink
Merge pull request #321 from PeggyJV/zaki/upgrade_handler_support
Browse files Browse the repository at this point in the history
  • Loading branch information
zmanian authored Jan 5, 2022
2 parents 4159c4f + 6cb5bbc commit 6cd4539
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 1 deletion.
74 changes: 74 additions & 0 deletions module/x/gravity/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,3 +562,77 @@ func (k Keeper) CreateContractCallTx(ctx sdk.Context, invalidationNonce uint64,
)
return newContractCallTx
}

/////////////////
// MIGRATE //
/////////////////

// Clean up all state associated a previous gravity contract and set a new contract. This is intended to run in the upgrade handler.
// This implementation is partial at best. It doees not contain necessary functionality to freeze the bridge.
// We will have yet to implement functionality to Migrate the Cosmos ERC20 tokens or any other ERC20 tokens bridged to the gravity contracts.
// This just does keeper state cleanup if a new gravity contract has been deployed
func (k Keeper) MigrateGravityContract(ctx sdk.Context, newBridgeAddress string, bridgeDeploymentHeight uint64) {

// Delete Any Outgoing TXs.

prefixStoreOtx := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{types.OutgoingTxKey})
iterOtx := prefixStoreOtx.ReverseIterator(nil, nil)
defer iterOtx.Close()
for ; iterOtx.Valid(); iterOtx.Next() {

var any cdctypes.Any
k.cdc.MustUnmarshal(iterOtx.Value(), &any)
var otx types.OutgoingTx
if err := k.cdc.UnpackAny(&any, &otx); err != nil {
panic(err)
}
// Delete any partial Eth Signatures handging around
prefixStoreSig := prefix.NewStore(ctx.KVStore(k.storeKey), append([]byte{types.EthereumSignatureKey}, otx.GetStoreIndex()...))
iterSig := prefixStoreSig.Iterator(nil, nil)
defer iterSig.Close()

for ; iterSig.Valid(); iterSig.Next() {
prefixStoreSig.Delete(iterSig.Key())
}

prefixStoreOtx.Delete(iterOtx.Key())
}

//Reset the last observed signer set nonce
ctx.KVStore(k.storeKey).Set([]byte{types.LatestSignerSetTxNonceKey}, sdk.Uint64ToBigEndian(0))

prefixStoreEthereumEvent := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{types.EthereumEventVoteRecordKey})

//Delete all Ethereum Events

iterEvent := prefixStoreEthereumEvent.Iterator(nil, nil)
defer iterEvent.Close()
for ; iterEvent.Valid(); iterEvent.Next() {
prefixStoreEthereumEvent.Delete(iterEvent.Key())
}

//Rest the Ethereum Event Nonce to Zero
store := ctx.KVStore(k.storeKey)
store.Set([]byte{types.LastObservedEventNonceKey}, sdk.Uint64ToBigEndian(0))

// Set the Last oberved Ethereum Blockheight to zero
height := types.LatestEthereumBlockHeight{
EthereumHeight: (bridgeDeploymentHeight - 1),
CosmosHeight: uint64(ctx.BlockHeight()),
}
store.Set([]byte{types.LastEthereumBlockHeightKey}, k.cdc.MustMarshal(&height))

k.setLastObservedSignerSetTx(ctx, types.SignerSetTx{
Nonce: 0,
Height: 0,
Signers: nil,
})

// Set the batch Nonce to zero
store.Set([]byte{types.LastOutgoingBatchNonceKey}, sdk.Uint64ToBigEndian(0))

// Update the bridge contract address
params := k.GetParams(ctx)
params.BridgeEthereumAddress = newBridgeAddress
k.setParams(ctx, params)
}
143 changes: 142 additions & 1 deletion module/x/gravity/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"bytes"
"testing"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -158,7 +159,7 @@ func TestStoreEventVoteRecord(t *testing.T) {

cctxe := &types.ContractCallExecutedEvent{
EventNonce: 2,
InvalidationScope: []byte{0x1, 0x2},
InvalidationScope: []byte{0x1, 0x2},
InvalidationNonce: 1,
EthereumHeight: 11,
}
Expand Down Expand Up @@ -504,6 +505,146 @@ func TestKeeper_GetEthereumSignatures(t *testing.T) {
})
}

func TestKeeper_Migration(t *testing.T) {

input := CreateTestEnv(t)
gk := input.GravityKeeper
ctx := input.Context

stce := &types.SendToCosmosEvent{
EventNonce: 1,
TokenContract: EthAddrs[0].Hex(),
EthereumSender: EthAddrs[0].Hex(),
CosmosReceiver: AccAddrs[0].String(),
EthereumHeight: 10,
Amount: sdk.NewInt(1000000),
}
stcea, err := types.PackEvent(stce)
require.NoError(t, err)

evr := &types.EthereumEventVoteRecord{
Event: stcea,
Votes: []string{
ValAddrs[0].String(),
ValAddrs[1].String(),
ValAddrs[2].String(),
},
Accepted: false,
}

cctxe := &types.ContractCallExecutedEvent{
EventNonce: 2,
InvalidationScope: []byte{0x1, 0x2},
InvalidationNonce: 1,
EthereumHeight: 11,
}

cctxea, err := types.PackEvent(cctxe)
require.NoError(t, err)

evr2 := &types.EthereumEventVoteRecord{
Event: cctxea,
Votes: []string{
ValAddrs[2].String(),
ValAddrs[3].String(),
ValAddrs[4].String(),
},
}

//Put an outgoing transaction into the system

var (
now = time.Now().UTC()
mySender, _ = sdk.AccAddressFromBech32("cosmos1ahx7f8wyertuus9r20284ej0asrs085case3kn")
myReceiver = common.HexToAddress("0xd041c41EA1bf0F006ADBb6d2c9ef9D425dE5eaD7")
myTokenContractAddr = common.HexToAddress("0x429881672B9AE42b8EbA0E26cD9C73711b891Ca5") // Pickle
allVouchers = sdk.NewCoins(
types.NewERC20Token(99999, myTokenContractAddr.Hex()).GravityCoin(),
)
)

// mint some voucher first
require.NoError(t, input.BankKeeper.MintCoins(ctx, types.ModuleName, allVouchers))
// set senders balance
input.AccountKeeper.NewAccountWithAddress(ctx, mySender)
require.NoError(t, fundAccount(ctx, input.BankKeeper, mySender, allVouchers))

// add some TX to the pool
input.AddSendToEthTxsToPool(t, ctx, myTokenContractAddr, mySender, myReceiver, 2, 3, 2, 1)

// when
ctx = ctx.WithBlockTime(now)

// tx batch size is 2, so that some of them stay behind
firstBatch := input.GravityKeeper.BuildBatchTx(ctx, myTokenContractAddr, 2)

// then batch is persisted
gotFirstBatch := input.GravityKeeper.GetOutgoingTx(ctx, firstBatch.GetStoreIndex())
require.NotNil(t, gotFirstBatch)

gk.setEthereumEventVoteRecord(ctx, stce.GetEventNonce(), stce.Hash(), evr)
gk.setLastObservedEventNonce(ctx, stce.GetEventNonce())
gk.setEthereumEventVoteRecord(ctx, cctxe.GetEventNonce(), cctxe.Hash(), evr2)
gk.setLastObservedEventNonce(ctx, cctxe.GetEventNonce())

stored := gk.GetEthereumEventVoteRecord(ctx, stce.GetEventNonce(), stce.Hash())
require.NotNil(t, stored)

ethAddr := common.HexToAddress("0x3146D2d6Eed46Afa423969f5dDC3152DfC359b09")

valAddr, err := sdk.ValAddressFromBech32("cosmosvaloper1jpz0ahls2chajf78nkqczdwwuqcu97w6z3plt4")
require.NoError(t, err)

{ // setup
batchTxConfirmation := &types.BatchTxConfirmation{
TokenContract: myTokenContractAddr.Hex(),
BatchNonce: firstBatch.BatchNonce,
EthereumSigner: ethAddr.Hex(),
Signature: []byte("fake-signature"),
}
key := gk.SetEthereumSignature(ctx, batchTxConfirmation, valAddr)
require.NotEmpty(t, key)
}

{ // validate
storeIndex := gotFirstBatch.GetStoreIndex()

{ // getEthereumSignature
got := gk.getEthereumSignature(ctx, storeIndex, valAddr)
require.Equal(t, []byte("fake-signature"), got)
}
{ // GetEthereumSignatures
got := gk.GetEthereumSignatures(ctx, storeIndex)
require.Len(t, got, 1)
}
}

nonce := gk.GetLastObservedEventNonce(ctx)
require.Equal(t, cctxe.GetEventNonce(), nonce)

gk.setLastObservedSignerSetTx(ctx, types.SignerSetTx{
Nonce: 1,
Height: 1,
Signers: nil,
})

gk.MigrateGravityContract(ctx, "0x5e175bE4d23Fa25604CE7848F60FB340894D5CDA", 1000)
stored2 := gk.GetEthereumEventVoteRecord(ctx, stce.GetEventNonce(), stce.Hash())
require.Nil(t, stored2)
nonce2 := gk.GetLastObservedEventNonce(ctx)
require.Equal(t, uint64(0), nonce2)

got := gk.GetLastObservedSignerSetTx(ctx)
require.Equal(t, got, &types.SignerSetTx{Nonce: 0x0, Height: 0x0, Signers: types.EthereumSigners(nil)})

{ // GetEthereumSignatures
storeIndex := gotFirstBatch.GetStoreIndex()
got := gk.GetEthereumSignatures(ctx, storeIndex)
require.Len(t, got, 0)
}

}

// TODO(levi) review/ensure coverage for:
// PaginateOutgoingTxsByType
// GetUnbondingvalidators(unbondingVals []byte) stakingtypes.ValAddresses

0 comments on commit 6cd4539

Please sign in to comment.