Skip to content

Commit c42f422

Browse files
authored
feat: status api (#15)
* Allow coordinator to be set manually * Add manual coordinator test * Implement across message handler * Send signature to all relayers * Implement signature cache to store generated signatures * Speed up process coordination * Implement signature cache to store generated signatures * Add signature cache tests * Allow for coordinator to notify other relayers of an across message * Reduce tss timeout * Implement calculation of the unlock hash that matches on-chain implementation * Add across message handler tests * Update mocks to maintained version * Fix test race condition * Convert abi to constant * Use source chain id property from across data * Use message destination as across deposit source * Use coordinator from the host in message handler * Send across message result over the err chanel * Return api errors as json * Implement api serve function * Add signing handler tests * Ignore valid json encode errors * Enforce protocol type on the signing API * Update signing url * Implement signature cache subscribe * Implement status sse endpoint * Bump action cache action * Convert deposit id to bigint * Tidy modules * Lint
1 parent de3529b commit c42f422

File tree

9 files changed

+391
-25
lines changed

9 files changed

+391
-25
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ genmocks:
3636
mockgen -destination=./comm/p2p/mock/conn/conn.go github.com/libp2p/go-libp2p/core/network Conn
3737
mockgen -destination=./comm/p2p/mock/stream/stream.go github.com/libp2p/go-libp2p/core/network Stream,Conn
3838
mockgen -source=./chains/evm/message/across.go -destination=./chains/evm/message/mock/across.go
39+
mockgen -source=./api/handlers/signing.go -destination=./api/handlers/mock/signing.go
3940

4041

4142

api/handlers/mock/signing.go

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/handlers/signing.go

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
package handlers
22

33
import (
4+
"context"
5+
"encoding/hex"
46
"encoding/json"
57
"fmt"
8+
"math/big"
69
"net/http"
710

11+
"github.com/gorilla/mux"
812
across "github.com/sprintertech/sprinter-signing/chains/evm/message"
913
"github.com/sygmaprotocol/sygma-core/relayer/message"
1014
)
1115

16+
type ProtocolType string
17+
18+
const (
19+
AcrossProtocol ProtocolType = "across"
20+
)
21+
1222
type SigningBody struct {
13-
DepositId *BigInt `json:"depositId"`
14-
ChainId uint64 `json:"chainId"`
23+
ChainId uint64
24+
DepositId *BigInt `json:"depositId"`
25+
Protocol ProtocolType `json:"protocol"`
1526
}
1627

1728
type SigningHandler struct {
@@ -37,18 +48,28 @@ func (h *SigningHandler) HandleSigning(w http.ResponseWriter, r *http.Request) {
3748
return
3849
}
3950

40-
err = h.validate(b)
51+
vars := mux.Vars(r)
52+
err = h.validate(b, vars)
4153
if err != nil {
4254
JSONError(w, fmt.Sprintf("invalid request body: %s", err), http.StatusBadRequest)
4355
return
4456
}
45-
4657
errChn := make(chan error, 1)
47-
am := across.NewAcrossMessage(0, b.ChainId, across.AcrossData{
48-
DepositId: b.DepositId.Int,
49-
ErrChn: errChn,
50-
})
51-
h.msgChan <- []*message.Message{am}
58+
59+
var m *message.Message
60+
switch b.Protocol {
61+
case AcrossProtocol:
62+
{
63+
m = across.NewAcrossMessage(0, b.ChainId, across.AcrossData{
64+
DepositId: b.DepositId.Int,
65+
ErrChn: errChn,
66+
})
67+
}
68+
default:
69+
JSONError(w, fmt.Sprintf("invalid protocol %s", b.Protocol), http.StatusBadRequest)
70+
return
71+
}
72+
h.msgChan <- []*message.Message{m}
5273

5374
err = <-errChn
5475
if err != nil {
@@ -59,7 +80,13 @@ func (h *SigningHandler) HandleSigning(w http.ResponseWriter, r *http.Request) {
5980
w.WriteHeader(http.StatusAccepted)
6081
}
6182

62-
func (h *SigningHandler) validate(b *SigningBody) error {
83+
func (h *SigningHandler) validate(b *SigningBody, vars map[string]string) error {
84+
chainId, ok := new(big.Int).SetString(vars["chainId"], 10)
85+
if !ok {
86+
return fmt.Errorf("field 'chainId' invalid")
87+
}
88+
b.ChainId = chainId.Uint64()
89+
6390
if b.DepositId == nil {
6491
return fmt.Errorf("missing field 'depositId'")
6592
}
@@ -68,10 +95,72 @@ func (h *SigningHandler) validate(b *SigningBody) error {
6895
return fmt.Errorf("missing field 'chainId'")
6996
}
7097

71-
_, ok := h.chains[b.ChainId]
98+
_, ok = h.chains[b.ChainId]
7299
if !ok {
73100
return fmt.Errorf("chain '%d' not supported", b.ChainId)
74101
}
75102

76103
return nil
77104
}
105+
106+
type SignatureCacher interface {
107+
Subscribe(ctx context.Context, id string, sigChannel chan []byte)
108+
}
109+
110+
type StatusHandler struct {
111+
cache SignatureCacher
112+
chains map[uint64]struct{}
113+
}
114+
115+
func NewStatusHandler(cache SignatureCacher, chains map[uint64]struct{}) *StatusHandler {
116+
return &StatusHandler{
117+
cache: cache,
118+
chains: chains,
119+
}
120+
}
121+
122+
// HandleRequest is an sse handler that waits until the signing signature is ready
123+
// and returns it
124+
func (h *StatusHandler) HandleRequest(w http.ResponseWriter, r *http.Request) {
125+
vars := mux.Vars(r)
126+
chainId, ok := new(big.Int).SetString(vars["chainId"], 0)
127+
if !ok {
128+
JSONError(w, "chain id invalid", http.StatusBadRequest)
129+
return
130+
}
131+
_, ok = h.chains[chainId.Uint64()]
132+
if !ok {
133+
JSONError(w, fmt.Sprintf("chain %d not supported", chainId.Int64()), http.StatusNotFound)
134+
return
135+
}
136+
depositId, ok := vars["depositId"]
137+
if !ok {
138+
JSONError(w, "missing 'depositId", http.StatusBadRequest)
139+
return
140+
}
141+
142+
h.setheaders(w)
143+
144+
ctx := r.Context()
145+
sigChn := make(chan []byte, 1)
146+
h.cache.Subscribe(ctx, fmt.Sprintf("%d-%s", chainId, depositId), sigChn)
147+
for {
148+
select {
149+
case <-r.Context().Done():
150+
return
151+
case sig := <-sigChn:
152+
{
153+
fmt.Fprintf(w, "data: %s\n\n", hex.EncodeToString(sig))
154+
w.(http.Flusher).Flush()
155+
return
156+
}
157+
}
158+
}
159+
}
160+
161+
func (h *StatusHandler) setheaders(w http.ResponseWriter) {
162+
w.Header().Set("Content-Type", "text/event-stream")
163+
w.Header().Set("Cache-Control", "no-cache")
164+
w.Header().Set("Connection", "keep-alive")
165+
w.Header().Set("Access-Control-Allow-Origin", "*")
166+
}

0 commit comments

Comments
 (0)