forked from cosmos/gravity-bridge
-
Notifications
You must be signed in to change notification settings - Fork 27
/
tx.go
100 lines (84 loc) · 3.29 KB
/
tx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package rest
import (
"fmt"
"net/http"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
hexUtil "github.com/ethereum/go-ethereum/common/hexutil"
ethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/althea-net/cosmos-gravity-bridge/module/x/gravity/types"
)
type valsetConfirmReq struct {
BaseReq rest.BaseReq `json:"base_req"`
EthAddress string `json:"eth_address"`
Nonce string `json:"nonce"`
EthSig string `json:"ethSig"`
}
// check the ethereum sig on a particular valset and broadcast a transaction containing
// it if correct. The nonce / block height is used to determine what valset to look up
// locally and verify
func createValsetConfirmHandler(cliCtx client.Context, storeKey string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req valsetConfirmReq
if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) {
rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request")
return
}
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
return
}
ethAddr, err := types.NewEthAddress(req.EthAddress)
if err != nil {
return
}
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/valsetRequest/%s", storeKey, req.Nonce), nil)
if err != nil {
fmt.Printf("could not get valset")
rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request")
return
}
var valset types.Valset
cliCtx.JSONMarshaler.MustUnmarshalJSON(res, &valset)
// TODO: fix this, need to fetch the gravityID from params here
checkpoint := valset.GetCheckpoint("fetch-gravity-id-from-params-please-this-should-panic")
// the signed message should be the hash of the checkpoint at the given nonce
ethHash := ethCrypto.Keccak256Hash(checkpoint)
ethSig, err := hexUtil.Decode(req.EthSig)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
ethPubkey, err := ethCrypto.SigToPub(ethHash.Bytes(), ethSig)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
ethPubkeyBytes := ethCrypto.FromECDSAPub(ethPubkey)
correct := ethCrypto.VerifySignature(ethPubkeyBytes, ethHash.Bytes(), ethSig)
if !correct {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
cosmosAddr := cliCtx.GetFromAddress()
msg := types.NewMsgValsetConfirm(valset.Nonce, *ethAddr, cosmosAddr, req.EthSig)
err = msg.ValidateBasic()
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request")
return
}
tx.WriteGeneratedTxResponse(cliCtx, w, baseReq, msg)
}
}
type bootstrapConfirmReq struct {
BaseReq rest.BaseReq `json:"base_req"`
Orchestrator sdk.AccAddress `json:"orchestrator"`
EthereumChainID uint64 `json:"ethereum_chain_id"`
BridgeContractAddress string `json:"bridge_contract_address"`
Block string `json:"block"`
BridgeValidators types.BridgeValidators `json:"bridge_validators"`
GravityID string `json:"gravity_id"`
StartThreshold uint64 `json:"start_threshold"`
}