diff --git a/signing_service/proto/signing_service.gen.go b/signing_service/proto/signing_service.gen.go index 0620f4ad..f49e5619 100644 --- a/signing_service/proto/signing_service.gen.go +++ b/signing_service/proto/signing_service.gen.go @@ -1,8 +1,8 @@ -// sequence-dapp-signing-server v0.4.0 127eca8a4e204625345db5ab95e4c446487f86d4 +// sequence-dapp-signing-server v0.1.0 eba943dd810a3108374b471782bdad9e2f1ba29f // -- -// Code generated by webrpc-gen@v0.11.x-dev with golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.12.x-dev with golang generator. DO NOT EDIT. // -// webrpc-gen -schema=dapp_signing_server.ridl -target=golang -pkg=proto -server -client -out=./dapp_signing_server.gen.go +// webrpc-gen -schema=dapp_signing_server.ridl -target=golang -pkg=proto -client -out=./clients/dapp_signing_server.gen.go package proto import ( @@ -15,7 +15,6 @@ import ( "io/ioutil" "net/http" "net/url" - "strings" "time" ) @@ -26,12 +25,12 @@ func WebRPCVersion() string { // Schema version of your RIDL schema func WebRPCSchemaVersion() string { - return "v0.4.0" + return "v0.1.0" } // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "127eca8a4e204625345db5ab95e4c446487f86d4" + return "eba943dd810a3108374b471782bdad9e2f1ba29f" } // @@ -59,15 +58,23 @@ type WalletConfig struct { Content string `json:"content"` } -type WalletSigner struct { - Address string `json:"address"` - Weight uint8 `json:"weight"` +type SignRequest struct { + ChainId uint64 `json:"chainId"` + Msg string `json:"msg"` + AuxData string `json:"auxData"` + SignContext *SignContext `json:"signContext"` } -type SignRequest struct { - ChainId uint64 `json:"chainId"` - Msg string `json:"msg"` - AuxData string `json:"auxData"` +type SignContext struct { + ChainId uint64 `json:"chainId"` + PreImage string `json:"preImage"` + WalletAddress *string `json:"walletAddress"` + SigneeWalletAddress string `json:"signeeWalletAddress"` + Signature string `json:"signature"` + Message *string `json:"message"` + Transactions *string `json:"transactions"` + Nonce *uint64 `json:"nonce"` + PartnerId *uint64 `json:"partnerId"` } type SigningService interface { @@ -90,442 +97,6 @@ var WebRPCServices = map[string][]string{ }, } -// -// Server -// - -type WebRPCServer interface { - http.Handler -} - -type signingServiceServer struct { - SigningService -} - -func NewSigningServiceServer(svc SigningService) WebRPCServer { - return &signingServiceServer{ - SigningService: svc, - } -} - -func (s *signingServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) - ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) - ctx = context.WithValue(ctx, ServiceNameCtxKey, "SigningService") - - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - - switch r.URL.Path { - case "/rpc/SigningService/Ping": - s.servePing(ctx, w, r) - return - case "/rpc/SigningService/Version": - s.serveVersion(ctx, w, r) - return - case "/rpc/SigningService/RuntimeStatus": - s.serveRuntimeStatus(ctx, w, r) - return - case "/rpc/SigningService/GetSignerConfig": - s.serveGetSignerConfig(ctx, w, r) - return - case "/rpc/SigningService/Sign": - s.serveSign(ctx, w, r) - return - case "/rpc/SigningService/SignWith": - s.serveSignWith(ctx, w, r) - return - default: - err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) - RespondWithError(w, err) - return - } -} - -func (s *signingServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.servePingJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.Ping(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func (s *signingServiceServer) serveVersion(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveVersionJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) serveVersionJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Version") - - // Call service method - var ret0 *Version - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.Version(ctx) - }() - respContent := struct { - Ret0 *Version `json:"version"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func (s *signingServiceServer) serveRuntimeStatus(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveRuntimeStatusJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) serveRuntimeStatusJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "RuntimeStatus") - - // Call service method - var ret0 *RuntimeStatus - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.RuntimeStatus(ctx) - }() - respContent := struct { - Ret0 *RuntimeStatus `json:"status"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func (s *signingServiceServer) serveGetSignerConfig(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetSignerConfigJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) serveGetSignerConfigJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetSignerConfig") - reqContent := struct { - Arg0 string `json:"signer"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) - return - } - defer r.Body.Close() - - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) - return - } - - // Call service method - var ret0 *WalletConfig - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.GetSignerConfig(ctx, reqContent.Arg0) - }() - respContent := struct { - Ret0 *WalletConfig `json:"signerConfig"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func (s *signingServiceServer) serveSign(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveSignJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) serveSignJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Sign") - reqContent := struct { - Arg0 *SignRequest `json:"request"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) - return - } - defer r.Body.Close() - - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) - return - } - - // Call service method - var ret0 string - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.Sign(ctx, reqContent.Arg0) - }() - respContent := struct { - Ret0 string `json:"sig"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func (s *signingServiceServer) serveSignWith(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveSignWithJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - -func (s *signingServiceServer) serveSignWithJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "SignWith") - reqContent := struct { - Arg0 string `json:"signer"` - Arg1 *SignRequest `json:"request"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) - return - } - defer r.Body.Close() - - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) - return - } - - // Call service method - var ret0 string - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.SigningService.SignWith(ctx, reqContent.Arg0, reqContent.Arg1) - }() - respContent := struct { - Ret0 string `json:"sig"` - }{ret0} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(respBody) -} - -func RespondWithError(w http.ResponseWriter, err error) { - rpcErr, ok := err.(WebRPCError) - if !ok { - rpcErr = ErrorWithCause(ErrWebrpcEndpoint, err) - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(rpcErr.HTTPStatus) - - respBody, _ := json.Marshal(rpcErr) - w.Write(respBody) -} - // // Client // diff --git a/signing_service/signing_service.go b/signing_service/signing_service.go index 3a30b5b8..2e32cfcc 100644 --- a/signing_service/signing_service.go +++ b/signing_service/signing_service.go @@ -7,7 +7,6 @@ import ( "github.com/0xsequence/ethkit/ethcoder" "github.com/0xsequence/ethkit/go-ethereum/common" - "github.com/0xsequence/go-sequence" "github.com/0xsequence/go-sequence/core" "github.com/0xsequence/go-sequence/signing_service/proto" ) @@ -40,14 +39,6 @@ func (r *SigningService) SignDigest(ctx context.Context, digest common.Hash, opt chainId = optChainID[0] } - var auxDataPacked []byte - if auxData, err := sequence.AuxDataFromContext(ctx); err == nil { - auxDataPacked, err = auxData.Pack() - if err != nil { - return nil, nil, err - } - } - rCtx := ctx if r.params.AuthToken != "" { rCtx, _ = proto.WithHTTPRequestHeaders(ctx, map[string][]string{ @@ -56,9 +47,9 @@ func (r *SigningService) SignDigest(ctx context.Context, digest common.Hash, opt } encSig, err := r.params.Client.SignWith(rCtx, r.params.SignerAddress.Hex(), &proto.SignRequest{ - ChainId: chainId.Uint64(), - Msg: ethcoder.HexEncode(digest[:]), - AuxData: ethcoder.HexEncode(auxDataPacked), + ChainId: chainId.Uint64(), + Msg: ethcoder.HexEncode(digest[:]), + SignContext: SignContextFromContext(ctx), }) if err != nil { return nil, nil, err @@ -69,4 +60,16 @@ func (r *SigningService) SignDigest(ctx context.Context, digest common.Hash, opt return sig, nil, nil } -var _ sequence.SignerDigestSigner = &SigningService{} +const SignContextKey = "signing_service_sign_context" + +func ContextWithSignContext(ctx context.Context, signer *proto.SignContext) context.Context { + return context.WithValue(ctx, SignContextKey, signer) +} + +func SignContextFromContext(ctx context.Context) *proto.SignContext { + signCtx, ok := ctx.Value(SignContextKey).(*proto.SignContext) + if !ok { + return nil + } + return signCtx +} diff --git a/wallet.go b/wallet.go index dd6d334a..2ce80f37 100644 --- a/wallet.go +++ b/wallet.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/0xsequence/ethkit" "github.com/0xsequence/ethkit/ethcoder" "github.com/0xsequence/ethkit/ethrpc" "github.com/0xsequence/ethkit/ethtxn" @@ -14,6 +15,8 @@ import ( v1 "github.com/0xsequence/go-sequence/core/v1" v2 "github.com/0xsequence/go-sequence/core/v2" "github.com/0xsequence/go-sequence/sessions/proto" + "github.com/0xsequence/go-sequence/signing_service" + proto_signing_service "github.com/0xsequence/go-sequence/signing_service/proto" ) type WalletOptions[C core.WalletConfig] struct { @@ -424,6 +427,14 @@ func (w *Wallet[C]) GetTransactionCount(optBlockNum ...*big.Int) (*big.Int, erro } func (w *Wallet[C]) SignMessage(ctx context.Context, msg []byte) ([]byte, core.Signature[C], error) { + signContext := signing_service.SignContextFromContext(ctx) + if signContext == nil { + signContext = &proto_signing_service.SignContext{} + ctx = signing_service.ContextWithSignContext(ctx, signContext) + } + + signContext.Message = ethkit.ToPtr(string(msg)) + return w.SignDigest(ctx, MessageDigest(msg)) } @@ -448,12 +459,16 @@ func (w *Wallet[C]) SignDigest(ctx context.Context, digest common.Hash, optChain chainID = w.chainID } - ctx = ContextWithAuxData(ctx, &AuxData{ - ChainID: chainID, - Address: &w.address, - Msg: digest[:], - Sig: []byte{}, - }) + signContext := signing_service.SignContextFromContext(ctx) + if signContext == nil { + signContext = &proto_signing_service.SignContext{} + signContext.WalletAddress = ethkit.ToPtr(w.address.Hex()) + ctx = signing_service.ContextWithSignContext(ctx, signContext) + } + + signContext.PreImage = digest.Hex() + signContext.SigneeWalletAddress = w.address.Hex() + signContext.ChainId = chainID.Uint64() subDigest, err := SubDigest(chainID, w.Address(), digest) if err != nil { @@ -471,15 +486,17 @@ func (w *Wallet[C]) SignDigest(ctx context.Context, digest common.Hash, optChain // add the signature to the aux data if available if len(signatures) != 0 { - if auxData, err := AuxDataFromContext(ctx); err == nil { + if signContext := signing_service.SignContextFromContext(ctx); signContext != nil { signature := signatures[0] - auxData.Sig, _, _ = w.buildSignature(ctx, func(ctx context.Context, signer common.Address, signatures []core.SignerSignature) (core.SignerSignatureType, []byte, error) { + sig, _, _ := w.buildSignature(ctx, func(ctx context.Context, signer common.Address, signatures []core.SignerSignature) (core.SignerSignatureType, []byte, error) { if signer == signature.Signer { return signature.Type, signature.Signature, nil } else { return 0, nil, fmt.Errorf("no signer") } }) + + signContext.Signature = ethcoder.HexEncode(sig) } } @@ -565,6 +582,24 @@ func (w *Wallet[C]) SignTransactions(ctx context.Context, txns Transactions) (*S return nil, err } + // Set SignContext + signContext := signing_service.SignContextFromContext(ctx) + if signContext == nil { + signContext = &proto_signing_service.SignContext{} + ctx = signing_service.ContextWithSignContext(ctx, signContext) + } + + signContext.Nonce = ethkit.ToPtr(nonce.Uint64()) + signContext.WalletAddress = ethkit.ToPtr(w.Address().Hex()) + signContext.ChainId = w.chainID.Uint64() + + encTxn, err := txns.EncodeRaw() + if err != nil { + return nil, err + } + + signContext.Transactions = ethkit.ToPtr(ethcoder.HexEncode(encTxn)) + // Sign the transactions sig, _, err := w.SignDigest(ctx, digest) if err != nil {