Skip to content

Commit 973cf99

Browse files
authored
chore(linea-ens-app): add more logs when calling Web3Signer (#349)
1 parent 51ec8f5 commit 973cf99

File tree

17 files changed

+110
-62
lines changed

17 files changed

+110
-62
lines changed

packages/linea-ens-app/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ In a third terminal, run:
6262

6363
```bash
6464
cd services/web3signer/
65-
cp ./keyFiles/examples/signer.yaml ./keyFiles/signer.yaml
65+
cp ./key-files/examples/signer.yaml ./key-files/signer.yaml
6666
make dev-docker
6767
```
6868

@@ -114,7 +114,7 @@ it [here] (https://poh.linea.build/).
114114
- Add this config:
115115

116116
| Setting | Value |
117-
| --------------- | --------------------- |
117+
| --------------- | --------------------- |
118118
| Network name | Localhost 8545 |
119119
| New RPC URL | http://127.0.0.1:8545 |
120120
| Chain ID | 1337 |

packages/poh-signer-api/.env.example

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ POH_API_URL=http://linea-poh-api-generic-app
1111
# Web3Signer
1212
WEB3SIGNER_BASE_URL=http://localhost:9000
1313
WEB3SIGNER_PUBLIC_KEY=0xba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e53807205fa2f08eec74f4
14-
WEB3SIGNER_KEYSTORE_PATH=
15-
WEB3SIGNER_KEYSTORE_PASSPHRASE=
16-
WEB3SIGNER_TRUSTED_STORE_PATH=
17-
WEB3SIGNER_TRUSTED_STORE_PASSPHRASE=
14+
WEB3SIGNER_KEYSTORE_PATH=certs/poh-signer-client-keystore.p12
15+
WEB3SIGNER_KEYSTORE_PASSPHRASE=changeit
16+
WEB3SIGNER_TRUSTED_STORE_PATH=certs/web3signer-truststore.p12
17+
WEB3SIGNER_TRUSTED_STORE_PASSPHRASE=changeit
4.17 KB
Binary file not shown.
1.18 KB
Binary file not shown.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus, } from '@nestjs/common';
2+
import { Response } from 'express';
3+
4+
@Catch()
5+
export class HttpExceptionFilter implements ExceptionFilter {
6+
catch(exception: unknown, host: ArgumentsHost) {
7+
const ctx = host.switchToHttp();
8+
const response = ctx.getResponse<Response>();
9+
const request = ctx.getRequest();
10+
11+
const status =
12+
exception instanceof HttpException
13+
? exception.getStatus()
14+
: HttpStatus.INTERNAL_SERVER_ERROR;
15+
16+
const message =
17+
exception instanceof HttpException
18+
? exception.message
19+
: 'Internal server error';
20+
21+
// Don't log here - logging is already done in services/controllers before throwing
22+
response.status(status).json({
23+
statusCode: status,
24+
timestamp: new Date().toISOString(),
25+
path: request.url,
26+
message,
27+
});
28+
}
29+
}

packages/poh-signer-api/src/main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
66

77
import { AppModule } from './app.module';
88
import type { CorsConfig, SwaggerConfig } from 'src/config/config.interface';
9+
import { HttpExceptionFilter } from './filters/http-exception.filter';
910

1011
async function bootstrap() {
1112
const app = await NestFactory.create(AppModule);
1213

1314
// Winston Logger
1415
app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));
1516

17+
app.useGlobalFilters(new HttpExceptionFilter());
18+
1619
// Validation
1720
app.useGlobalPipes(new ValidationPipe());
1821

packages/poh-signer-api/src/modules/poh/poh.controller.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,23 @@ export class PohController {
2222
async signMessage(@Param('address') address: Address): Promise<string> {
2323
if (!isAddress(address)) {
2424
this.logger.warn(`Invalid Ethereum address received: ${address}`);
25-
throw new HttpException('Invalid Ethereum address', HttpStatus.BAD_REQUEST);
26-
}
27-
try {
28-
return await this.pohService.signMessage(address);
29-
} catch (error) {
30-
this.logger.error(error);
31-
throw new HttpException(error.message, HttpStatus.BAD_REQUEST);
25+
throw new HttpException(
26+
'Invalid Ethereum address',
27+
HttpStatus.BAD_REQUEST,
28+
);
3229
}
30+
return this.pohService.signMessage(address);
3331
}
3432

3533
@Get('v2/:address')
3634
async signMessageV2(@Param('address') address: Address): Promise<string> {
3735
if (!isAddress(address)) {
3836
this.logger.warn(`Invalid Ethereum address received: ${address}`);
39-
throw new HttpException('Invalid Ethereum address', HttpStatus.BAD_REQUEST);
40-
}
41-
try {
42-
return await this.pohService.signMessage(address, true);
43-
} catch (error) {
44-
this.logger.error(error);
45-
throw new HttpException(error.message, HttpStatus.BAD_REQUEST);
37+
throw new HttpException(
38+
'Invalid Ethereum address',
39+
HttpStatus.BAD_REQUEST,
40+
);
4641
}
42+
return this.pohService.signMessage(address, true);
4743
}
4844
}

packages/poh-signer-api/src/modules/poh/poh.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ export class PohService {
4343
const message = {
4444
to: address,
4545
};
46+
4647
const serializedData = ethers.TypedDataEncoder.encode(
4748
domain,
4849
types,
4950
message,
5051
);
51-
return await this.signerService.signTypedData(serializedData);
52+
53+
return this.signerService.signTypedData(serializedData);
5254
} catch (error) {
5355
this.logger.error({ address, error });
5456
throw error;

packages/poh-signer-api/src/modules/signer/signer.service.ts

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import path from 'path';
1212
export class SignerService {
1313
private readonly logger = new Logger(SignerService.name);
1414
private readonly axiosInstance: AxiosInstance;
15-
private httpsAgent: Agent | null = null;
15+
private httpsAgent: Agent;
1616

1717
constructor(private readonly configService: ConfigService) {
1818
this.axiosInstance = axios.create();
@@ -27,34 +27,50 @@ export class SignerService {
2727
web3signer.baseUrl,
2828
);
2929

30+
this.logger.debug({
31+
message: 'Calling Web3Signer to sign typed data',
32+
url: url.href,
33+
publicKey: web3signer.publicKey,
34+
dataLength: data.length,
35+
});
36+
3037
try {
38+
const startTime = Date.now();
3139
const response = await this.axiosInstance.post(
3240
url.href,
3341
{
3442
data: data,
3543
},
3644
{
37-
httpsAgent:
38-
process.env.NODE_ENV !== 'development' ? this.httpsAgent : undefined,
45+
httpsAgent: this.httpsAgent,
3946
},
4047
);
4148

49+
const duration = Date.now() - startTime;
50+
51+
this.logger.log({
52+
message: 'Successfully signed typed data with Web3Signer',
53+
url: url.href,
54+
duration: `${duration}ms`,
55+
signatureLength: response.data?.length || 0,
56+
});
57+
4258
return response.data;
4359
} catch (error) {
4460
this.logger.error({
4561
message: 'Failed to sign typed data',
46-
url,
62+
url: url.href,
4763
error: error.message,
4864
stack: error.stack,
65+
statusCode: error.response?.status,
66+
statusText: error.response?.statusText,
67+
responseData: error.response?.data,
4968
});
5069
throw error;
5170
}
5271
}
5372

54-
convertToPem(
55-
p12Der: string | forge.util.ByteStringBuffer,
56-
password: string,
57-
) {
73+
convertToPem(p12Der: string | forge.util.ByteStringBuffer, password: string) {
5874
const p12Asn1 = forge.asn1.fromDer(p12Der);
5975
const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, password);
6076

@@ -69,13 +85,12 @@ export class SignerService {
6985
throw new Error('Certificate not found in P12');
7086
}
7187

72-
const pemCertificate = forge.pki.certificateToPem(certificate.cert);
73-
return { pemCertificate };
88+
return forge.pki.certificateToPem(certificate.cert);
7489
}
7590

7691
private validateWeb3SignerConfig(): void {
7792
const web3signer = this.configService.get<Web3SignerConfig>('web3signer');
78-
93+
7994
if (!web3signer) {
8095
throw new Error('Web3Signer configuration is missing');
8196
}
@@ -95,12 +110,6 @@ export class SignerService {
95110
}
96111
}
97112

98-
// Skip certificate validation in development mode
99-
if (process.env.NODE_ENV === 'development') {
100-
this.logger.log('Skipping certificate configuration validation in development mode');
101-
return;
102-
}
103-
104113
// Validate certificate fields required in non-development environments
105114
const certificateRequiredFields: (keyof Web3SignerConfig)[] = [
106115
'keystorePath',
@@ -120,12 +129,6 @@ export class SignerService {
120129
}
121130

122131
private initializeHttpsAgent(): void {
123-
// Skip HTTPS agent initialization in development
124-
if (process.env.NODE_ENV === 'development') {
125-
this.logger.log('Skipping HTTPS agent initialization in development mode');
126-
return;
127-
}
128-
129132
const web3signer = this.configService.get<Web3SignerConfig>('web3signer');
130133

131134
try {
@@ -152,20 +155,29 @@ export class SignerService {
152155
trustedStorePath: string,
153156
trustedStorePassphrase: string,
154157
): Agent {
155-
const trustedStoreFile = readFileSync(
156-
path.resolve(process.cwd(), trustedStorePath),
157-
{ encoding: 'binary' },
158-
);
158+
this.logger.log('Creating HTTPS agent with mTLS configuration');
159+
160+
// Load client certificate (pfx contains both cert and private key)
161+
const keystoreFullPath = path.resolve(process.cwd(), keystorePath);
162+
const clientPfx = readFileSync(keystoreFullPath);
163+
164+
// Load trusted CA certificate (server certificate)
165+
const trustedStoreFullPath = path.resolve(process.cwd(), trustedStorePath);
166+
const trustedStoreFile = readFileSync(trustedStoreFullPath, {
167+
encoding: 'binary',
168+
});
159169

160-
const { pemCertificate } = this.convertToPem(
170+
const caCertPem = this.convertToPem(
161171
trustedStoreFile,
162172
trustedStorePassphrase,
163173
);
164174

165175
return new Agent({
166-
pfx: readFileSync(path.resolve(process.cwd(), keystorePath)),
176+
pfx: clientPfx,
167177
passphrase: keystorePassphrase,
168-
ca: pemCertificate,
178+
ca: caCertPem,
179+
rejectUnauthorized: true,
180+
requestCert: true,
169181
});
170182
}
171183
}

services/web3signer/.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
# Ignore keyFiles
2-
keyFiles/*.yaml
1+
# Ignore key-files
2+
key-files/*.yaml

0 commit comments

Comments
 (0)