@aztec/node-keystore 0.0.1-commit.b655e406 → 0.0.1-commit.d1f2d6c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/config.d.ts +1 -1
- package/dest/index.d.ts +1 -1
- package/dest/keystore_manager.d.ts +5 -5
- package/dest/keystore_manager.d.ts.map +1 -1
- package/dest/keystore_manager.js +19 -4
- package/dest/loader.d.ts +1 -1
- package/dest/loader.d.ts.map +1 -1
- package/dest/loader.js +76 -20
- package/dest/schemas.d.ts +2372 -426
- package/dest/schemas.d.ts.map +1 -1
- package/dest/schemas.js +57 -13
- package/dest/signer.d.ts +2 -17
- package/dest/signer.d.ts.map +1 -1
- package/dest/signer.js +7 -6
- package/dest/types.d.ts +13 -6
- package/dest/types.d.ts.map +1 -1
- package/package.json +10 -7
- package/src/keystore_manager.ts +30 -5
- package/src/loader.ts +77 -13
- package/src/schemas.ts +107 -43
- package/src/signer.ts +8 -11
- package/src/types.ts +12 -5
package/src/schemas.ts
CHANGED
|
@@ -22,38 +22,46 @@ const urlSchema = z.string().url('Invalid URL');
|
|
|
22
22
|
// Remote signer config schema
|
|
23
23
|
const remoteSignerConfigSchema = z.union([
|
|
24
24
|
urlSchema,
|
|
25
|
-
z
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
z
|
|
26
|
+
.object({
|
|
27
|
+
remoteSignerUrl: urlSchema,
|
|
28
|
+
certPath: optional(z.string()),
|
|
29
|
+
certPass: optional(z.string()),
|
|
30
|
+
})
|
|
31
|
+
.strict(),
|
|
30
32
|
]);
|
|
31
33
|
|
|
32
34
|
// Remote signer account schema
|
|
33
35
|
const remoteSignerAccountSchema = z.union([
|
|
34
36
|
schemas.EthAddress,
|
|
35
|
-
z
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
z
|
|
38
|
+
.object({
|
|
39
|
+
address: schemas.EthAddress,
|
|
40
|
+
remoteSignerUrl: urlSchema,
|
|
41
|
+
certPath: optional(z.string()),
|
|
42
|
+
certPass: optional(z.string()),
|
|
43
|
+
})
|
|
44
|
+
.strict(),
|
|
41
45
|
]);
|
|
42
46
|
|
|
43
47
|
// Encrypted keystore file schema (used for both JSON V3 ETH keys and EIP-2335 BLS keys)
|
|
44
|
-
const encryptedKeyFileSchema = z
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
const encryptedKeyFileSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
path: z.string(),
|
|
51
|
+
password: optional(z.string()),
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
48
54
|
|
|
49
55
|
// Mnemonic config schema
|
|
50
|
-
const mnemonicConfigSchema = z
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
const mnemonicConfigSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
mnemonic: z.string().min(1, 'Mnemonic cannot be empty'),
|
|
59
|
+
addressIndex: z.number().int().min(0).default(0),
|
|
60
|
+
accountIndex: z.number().int().min(0).default(0),
|
|
61
|
+
addressCount: z.number().int().min(1).default(1),
|
|
62
|
+
accountCount: z.number().int().min(1).default(1),
|
|
63
|
+
})
|
|
64
|
+
.strict();
|
|
57
65
|
|
|
58
66
|
// EthAccount schema
|
|
59
67
|
const ethAccountSchema = z.union([ethPrivateKeySchema, remoteSignerAccountSchema, encryptedKeyFileSchema]);
|
|
@@ -67,10 +75,12 @@ const blsAccountSchema = z.union([blsPrivateKeySchema, encryptedKeyFileSchema]);
|
|
|
67
75
|
// AttesterAccount schema: either EthAccount or { eth: EthAccount, bls?: BLSAccount }
|
|
68
76
|
const attesterAccountSchema = z.union([
|
|
69
77
|
ethAccountSchema,
|
|
70
|
-
z
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
z
|
|
79
|
+
.object({
|
|
80
|
+
eth: ethAccountSchema,
|
|
81
|
+
bls: optional(blsAccountSchema),
|
|
82
|
+
})
|
|
83
|
+
.strict(),
|
|
74
84
|
]);
|
|
75
85
|
|
|
76
86
|
// AttesterAccounts schema: AttesterAccount | AttesterAccount[] | MnemonicConfig
|
|
@@ -79,33 +89,87 @@ const attesterAccountsSchema = z.union([attesterAccountSchema, z.array(attesterA
|
|
|
79
89
|
// Prover keystore schema
|
|
80
90
|
const proverKeyStoreSchema = z.union([
|
|
81
91
|
ethAccountSchema,
|
|
82
|
-
z
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
z
|
|
93
|
+
.object({
|
|
94
|
+
id: schemas.EthAddress,
|
|
95
|
+
publisher: ethAccountsSchema,
|
|
96
|
+
})
|
|
97
|
+
.strict(),
|
|
86
98
|
]);
|
|
87
99
|
|
|
88
|
-
// Validator keystore schema
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
// Validator keystore schema for v1 (feeRecipient required)
|
|
101
|
+
const validatorKeyStoreSchemaV1 = z
|
|
102
|
+
.object({
|
|
103
|
+
attester: attesterAccountsSchema,
|
|
104
|
+
coinbase: optional(schemas.EthAddress),
|
|
105
|
+
publisher: optional(ethAccountsSchema),
|
|
106
|
+
feeRecipient: AztecAddress.schema,
|
|
107
|
+
remoteSigner: optional(remoteSignerConfigSchema),
|
|
108
|
+
fundingAccount: optional(ethAccountSchema),
|
|
109
|
+
})
|
|
110
|
+
.strict();
|
|
111
|
+
|
|
112
|
+
// Validator keystore schema for v2 (feeRecipient optional, can fall back to top-level)
|
|
113
|
+
const validatorKeyStoreSchemaV2 = z
|
|
114
|
+
.object({
|
|
115
|
+
attester: attesterAccountsSchema,
|
|
116
|
+
coinbase: optional(schemas.EthAddress),
|
|
117
|
+
publisher: optional(ethAccountsSchema),
|
|
118
|
+
feeRecipient: optional(AztecAddress.schema),
|
|
119
|
+
remoteSigner: optional(remoteSignerConfigSchema),
|
|
120
|
+
fundingAccount: optional(ethAccountSchema),
|
|
121
|
+
})
|
|
122
|
+
.strict();
|
|
123
|
+
|
|
124
|
+
// Schema v1 - original format
|
|
125
|
+
const keystoreSchemaV1 = z
|
|
100
126
|
.object({
|
|
101
127
|
schemaVersion: z.literal(1),
|
|
102
|
-
validators: optional(z.array(
|
|
128
|
+
validators: optional(z.array(validatorKeyStoreSchemaV1)),
|
|
103
129
|
slasher: optional(ethAccountsSchema),
|
|
104
130
|
remoteSigner: optional(remoteSignerConfigSchema),
|
|
105
131
|
prover: optional(proverKeyStoreSchema),
|
|
106
132
|
fundingAccount: optional(ethAccountSchema),
|
|
107
133
|
})
|
|
134
|
+
.strict()
|
|
108
135
|
.refine(data => data.validators || data.prover, {
|
|
109
136
|
message: 'Keystore must have at least validators or prover configuration',
|
|
110
137
|
path: ['root'],
|
|
111
138
|
});
|
|
139
|
+
|
|
140
|
+
// Schema v2 - adds top-level publisher, coinbase, feeRecipient
|
|
141
|
+
const keystoreSchemaV2 = z
|
|
142
|
+
.object({
|
|
143
|
+
schemaVersion: z.literal(2),
|
|
144
|
+
validators: optional(z.array(validatorKeyStoreSchemaV2)),
|
|
145
|
+
slasher: optional(ethAccountsSchema),
|
|
146
|
+
remoteSigner: optional(remoteSignerConfigSchema),
|
|
147
|
+
prover: optional(proverKeyStoreSchema),
|
|
148
|
+
fundingAccount: optional(ethAccountSchema),
|
|
149
|
+
publisher: optional(ethAccountsSchema),
|
|
150
|
+
coinbase: optional(schemas.EthAddress),
|
|
151
|
+
feeRecipient: optional(AztecAddress.schema),
|
|
152
|
+
})
|
|
153
|
+
.strict()
|
|
154
|
+
.refine(data => data.validators || data.prover, {
|
|
155
|
+
message: 'Keystore must have at least validators or prover configuration',
|
|
156
|
+
path: ['root'],
|
|
157
|
+
})
|
|
158
|
+
.refine(
|
|
159
|
+
data => {
|
|
160
|
+
// If validators are present, ensure each validator has a feeRecipient or there's a top-level feeRecipient
|
|
161
|
+
if (data.validators) {
|
|
162
|
+
const hasTopLevelFeeRecipient = !!data.feeRecipient;
|
|
163
|
+
const allValidatorsHaveFeeRecipient = data.validators.every(v => v.feeRecipient);
|
|
164
|
+
return hasTopLevelFeeRecipient || allValidatorsHaveFeeRecipient;
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
message: 'Each validator must have a feeRecipient, or a top-level feeRecipient must be set for all validators',
|
|
170
|
+
path: ['feeRecipient'],
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// Main keystore schema - accepts both v1 and v2
|
|
175
|
+
export const keystoreSchema = z.union([keystoreSchemaV1, keystoreSchemaV2]);
|
package/src/signer.ts
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Common interface for different signing backends (local, remote, encrypted)
|
|
5
5
|
*/
|
|
6
|
-
import type { EthSigner } from '@aztec/ethereum';
|
|
6
|
+
import type { EthSigner } from '@aztec/ethereum/eth-signer';
|
|
7
7
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
8
|
-
import {
|
|
8
|
+
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
9
|
+
import { Secp256k1Signer, toRecoveryBit } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
9
10
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
10
11
|
import { Signature, type ViemTransactionSignature } from '@aztec/foundation/eth-signature';
|
|
11
12
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
12
|
-
import { withHexPrefix } from '@aztec/foundation/string';
|
|
13
|
+
import { bufferToHex, withHexPrefix } from '@aztec/foundation/string';
|
|
13
14
|
|
|
14
15
|
import {
|
|
15
16
|
type TransactionSerializable,
|
|
@@ -243,10 +244,6 @@ export class RemoteSigner implements EthSigner {
|
|
|
243
244
|
* Make a JSON-RPC eth_signTransaction request.
|
|
244
245
|
*/
|
|
245
246
|
private async makeJsonRpcSignTransactionRequest(tx: TransactionSerializable): Promise<Signature> {
|
|
246
|
-
if (tx.type !== 'eip1559') {
|
|
247
|
-
throw new Error('This signer does not support tx type: ' + tx.type);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
247
|
const txObject: RemoteSignerTxObject = {
|
|
251
248
|
from: this.address.toString(),
|
|
252
249
|
to: tx.to ?? null,
|
|
@@ -260,10 +257,10 @@ export class RemoteSigner implements EthSigner {
|
|
|
260
257
|
? withHexPrefix(tx.maxPriorityFeePerGas.toString(16))
|
|
261
258
|
: undefined,
|
|
262
259
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
260
|
+
maxFeePerBlobGas:
|
|
261
|
+
typeof tx.maxFeePerBlobGas !== 'undefined' ? withHexPrefix(tx.maxFeePerBlobGas.toString(16)) : undefined,
|
|
262
|
+
blobVersionedHashes: tx.blobVersionedHashes,
|
|
263
|
+
blobs: tx.blobs?.map(blob => (typeof blob === 'string' ? blob : bufferToHex(Buffer.from(blob)))),
|
|
267
264
|
};
|
|
268
265
|
|
|
269
266
|
let rawTxHex = await this.makeJsonRpcRequest('eth_signTransaction', txObject);
|
package/src/types.ts
CHANGED
|
@@ -91,18 +91,19 @@ export type ValidatorKeyStore = {
|
|
|
91
91
|
attester: AttesterAccounts;
|
|
92
92
|
/**
|
|
93
93
|
* Coinbase address to use when proposing an L2 block as any of the validators in this configuration block.
|
|
94
|
-
* Falls back to the attester address if not set.
|
|
94
|
+
* Falls back to the keystore-level coinbase, then to the attester address if not set.
|
|
95
95
|
*/
|
|
96
96
|
coinbase?: EthAddress;
|
|
97
97
|
/**
|
|
98
98
|
* One or more EOAs used for sending block proposal L1 txs for all validators in this configuration block.
|
|
99
|
-
* Falls back to the attester account if not set.
|
|
99
|
+
* Falls back to the keystore-level publisher, then to the attester account if not set.
|
|
100
100
|
*/
|
|
101
101
|
publisher?: EthAccounts;
|
|
102
102
|
/**
|
|
103
103
|
* Fee recipient address to use when proposing an L2 block as any of the validators in this configuration block.
|
|
104
|
+
* Falls back to the keystore-level feeRecipient if not set.
|
|
104
105
|
*/
|
|
105
|
-
feeRecipient
|
|
106
|
+
feeRecipient?: AztecAddress;
|
|
106
107
|
/**
|
|
107
108
|
* Default remote signer for all accounts in this block.
|
|
108
109
|
*/
|
|
@@ -114,8 +115,8 @@ export type ValidatorKeyStore = {
|
|
|
114
115
|
};
|
|
115
116
|
|
|
116
117
|
export type KeyStore = {
|
|
117
|
-
/** Schema version of this keystore file (
|
|
118
|
-
schemaVersion:
|
|
118
|
+
/** Schema version of this keystore file (1 or 2). */
|
|
119
|
+
schemaVersion: 1 | 2;
|
|
119
120
|
/** Validator configurations. */
|
|
120
121
|
validators?: ValidatorKeyStore[];
|
|
121
122
|
/** One or more accounts used for creating slash payloads on L1. Does not create slash payloads if not set. */
|
|
@@ -126,4 +127,10 @@ export type KeyStore = {
|
|
|
126
127
|
prover?: ProverKeyStore;
|
|
127
128
|
/** Used for automatically funding publisher accounts if there is none defined in the corresponding ValidatorKeyStore*/
|
|
128
129
|
fundingAccount?: EthAccount;
|
|
130
|
+
/** Default publisher accounts for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
131
|
+
publisher?: EthAccounts;
|
|
132
|
+
/** Default coinbase address for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
133
|
+
coinbase?: EthAddress;
|
|
134
|
+
/** Default fee recipient address for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
135
|
+
feeRecipient?: AztecAddress;
|
|
129
136
|
};
|