From f5129346c35d52b6fd04cf21a32b156582a5e917 Mon Sep 17 00:00:00 2001 From: jie Date: Sat, 2 May 2026 11:02:35 +0800 Subject: [PATCH 1/4] Add webapi external signer constructor --- webapi/api_server.go | 29 +++++++++++++++++++++++++++++ webapi/internal_api_server.go | 19 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/webapi/api_server.go b/webapi/api_server.go index 486fb06..f46ad5a 100644 --- a/webapi/api_server.go +++ b/webapi/api_server.go @@ -107,6 +107,35 @@ func NewApiServer( return s } +func NewApiServerWithExternalSigner( + webPort int, + grpcPort int, + allowedOrigins string, + addr string, + dataPath string, + config string, + signcb celersdk.ExternalSignerCallback) *ApiServer { + callbackImpl := NewCallbackImpl() + s := &ApiServer{ + webPort: webPort, + grpcPort: grpcPort, + allowedOrigins: allowedOrigins, + callbackImpl: callbackImpl, + appSessionMap: make(map[string]*celersdk.AppSession), + appSessionCallbackMap: make(map[string]*appSessionCallback), + } + go celersdk.InitClientWithSigner(addr, config, dataPath, callbackImpl, signcb) + + select { + case client := <-callbackImpl.clientReady: + s.apiClient = client + case err := <-callbackImpl.clientInitErr: + log.Fatal(err) + return nil + } + return s +} + func (s *ApiServer) Start() { gs := grpc.NewServer() rpc.RegisterWebApiServer(gs, s) diff --git a/webapi/internal_api_server.go b/webapi/internal_api_server.go index 0bbabef..5932684 100644 --- a/webapi/internal_api_server.go +++ b/webapi/internal_api_server.go @@ -14,6 +14,7 @@ import ( type InternalApiServer struct { *ApiServer + register func(*grpc.Server) } func NewInternalApiServer( @@ -26,11 +27,27 @@ func NewInternalApiServer( config string, extSigner bool) *InternalApiServer { apiServer := NewApiServer(webPort, grpcPort, allowedOrigins, keystore, password, dataPath, config, extSigner) - return &InternalApiServer{apiServer} + return &InternalApiServer{ApiServer: apiServer} +} + +func NewInternalApiServerWithExternalSigner( + addr string, + config string, + dataPath string, + webPort int, + grpcPort int, + allowedOrigins string, + cb celersdk.ExternalSignerCallback, + register func(*grpc.Server)) *InternalApiServer { + apiServer := NewApiServerWithExternalSigner(webPort, grpcPort, allowedOrigins, addr, dataPath, config, cb) + return &InternalApiServer{ApiServer: apiServer, register: register} } func (s *InternalApiServer) Start() { gs := grpc.NewServer() + if s.register != nil { + s.register(gs) + } rpc.RegisterWebApiServer(gs, s.ApiServer) rpc.RegisterInternalWebApiServer(gs, s) s.ApiServer.serve(gs) From 261f119b5e12e58ff0f872db8c0ec3dce27c338a Mon Sep 17 00:00:00 2001 From: jie Date: Tue, 5 May 2026 13:54:59 +0800 Subject: [PATCH 2/4] Fix NewApiServerWithExternalSigner referencing removed appSessionCallback type appSessionCallbackMap was initialized in the constructor but appSessionCallback type was removed when the OSP dispute-subscription methods were stripped. Co-Authored-By: Claude Sonnet 4.6 --- webapi/api_server.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webapi/api_server.go b/webapi/api_server.go index f46ad5a..09c7cc9 100644 --- a/webapi/api_server.go +++ b/webapi/api_server.go @@ -121,8 +121,7 @@ func NewApiServerWithExternalSigner( grpcPort: grpcPort, allowedOrigins: allowedOrigins, callbackImpl: callbackImpl, - appSessionMap: make(map[string]*celersdk.AppSession), - appSessionCallbackMap: make(map[string]*appSessionCallback), + appSessionMap: make(map[string]*celersdk.AppSession), } go celersdk.InitClientWithSigner(addr, config, dataPath, callbackImpl, signcb) From 8ad6b3f2f54d870ce8bf99c5fc81d731e23975bd Mon Sep 17 00:00:00 2001 From: jie Date: Wed, 6 May 2026 11:05:47 +0800 Subject: [PATCH 3/4] Refactor webapi constructors for external signer support --- webapi/api_server.go | 58 +++++++++++++++++------------------ webapi/internal_api_server.go | 6 ++-- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/webapi/api_server.go b/webapi/api_server.go index 09c7cc9..018baac 100644 --- a/webapi/api_server.go +++ b/webapi/api_server.go @@ -70,21 +70,18 @@ func NewApiServer( dataPath string, config string, useExtSigner bool) *ApiServer { - callbackImpl := NewCallbackImpl() - s := &ApiServer{ - webPort: webPort, - grpcPort: grpcPort, - allowedOrigins: allowedOrigins, - callbackImpl: callbackImpl, - appSessionMap: make(map[string]*celersdk.AppSession), - } if !useExtSigner { - go celersdk.InitClient( - &celersdk.Account{Keystore: keystore, Password: password}, - config, - dataPath, - callbackImpl) - } else { // exercise external signer code path + return newApiServerWithClientInit(webPort, grpcPort, allowedOrigins, func(callbackImpl *callbackImpl) { + go celersdk.InitClient( + &celersdk.Account{Keystore: keystore, Password: password}, + config, + dataPath, + callbackImpl) + }) + } + + // exercise external signer code path + return newApiServerWithClientInit(webPort, grpcPort, allowedOrigins, func(callbackImpl *callbackImpl) { addr, priv, err := eth.GetAddrPrivKeyFromKeystore(keystore, password) if err != nil { log.Fatal(err) @@ -95,16 +92,7 @@ func NewApiServer( log.Fatal(err) } go celersdk.InitClientWithSigner(ctype.Addr2Hex(addr), config, dataPath, callbackImpl, &extSigner{signer}) - } - - select { - case client := <-callbackImpl.clientReady: - s.apiClient = client - case err := <-callbackImpl.clientInitErr: - log.Fatal(err) - return nil - } - return s + }) } func NewApiServerWithExternalSigner( @@ -115,15 +103,25 @@ func NewApiServerWithExternalSigner( dataPath string, config string, signcb celersdk.ExternalSignerCallback) *ApiServer { + return newApiServerWithClientInit(webPort, grpcPort, allowedOrigins, func(callbackImpl *callbackImpl) { + go celersdk.InitClientWithSigner(addr, config, dataPath, callbackImpl, signcb) + }) +} + +func newApiServerWithClientInit( + webPort int, + grpcPort int, + allowedOrigins string, + initClient func(*callbackImpl)) *ApiServer { callbackImpl := NewCallbackImpl() s := &ApiServer{ - webPort: webPort, - grpcPort: grpcPort, - allowedOrigins: allowedOrigins, - callbackImpl: callbackImpl, - appSessionMap: make(map[string]*celersdk.AppSession), + webPort: webPort, + grpcPort: grpcPort, + allowedOrigins: allowedOrigins, + callbackImpl: callbackImpl, + appSessionMap: make(map[string]*celersdk.AppSession), } - go celersdk.InitClientWithSigner(addr, config, dataPath, callbackImpl, signcb) + initClient(callbackImpl) select { case client := <-callbackImpl.clientReady: diff --git a/webapi/internal_api_server.go b/webapi/internal_api_server.go index 5932684..afe386e 100644 --- a/webapi/internal_api_server.go +++ b/webapi/internal_api_server.go @@ -31,12 +31,12 @@ func NewInternalApiServer( } func NewInternalApiServerWithExternalSigner( - addr string, - config string, - dataPath string, webPort int, grpcPort int, allowedOrigins string, + addr string, + dataPath string, + config string, cb celersdk.ExternalSignerCallback, register func(*grpc.Server)) *InternalApiServer { apiServer := NewApiServerWithExternalSigner(webPort, grpcPort, allowedOrigins, addr, dataPath, config, cb) From 3363b51995cc28f047f963408ff04575351565d0 Mon Sep 17 00:00:00 2001 From: jie Date: Wed, 6 May 2026 12:14:02 +0800 Subject: [PATCH 4/4] Remove mixed signer mode from WebAPI constructors --- testing/testclient/testclient.go | 43 ++++++++++++++++++++++++++-- webapi/api_server.go | 49 ++++---------------------------- webapi/cmd/main.go | 2 +- webapi/internal_api_server.go | 5 ++-- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/testing/testclient/testclient.go b/testing/testclient/testclient.go index 54cdafa..199ff8f 100644 --- a/testing/testclient/testclient.go +++ b/testing/testclient/testclient.go @@ -5,8 +5,13 @@ package main import ( "flag" "io/ioutil" + "math/big" + "github.com/celer-network/agent-pay/celersdk" + "github.com/celer-network/agent-pay/common" + "github.com/celer-network/agent-pay/ctype" "github.com/celer-network/agent-pay/webapi" + "github.com/celer-network/goutils/eth" "github.com/celer-network/goutils/log" ) @@ -29,6 +34,27 @@ func main() { log.Fatal(err) } log.Infoln("start testclient on port", *grpcPort, "using ks", *ksPath) + if *extSigner { + addr, priv, err := eth.GetAddrPrivKeyFromKeystore(string(ksBytes), "") + if err != nil { + log.Fatal(err) + } + p := common.Bytes2Profile(cfg) + signer, err := eth.NewSigner(priv, big.NewInt(p.ChainId)) + if err != nil { + log.Fatal(err) + } + webapi.NewInternalApiServerWithExternalSigner( + -1, + *grpcPort, + "http://localhost:*", + ctype.Addr2Hex(addr), + *dataPath, + string(cfg[:]), + &testExternalSigner{Signer: signer}, + nil).Start() + return + } webapi.NewInternalApiServer( -1, *grpcPort, @@ -36,6 +62,19 @@ func main() { string(ksBytes[:]), "", *dataPath, - string(cfg[:]), - *extSigner).Start() + string(cfg[:])).Start() +} + +type testExternalSigner struct { + eth.Signer +} + +func (es *testExternalSigner) OnSignMessage(reqid int, msg []byte) { + res, _ := es.SignEthMessage(msg) + celersdk.PublishSignedResult(reqid, res) +} + +func (es *testExternalSigner) OnSignTransaction(reqid int, rawtx []byte) { + res, _ := es.SignEthTransaction(rawtx) + celersdk.PublishSignedResult(reqid, res) } diff --git a/webapi/api_server.go b/webapi/api_server.go index 018baac..999e3cb 100644 --- a/webapi/api_server.go +++ b/webapi/api_server.go @@ -7,7 +7,6 @@ import ( "encoding/json" "errors" "fmt" - "math/big" "net" "net/http" "strconv" @@ -17,12 +16,10 @@ import ( "github.com/celer-network/agent-pay/celersdk" "github.com/celer-network/agent-pay/celersdkintf" - "github.com/celer-network/agent-pay/common" "github.com/celer-network/agent-pay/ctype" "github.com/celer-network/agent-pay/entity" msgrpc "github.com/celer-network/agent-pay/rpc" "github.com/celer-network/agent-pay/webapi/rpc" - "github.com/celer-network/goutils/eth" "github.com/celer-network/goutils/log" "github.com/improbable-eng/grpc-web/go/grpcweb" "github.com/rs/cors" @@ -44,23 +41,6 @@ type ApiServer struct { appSessionMapLock sync.Mutex } -// implement celersdk.ExternalSignerCallback interface -// also embed eth.Signer so celersdk.ExternalSignerManager can tell the difference and -// avoid double hash -type extSigner struct { - eth.Signer -} - -func (es *extSigner) OnSignMessage(reqid int, msg []byte) { - res, _ := es.SignEthMessage(msg) - celersdk.PublishSignedResult(reqid, res) -} - -func (es *extSigner) OnSignTransaction(reqid int, rawtx []byte) { - res, _ := es.SignEthTransaction(rawtx) - celersdk.PublishSignedResult(reqid, res) -} - func NewApiServer( webPort int, grpcPort int, @@ -68,30 +48,13 @@ func NewApiServer( keystore string, password string, dataPath string, - config string, - useExtSigner bool) *ApiServer { - if !useExtSigner { - return newApiServerWithClientInit(webPort, grpcPort, allowedOrigins, func(callbackImpl *callbackImpl) { - go celersdk.InitClient( - &celersdk.Account{Keystore: keystore, Password: password}, - config, - dataPath, - callbackImpl) - }) - } - - // exercise external signer code path + config string) *ApiServer { return newApiServerWithClientInit(webPort, grpcPort, allowedOrigins, func(callbackImpl *callbackImpl) { - addr, priv, err := eth.GetAddrPrivKeyFromKeystore(keystore, password) - if err != nil { - log.Fatal(err) - } - p := common.Bytes2Profile([]byte(config)) - signer, err := eth.NewSigner(priv, big.NewInt(p.ChainId)) - if err != nil { - log.Fatal(err) - } - go celersdk.InitClientWithSigner(ctype.Addr2Hex(addr), config, dataPath, callbackImpl, &extSigner{signer}) + go celersdk.InitClient( + &celersdk.Account{Keystore: keystore, Password: password}, + config, + dataPath, + callbackImpl) }) } diff --git a/webapi/cmd/main.go b/webapi/cmd/main.go index a82d46d..bca7040 100644 --- a/webapi/cmd/main.go +++ b/webapi/cmd/main.go @@ -73,5 +73,5 @@ func main() { string(ksBytes[:]), ksPasswordStr, *dataPath, - string(cfg[:]), false).Start() + string(cfg[:])).Start() } diff --git a/webapi/internal_api_server.go b/webapi/internal_api_server.go index afe386e..d11e4f4 100644 --- a/webapi/internal_api_server.go +++ b/webapi/internal_api_server.go @@ -24,9 +24,8 @@ func NewInternalApiServer( keystore string, password string, dataPath string, - config string, - extSigner bool) *InternalApiServer { - apiServer := NewApiServer(webPort, grpcPort, allowedOrigins, keystore, password, dataPath, config, extSigner) + config string) *InternalApiServer { + apiServer := NewApiServer(webPort, grpcPort, allowedOrigins, keystore, password, dataPath, config) return &InternalApiServer{ApiServer: apiServer} }