Skip to content

Commit 5c6c225

Browse files
committed
WIP: config and client controller
1 parent 3adb2e0 commit 5c6c225

File tree

4 files changed

+128
-67
lines changed

4 files changed

+128
-67
lines changed

coordinator/internal/config/proxy_config.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@ import (
1212
type ProxyManager struct {
1313
// Zk verifier config help to confine the connected prover.
1414
Verifier *VerifierConfig `json:"verifier"`
15+
Client *ProxyClient `json:"proxy_cli"`
16+
Auth *Auth `json:"auth"`
17+
}
18+
19+
func (m *ProxyManager) Normalize() {
20+
if m.Client.Auth == nil {
21+
m.Client.Auth = m.Auth
22+
}
23+
24+
if m.Client.ProxyVersion == "" {
25+
m.Client.ProxyVersion = m.Verifier.MinProverVersion
26+
}
27+
}
28+
29+
// Proxy client configuration for connect to upstream as a client
30+
type ProxyClient struct {
31+
ProxyName string `json:"proxy_name"`
32+
ProxyVersion string `json:"proxy_version,omitempty"`
33+
Auth *Auth `json:"auth,omitempty"`
1534
}
1635

1736
// Coordinator configuration

coordinator/internal/controller/proxy/client.go

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,28 @@ package proxy
22

33
import (
44
"bytes"
5-
"crypto/ecdsa"
5+
"context"
66
"encoding/json"
77
"fmt"
88
"net/http"
99
"time"
1010

11-
"github.com/scroll-tech/go-ethereum/common"
12-
"github.com/scroll-tech/go-ethereum/crypto"
11+
"github.com/gin-gonic/gin"
1312

1413
"scroll-tech/coordinator/internal/config"
1514
"scroll-tech/coordinator/internal/types"
1615
)
1716

1817
// Client wraps an http client with a preset host for coordinator API calls
19-
type Client struct {
18+
type upClient struct {
2019
httpClient *http.Client
2120
baseURL string
2221
loginToken string
2322
}
2423

2524
// NewClient creates a new Client with the specified host
26-
func NewClient(cfg *config.UpStream) *Client {
27-
return &Client{
25+
func newUpClient(cfg *config.UpStream) *upClient {
26+
return &upClient{
2827
httpClient: &http.Client{
2928
Timeout: time.Duration(cfg.ConnectionTimeoutSec) * time.Second,
3029
},
@@ -33,7 +32,7 @@ func NewClient(cfg *config.UpStream) *Client {
3332
}
3433

3534
// FullLogin performs the complete login process: get challenge then login
36-
func (c *Client) Login(param types.LoginParameter) (*types.LoginSchema, error) {
35+
func (c *upClient) Login(ctx context.Context, param types.LoginParameter) (*types.LoginSchema, error) {
3736
// Step 1: Get challenge
3837
url := fmt.Sprintf("%s/coordinator/v1/challenge", c.baseURL)
3938

@@ -93,15 +92,15 @@ func (c *Client) Login(param types.LoginParameter) (*types.LoginSchema, error) {
9392
}
9493

9594
// ProxyLogin makes a POST request to /v1/proxy_login with LoginParameter
96-
func (c *Client) ProxyLogin(param types.LoginParameter) (*http.Response, error) {
95+
func (c *upClient) ProxyLogin(ctx *gin.Context, param types.LoginParameter) (*http.Response, error) {
9796
url := fmt.Sprintf("%s/coordinator/v1/proxy_login", c.baseURL)
9897

9998
jsonData, err := json.Marshal(param)
10099
if err != nil {
101100
return nil, fmt.Errorf("failed to marshal proxy login parameter: %w", err)
102101
}
103102

104-
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
103+
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
105104
if err != nil {
106105
return nil, fmt.Errorf("failed to create proxy login request: %w", err)
107106
}
@@ -113,15 +112,15 @@ func (c *Client) ProxyLogin(param types.LoginParameter) (*http.Response, error)
113112
}
114113

115114
// GetTask makes a POST request to /v1/get_task with GetTaskParameter
116-
func (c *Client) GetTask(param types.GetTaskParameter, token string) (*http.Response, error) {
115+
func (c *upClient) GetTask(ctx *gin.Context, param types.GetTaskParameter, token string) (*http.Response, error) {
117116
url := fmt.Sprintf("%s/coordinator/v1/get_task", c.baseURL)
118117

119118
jsonData, err := json.Marshal(param)
120119
if err != nil {
121120
return nil, fmt.Errorf("failed to marshal get task parameter: %w", err)
122121
}
123122

124-
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
123+
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
125124
if err != nil {
126125
return nil, fmt.Errorf("failed to create get task request: %w", err)
127126
}
@@ -135,15 +134,15 @@ func (c *Client) GetTask(param types.GetTaskParameter, token string) (*http.Resp
135134
}
136135

137136
// SubmitProof makes a POST request to /v1/submit_proof with SubmitProofParameter
138-
func (c *Client) SubmitProof(param types.SubmitProofParameter, token string) (*http.Response, error) {
137+
func (c *upClient) SubmitProof(ctx *gin.Context, param types.SubmitProofParameter, token string) (*http.Response, error) {
139138
url := fmt.Sprintf("%s/coordinator/v1/submit_proof", c.baseURL)
140139

141140
jsonData, err := json.Marshal(param)
142141
if err != nil {
143142
return nil, fmt.Errorf("failed to marshal submit proof parameter: %w", err)
144143
}
145144

146-
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
145+
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
147146
if err != nil {
148147
return nil, fmt.Errorf("failed to create submit proof request: %w", err)
149148
}
@@ -155,53 +154,3 @@ func (c *Client) SubmitProof(param types.SubmitProofParameter, token string) (*h
155154

156155
return c.httpClient.Do(req)
157156
}
158-
159-
// transformToValidPrivateKey safely transforms arbitrary bytes into valid private key bytes
160-
func (c *Client) buildPrivateKey(inputBytes []byte) (*ecdsa.PrivateKey, error) {
161-
// Try appending bytes from 0x0 to 0x20 until we get a valid private key
162-
for appendByte := byte(0x0); appendByte <= 0x20; appendByte++ {
163-
// Append the byte to input
164-
extendedBytes := append(inputBytes, appendByte)
165-
166-
// Calculate 256-bit hash
167-
hash := crypto.Keccak256(extendedBytes)
168-
169-
// Try to create private key from hash
170-
if k, err := crypto.ToECDSA(hash); err == nil {
171-
return k, nil
172-
}
173-
}
174-
175-
return nil, fmt.Errorf("failed to generate valid private key from input bytes")
176-
}
177-
178-
func (c *Client) generateLoginParameter(privateKeyBytes []byte, challenge string) (*types.LoginParameter, error) {
179-
// Generate private key
180-
privKey, err := c.buildPrivateKey(privateKeyBytes)
181-
if err != nil {
182-
return nil, err
183-
}
184-
185-
// Generate public key string
186-
publicKeyHex := common.Bytes2Hex(crypto.CompressPubkey(&privKey.PublicKey))
187-
188-
// Create login parameter with proxy settings
189-
loginParam := &types.LoginParameter{
190-
Message: types.Message{
191-
Challenge: challenge,
192-
ProverName: "proxy",
193-
ProverVersion: "proxy",
194-
ProverProviderType: types.ProverProviderTypeProxy,
195-
ProverTypes: []types.ProverType{}, // Default empty
196-
VKs: []string{}, // Default empty
197-
},
198-
PublicKey: publicKeyHex,
199-
}
200-
201-
// Sign the message with the private key
202-
if err := loginParam.SignWithKey(privKey); err != nil {
203-
return nil, fmt.Errorf("failed to sign login parameter: %w", err)
204-
}
205-
206-
return loginParam, nil
207-
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package proxy
2+
3+
import (
4+
"context"
5+
"crypto/ecdsa"
6+
"fmt"
7+
8+
"github.com/scroll-tech/go-ethereum/common"
9+
"github.com/scroll-tech/go-ethereum/crypto"
10+
11+
"scroll-tech/coordinator/internal/config"
12+
"scroll-tech/coordinator/internal/types"
13+
)
14+
15+
type Client interface {
16+
Client(context.Context) *upClient
17+
}
18+
19+
type ClientManager struct {
20+
cliCfg *config.ProxyClient
21+
cfg *config.UpStream
22+
privKey *ecdsa.PrivateKey
23+
}
24+
25+
// transformToValidPrivateKey safely transforms arbitrary bytes into valid private key bytes
26+
func buildPrivateKey(inputBytes []byte) (*ecdsa.PrivateKey, error) {
27+
// Try appending bytes from 0x0 to 0x20 until we get a valid private key
28+
for appendByte := byte(0x0); appendByte <= 0x20; appendByte++ {
29+
// Append the byte to input
30+
extendedBytes := append(inputBytes, appendByte)
31+
32+
// Calculate 256-bit hash
33+
hash := crypto.Keccak256(extendedBytes)
34+
35+
// Try to create private key from hash
36+
if k, err := crypto.ToECDSA(hash); err == nil {
37+
return k, nil
38+
}
39+
}
40+
41+
return nil, fmt.Errorf("failed to generate valid private key from input bytes")
42+
}
43+
44+
func NewClientManager(cliCfg *config.ProxyClient, cfg *config.UpStream) (*ClientManager, error) {
45+
46+
privKey, err := buildPrivateKey([]byte(cliCfg.Auth.Secret))
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
return &ClientManager{
52+
privKey: privKey,
53+
cfg: cfg,
54+
cliCfg: cliCfg,
55+
}, nil
56+
}
57+
58+
func (cliMgr *ClientManager) Client(ctx context.Context) *upClient {
59+
return newUpClient(cliMgr.cfg)
60+
}
61+
62+
func (cliMgr *ClientManager) generateLoginParameter(privKey []byte, challenge string) (*types.LoginParameter, error) {
63+
64+
// Generate public key string
65+
publicKeyHex := common.Bytes2Hex(crypto.CompressPubkey(&cliMgr.privKey.PublicKey))
66+
67+
// Create login parameter with proxy settings
68+
loginParam := &types.LoginParameter{
69+
Message: types.Message{
70+
Challenge: challenge,
71+
ProverName: cliMgr.cliCfg.ProxyName,
72+
ProverVersion: cliMgr.cliCfg.ProxyVersion,
73+
ProverProviderType: types.ProverProviderTypeProxy,
74+
ProverTypes: []types.ProverType{}, // Default empty
75+
VKs: []string{}, // Default empty
76+
},
77+
PublicKey: publicKeyHex,
78+
}
79+
80+
// Sign the message with the private key
81+
if err := loginParam.SignWithKey(cliMgr.privKey); err != nil {
82+
return nil, fmt.Errorf("failed to sign login parameter: %w", err)
83+
}
84+
85+
return loginParam, nil
86+
}

coordinator/internal/controller/proxy/controller.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,28 @@ var (
1818

1919
// Clients manager a series of thread-safe clients for requesting upstream
2020
// coordinators
21-
type Clients map[string]*Client
21+
type Clients map[string]Client
2222

2323
// InitController inits Controller with database
2424
func InitController(cfg *config.ProxyConfig) {
25+
// normalize cfg
26+
cfg.ProxyManager.Normalize()
27+
2528
vf, err := verifier.NewVerifier(cfg.ProxyManager.Verifier)
2629
if err != nil {
2730
panic("proof receiver new verifier failure")
2831
}
2932

3033
log.Info("verifier created", "openVmVerifier", vf.OpenVMVkMap)
3134

32-
clients := make(map[string]*Client)
35+
clients := make(map[string]Client)
3336

34-
for nm, cfg := range cfg.Coordinators {
35-
clients[nm] = NewClient(cfg)
37+
for nm, upCfg := range cfg.Coordinators {
38+
cli, err := NewClientManager(cfg.ProxyManager.Client, upCfg)
39+
if err != nil {
40+
panic("create new client fail")
41+
}
42+
clients[nm] = cli
3643
}
3744

3845
Auth = NewAuthController(cfg, clients, vf)

0 commit comments

Comments
 (0)