Skip to content

Commit

Permalink
add merkle prove query RPC and smoketest for it
Browse files Browse the repository at this point in the history
  • Loading branch information
brewmaster012 committed Sep 14, 2023
1 parent 6bf8451 commit 5060dba
Show file tree
Hide file tree
Showing 6 changed files with 910 additions and 143 deletions.
52 changes: 48 additions & 4 deletions contrib/localnet/orchestrator/smoketest/test_deposit_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import (
"math/big"
"time"

ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/zeta-chain/zetacore/x/crosschain/types"
"github.com/zeta-chain/zetacore/zetaclient"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
zrc20 "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol"
"github.com/zeta-chain/zetacore/common"
ethereum2 "github.com/zeta-chain/zetacore/common/ethereum"
"github.com/zeta-chain/zetacore/x/crosschain/types"
observertypes "github.com/zeta-chain/zetacore/x/observer/types"
"github.com/zeta-chain/zetacore/zetaclient"
)

// this tests sending ZETA out of ZetaChain to Ethereum
Expand Down Expand Up @@ -53,6 +54,49 @@ func (sm *SmokeTest) TestDepositEtherIntoZRC20() {
fmt.Printf(" value: %d\n", signedTx.Value())
fmt.Printf(" block num: %d\n", receipt.BlockNumber)

{
LoudPrintf("Merkle Proof\n")
txHash := receipt.TxHash
blockHash := receipt.BlockHash
txIndex := int(receipt.TransactionIndex)
block, err := sm.goerliClient.BlockByHash(context.Background(), blockHash)
if err != nil {
panic(err)
}

trie := ethereum2.NewTrie(block.Transactions())
if trie.Hash() != block.Header().TxHash {
panic("tx root hash & block tx root mismatch") // FIXME: don't do this in production
}
txProof, err := trie.GenerateProof(txIndex)
if err != nil {
panic("error generating txProof") // FIXME: don't do this in production
}
val, err := txProof.Verify(block.TxHash(), txIndex)
if err != nil {
panic("error verifying txProof") // FIXME: don't do this in production
}
var txx ethtypes.Transaction
err = txx.UnmarshalBinary(val)
if err != nil {
panic("error unmarshalling txProof'd tx") // FIXME: don't do this in production
}
res, err := sm.observerClient.Prove(context.Background(), &observertypes.QueryProveRequest{
BlockHash: blockHash.Hex(),
TxIndex: int64(txIndex),
TxHash: txHash.Hex(),
Proof: txProof,
ChainId: 0,
})
if err != nil {
panic(err)
}
if !res.Valid {
panic("txProof invalid") // FIXME: don't do this in production
}
fmt.Printf("OK: txProof verified\n")
}

{
tx, err := sm.SendEther(TSSAddress, big.NewInt(101000000000000000), []byte(zetaclient.DonationMessage))
if err != nil {
Expand Down
18 changes: 18 additions & 0 deletions proto/observer/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ syntax = "proto3";
package zetachain.zetacore.observer;

import "common/common.proto";
import "common/ethereum/ethereum.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
Expand Down Expand Up @@ -88,6 +89,23 @@ service Query {
rpc GetBlockHeaderByHash(QueryGetBlockHeaderByHashRequest) returns (QueryGetBlockHeaderByHashResponse) {
option (google.api.http).get = "/zeta-chain/observer/get_block_header_by_hash/{block_hash}";
}

// merkle proof verification
rpc Prove(QueryProveRequest) returns (QueryProveResponse) {
option (google.api.http).get = "/zeta-chain/observer/prove";
}
}

message QueryProveRequest {
uint64 chain_id = 1;
string tx_hash = 4;
ethereum.Proof proof = 5;
string block_hash = 6;
int64 tx_index = 7;
}

message QueryProveResponse {
bool valid = 1;
}

message QueryParamsRequest {}
Expand Down
47 changes: 47 additions & 0 deletions x/observer/keeper/grpc_query_prove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package keeper

import (
"context"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
eth "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/zeta-chain/zetacore/x/observer/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (k Keeper) Prove(c context.Context, req *types.QueryProveRequest) (*types.QueryProveResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
ctx := sdk.UnwrapSDKContext(c)

blockHash := eth.HexToHash(req.BlockHash)
res, found := k.GetBlockHeader(ctx, blockHash.Bytes())
if !found {
return nil, status.Error(codes.NotFound, "block header not found")
}
var header ethtypes.Header
err := rlp.DecodeBytes(res.Header, &header)
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("failed to decode header: %s", err))
}
proven := false
if found {
val, err := req.Proof.Verify(header.TxHash, int(req.TxIndex))
if err == nil {
var txx ethtypes.Transaction
err = txx.UnmarshalBinary(val)
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("failed to unmarshal transaction: %s", err))
}
proven = true
}
}
return &types.QueryProveResponse{
Valid: proven,
}, nil
}
Loading

0 comments on commit 5060dba

Please sign in to comment.