Skip to content

Commit

Permalink
add optional block header verification on inbound tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
kingpinXD committed Oct 4, 2023
1 parent f96feeb commit 978c742
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 98 deletions.
8 changes: 8 additions & 0 deletions common/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ func (chain Chain) IsKlaytnChain() bool {
return chain.ChainId == 1001
}

func (chain Chain) IsProvable() bool {
return chain.ChainId == 1 ||
chain.ChainId == 5 ||
chain.ChainId == 1337 ||
chain.ChainId == 97 ||
chain.ChainId == 56
}

func IsBitcoinChain(chainID int64) bool {
return chainID == 18444 || // regtest
chainID == 18332 || //testnet
Expand Down
3 changes: 3 additions & 0 deletions docs/spec/crosschain/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ message MsgAddToInTxTracker {
int64 chain_id = 2;
string tx_hash = 3;
common.CoinType coin_type = 4;
common.Proof proof = 5;
string block_hash = 6;
int64 tx_index = 7;
}
```

Expand Down
3 changes: 3 additions & 0 deletions proto/crosschain/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ message MsgAddToInTxTracker {
int64 chain_id = 2;
string tx_hash = 3;
common.CoinType coin_type = 4;
common.Proof proof = 5;
string block_hash = 6;
int64 tx_index = 7;
}
message MsgAddToInTxTrackerResponse {}

Expand Down
87 changes: 82 additions & 5 deletions x/crosschain/keeper/keeper_in_tx_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import (
"context"
"fmt"

cosmoserrors "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/query"
eth "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/zeta-chain/zetacore/common"
"github.com/zeta-chain/zetacore/x/crosschain/types"
zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types"
observerTypes "github.com/zeta-chain/zetacore/x/observer/types"
)

func getInTrackerKey(chainID int64, txHash string) string {
Expand Down Expand Up @@ -85,19 +89,27 @@ func (k msgServer) AddToInTxTracker(goCtx context.Context, msg *types.MsgAddToIn
ctx := sdk.UnwrapSDKContext(goCtx)
chain := k.zetaObserverKeeper.GetParams(ctx).GetChainFromChainID(msg.ChainId)
if chain == nil {
return nil, zetaObserverTypes.ErrSupportedChains
return nil, observerTypes.ErrSupportedChains
}

adminPolicyAccount := k.zetaObserverKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group1)
adminPolicyAccount := k.zetaObserverKeeper.GetParams(ctx).GetAdminPolicyAccount(observerTypes.Policy_Type_group1)
isAdmin := msg.Creator == adminPolicyAccount

isObserver, err := k.zetaObserverKeeper.IsAuthorized(ctx, msg.Creator, chain)
if err != nil {
ctx.Logger().Error("Error while checking if the account is an observer", err)
}
isProven := false
if msg.Proof != nil {
isProven, err = k.VerifyInTxTrackerProof(ctx, msg.Proof, msg.BlockHash, msg.TxIndex, msg.ChainId, msg.CoinType)
if err != nil {
return nil, err
}
}

// Sender needs to be either the admin policy account or an observer
if !(isAdmin || isObserver) {
return nil, sdkerrors.Wrap(zetaObserverTypes.ErrNotAuthorized, fmt.Sprintf("Creator %s", msg.Creator))
if !(isAdmin || isObserver || isProven) {
return nil, sdkerrors.Wrap(observerTypes.ErrNotAuthorized, fmt.Sprintf("Creator %s", msg.Creator))
}

k.Keeper.SetInTxTracker(ctx, types.InTxTracker{
Expand All @@ -107,3 +119,68 @@ func (k msgServer) AddToInTxTracker(goCtx context.Context, msg *types.MsgAddToIn
})
return &types.MsgAddToInTxTrackerResponse{}, nil
}

func (k Keeper) VerifyInTxTrackerProof(ctx sdk.Context, proof *common.Proof, hash string, txIndex int64, chainID int64, coinType common.CoinType) (bool, error) {

senderChain := common.GetChainFromChainID(chainID)
if senderChain == nil {
return false, types.ErrUnsupportedChain
}

if !senderChain.IsProvable() {
return false, types.ErrCannotVerifyProof.Wrapf("chain %d does not support block header verification", chainID)
}

blockHash := eth.HexToHash(hash)
res, found := k.zetaObserverKeeper.GetBlockHeader(ctx, blockHash.Bytes())
if !found {
return false, cosmoserrors.Wrap(observerTypes.ErrBlockHeaderNotFound, fmt.Sprintf("block header not found %s", blockHash))
}

// verify and process the proof
val, err := proof.Verify(res.Header, int(txIndex))
if err != nil && !common.IsErrorInvalidProof(err) {
return false, err
}
var txx ethtypes.Transaction
err = txx.UnmarshalBinary(val)
if err != nil {
return false, err
}

coreParams, found := k.zetaObserverKeeper.GetCoreParamsByChainID(ctx, senderChain.ChainId)
if !found {
return false, types.ErrUnsupportedChain.Wrapf("core params not found for chain %d", senderChain.ChainId)
}
tssRes, err := k.GetTssAddress(ctx, &types.QueryGetTssAddressRequest{})
if err != nil {
return false, err
}
tssAddr := eth.HexToAddress(tssRes.Eth)
if tssAddr == (eth.Address{}) {
return false, fmt.Errorf("tss address not found")
}
if common.IsEVMChain(chainID) {
switch coinType {
case common.CoinType_Zeta:
if txx.To().Hex() != coreParams.ConnectorContractAddress {
return false, types.ErrCannotVerifyProof.Wrapf("receiver is not connector contract for coin type %s", coinType)
}
return true, nil
case common.CoinType_ERC20:
if txx.To().Hex() != coreParams.Erc20CustodyContractAddress {
return false, types.ErrCannotVerifyProof.Wrapf("receiver is not erc20Custory contract for coin type %s", coinType)
}
return true, nil
case common.CoinType_Gas:
if txx.To().Hex() != tssAddr.Hex() {
return false, types.ErrCannotVerifyProof.Wrapf("receiver is not tssAddress contract for coin type %s", coinType)
}
return true, nil
}
}
if common.IsBitcoinChain(chainID) {
return false, types.ErrCannotVerifyProof.Wrapf("cannot verify proof for bitcoin chain %d", chainID)
}
return false, fmt.Errorf("proof failed")
}
2 changes: 2 additions & 0 deletions x/crosschain/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ var (
ErrInvalidGasAmount = errorsmod.Register(ModuleName, 1137, "invalid gas amount")
ErrNoLiquidityPool = errorsmod.Register(ModuleName, 1138, "no liquidity pool")
ErrInvalidCoinType = errorsmod.Register(ModuleName, 1139, "invalid coin type")

ErrCannotVerifyProof = errorsmod.Register(ModuleName, 1140, "invalid coin type")
)
Loading

0 comments on commit 978c742

Please sign in to comment.