forked from sprintertech/sygma-relayer
-
Notifications
You must be signed in to change notification settings - Fork 1
feat: signing api #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 25 commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
d72a6d6
Allow coordinator to be set manually
mpetrun5 5c1de0a
Add manual coordinator test
mpetrun5 de6b2ef
Implement across message handler
mpetrun5 913ebd0
Send signature to all relayers
mpetrun5 21cbcfe
Implement signature cache to store generated signatures
mpetrun5 6eb268c
Speed up process coordination
mpetrun5 2ca060c
Implement signature cache to store generated signatures
mpetrun5 4d80bbd
Add signature cache tests
mpetrun5 084d5e3
Allow for coordinator to notify other relayers of an across message
mpetrun5 5205828
Reduce tss timeout
mpetrun5 54b76d6
Implement calculation of the unlock hash that matches on-chain implem…
mpetrun5 89733ba
Add across message handler tests
mpetrun5 bf72ba3
Merge branch 'main' into feat/across-message-handler
mpetrun5 d38887e
Update mocks to maintained version
mpetrun5 9cc32f0
Fix test race condition
mpetrun5 9627a80
Convert abi to constant
mpetrun5 a6f6b10
Use source chain id property from across data
mpetrun5 183b8fe
Use message destination as across deposit source
mpetrun5 692a7f8
Use coordinator from the host in message handler
mpetrun5 0dfaff1
Send across message result over the err chanel
mpetrun5 94dedf0
Return api errors as json
mpetrun5 ed8e2bb
Implement api serve function
mpetrun5 21582cd
Add signing handler tests
mpetrun5 6ff8c0c
Merge branch 'main' into feat/signing-api
mpetrun5 6e22f4e
Ignore valid json encode errors
mpetrun5 290cc5a
Remove print
mpetrun5 bb235a8
Bump cache action
mpetrun5 f3640f1
Use a custom big.Int type that decode big int from string
mpetrun5 172ec9e
Add read timeout
mpetrun5 f51b347
Add custom lint configuration
mpetrun5 ccd5811
Remove messy linters
mpetrun5 5b72bdb
Lint
mpetrun5 6356bc4
Remove extra nolint
mpetrun5 8e726ae
Remove linter errors
mpetrun5 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| package handlers | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "math/big" | ||
| "net/http" | ||
|
|
||
| across "github.com/sprintertech/sprinter-signing/chains/evm/message" | ||
| "github.com/sygmaprotocol/sygma-core/relayer/message" | ||
| ) | ||
|
|
||
| type SigningBody struct { | ||
| DepositId *big.Int `json:"depositId"` | ||
| ChainId uint64 `json:"chainId"` | ||
| } | ||
|
|
||
| type SigningHandler struct { | ||
| msgChan chan []*message.Message | ||
| chains map[uint64]struct{} | ||
| } | ||
|
|
||
| func NewSigningHandler(msgChan chan []*message.Message, chains map[uint64]struct{}) *SigningHandler { | ||
| return &SigningHandler{ | ||
| msgChan: msgChan, | ||
| chains: chains, | ||
| } | ||
| } | ||
|
|
||
| // HandleSigning sends a message to the across message handler and returns status code 202 | ||
| // if the deposit has been accepted for the signing process | ||
| func (h *SigningHandler) HandleSigning(w http.ResponseWriter, r *http.Request) { | ||
| b := &SigningBody{} | ||
| d := json.NewDecoder(r.Body) | ||
| err := d.Decode(b) | ||
| if err != nil { | ||
| JSONError(w, fmt.Sprintf("invalid request body: %s", err), http.StatusBadRequest) | ||
| return | ||
| } | ||
|
|
||
| err = h.validate(b) | ||
| if err != nil { | ||
| JSONError(w, fmt.Sprintf("invalid request body: %s", err), http.StatusBadRequest) | ||
| return | ||
| } | ||
|
|
||
| errChn := make(chan error, 1) | ||
| am := across.NewAcrossMessage(0, b.ChainId, across.AcrossData{ | ||
| DepositId: b.DepositId, | ||
| ErrChn: errChn, | ||
| }) | ||
| h.msgChan <- []*message.Message{am} | ||
|
|
||
| err = <-errChn | ||
| if err != nil { | ||
| JSONError(w, fmt.Sprintf("Singing failed: %s", err), http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| w.WriteHeader(http.StatusAccepted) | ||
| } | ||
|
|
||
| func (h *SigningHandler) validate(b *SigningBody) error { | ||
| if b.DepositId == nil { | ||
| return fmt.Errorf("missing field 'depositId'") | ||
| } | ||
|
|
||
| if b.ChainId == 0 { | ||
| return fmt.Errorf("missing field 'chainId'") | ||
| } | ||
|
|
||
| _, ok := h.chains[b.ChainId] | ||
| if !ok { | ||
| return fmt.Errorf("chain '%d' not supported", b.ChainId) | ||
| } | ||
|
|
||
| return nil | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| package handlers_test | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "encoding/json" | ||
| "fmt" | ||
| "math/big" | ||
| "net/http" | ||
| "net/http/httptest" | ||
| "testing" | ||
|
|
||
| "github.com/sprintertech/sprinter-signing/api/handlers" | ||
| across "github.com/sprintertech/sprinter-signing/chains/evm/message" | ||
| "github.com/stretchr/testify/suite" | ||
| "github.com/sygmaprotocol/sygma-core/relayer/message" | ||
| "go.uber.org/mock/gomock" | ||
| ) | ||
|
|
||
| type SigningHandlerTestSuite struct { | ||
| suite.Suite | ||
|
|
||
| handler *handlers.SigningHandler | ||
| msgChn chan []*message.Message | ||
| } | ||
|
|
||
| func TestRunSigningHandlerTestSuite(t *testing.T) { | ||
| suite.Run(t, new(SigningHandlerTestSuite)) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) SetupTest() { | ||
| ctrl := gomock.NewController(s.T()) | ||
| defer ctrl.Finish() | ||
|
|
||
| chains := make(map[uint64]struct{}) | ||
| chains[1] = struct{}{} | ||
|
|
||
| s.msgChn = make(chan []*message.Message, 1) | ||
| s.handler = handlers.NewSigningHandler(s.msgChn, chains) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) Test_HandleSigning_MissingDepositID() { | ||
| input := handlers.SigningBody{ | ||
| ChainId: 1, | ||
| } | ||
| body, _ := json.Marshal(input) | ||
|
|
||
| req := httptest.NewRequest(http.MethodPost, "/signing", bytes.NewReader(body)) | ||
| req.Header.Set("Content-Type", "application/json") | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
|
|
||
| go func() { | ||
| msg := <-s.msgChn | ||
| ad := msg[0].Data.(across.AcrossData) | ||
| ad.ErrChn <- fmt.Errorf("error handling message") | ||
| }() | ||
|
|
||
| s.handler.HandleSigning(recorder, req) | ||
|
|
||
| s.Equal(http.StatusBadRequest, recorder.Code) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) Test_HandleSigning_MissingChainID() { | ||
| input := handlers.SigningBody{ | ||
| DepositId: big.NewInt(1000), | ||
| } | ||
| body, _ := json.Marshal(input) | ||
|
|
||
| req := httptest.NewRequest(http.MethodPost, "/signing", bytes.NewReader(body)) | ||
| req.Header.Set("Content-Type", "application/json") | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
|
|
||
| go func() { | ||
| msg := <-s.msgChn | ||
| ad := msg[0].Data.(across.AcrossData) | ||
| ad.ErrChn <- fmt.Errorf("error handling message") | ||
| }() | ||
|
|
||
| s.handler.HandleSigning(recorder, req) | ||
|
|
||
| s.Equal(http.StatusBadRequest, recorder.Code) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) Test_HandleSigning_ChainNotSupported() { | ||
| input := handlers.SigningBody{ | ||
| ChainId: 2, | ||
| DepositId: big.NewInt(1000), | ||
| } | ||
| body, _ := json.Marshal(input) | ||
|
|
||
| req := httptest.NewRequest(http.MethodPost, "/signing", bytes.NewReader(body)) | ||
| req.Header.Set("Content-Type", "application/json") | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
|
|
||
| go func() { | ||
| msg := <-s.msgChn | ||
| ad := msg[0].Data.(across.AcrossData) | ||
| ad.ErrChn <- fmt.Errorf("error handling message") | ||
| }() | ||
|
|
||
| s.handler.HandleSigning(recorder, req) | ||
|
|
||
| s.Equal(http.StatusBadRequest, recorder.Code) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) Test_HandleSigning_ErrorHandlingMessage() { | ||
| input := handlers.SigningBody{ | ||
| ChainId: 1, | ||
| DepositId: big.NewInt(1000), | ||
| } | ||
| body, _ := json.Marshal(input) | ||
|
|
||
| req := httptest.NewRequest(http.MethodPost, "/signing", bytes.NewReader(body)) | ||
| req.Header.Set("Content-Type", "application/json") | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
|
|
||
| go func() { | ||
| msg := <-s.msgChn | ||
| ad := msg[0].Data.(across.AcrossData) | ||
| ad.ErrChn <- fmt.Errorf("error handling message") | ||
| }() | ||
|
|
||
| s.handler.HandleSigning(recorder, req) | ||
|
|
||
| s.Equal(http.StatusInternalServerError, recorder.Code) | ||
| } | ||
|
|
||
| func (s *SigningHandlerTestSuite) Test_HandleSigning_Success() { | ||
| input := handlers.SigningBody{ | ||
| ChainId: 1, | ||
| DepositId: big.NewInt(1000), | ||
| } | ||
| body, _ := json.Marshal(input) | ||
|
|
||
| req := httptest.NewRequest(http.MethodPost, "/signing", bytes.NewReader(body)) | ||
| req.Header.Set("Content-Type", "application/json") | ||
|
|
||
| recorder := httptest.NewRecorder() | ||
|
|
||
| go func() { | ||
| msg := <-s.msgChn | ||
| ad := msg[0].Data.(across.AcrossData) | ||
| ad.ErrChn <- nil | ||
| }() | ||
|
|
||
| s.handler.HandleSigning(recorder, req) | ||
|
|
||
| fmt.Println(recorder.Body.String()) | ||
| s.Equal(http.StatusAccepted, recorder.Code) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package handlers | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "net/http" | ||
| ) | ||
|
|
||
| func JSONError(w http.ResponseWriter, err interface{}, code int) { | ||
| w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||
| w.Header().Set("X-Content-Type-Options", "nosniff") | ||
| w.WriteHeader(code) | ||
| _ = json.NewEncoder(w).Encode(err) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package api | ||
|
|
||
| import ( | ||
| "context" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/rs/zerolog/log" | ||
| "github.com/sprintertech/sprinter-signing/api/handlers" | ||
| ) | ||
|
|
||
| func Serve( | ||
| ctx context.Context, | ||
| addr string, | ||
| signingHandler *handlers.SigningHandler, | ||
| ) { | ||
| mux := http.NewServeMux() | ||
| mux.HandleFunc("POST /signing", signingHandler.HandleSigning) | ||
|
|
||
| server := &http.Server{ | ||
mpetrun5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Addr: addr, | ||
| } | ||
| go func() { | ||
| log.Info().Msgf("Starting server on %s", addr) | ||
| if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { | ||
| panic(err) | ||
| } | ||
| }() | ||
|
|
||
| <-ctx.Done() | ||
| shutdownCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | ||
| defer cancel() | ||
|
|
||
| err := server.Shutdown(shutdownCtx) | ||
| if err != nil { | ||
| log.Err(err).Msgf("Error shutting down server") | ||
| } else { | ||
| log.Info().Msgf("Server shut down gracefully.") | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.