@aztec/node-keystore 2.1.9 → 2.1.11
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/keystore_manager.d.ts +3 -3
- package/dest/keystore_manager.d.ts.map +1 -1
- package/dest/keystore_manager.js +19 -4
- package/dest/loader.d.ts.map +1 -1
- package/dest/loader.js +76 -20
- package/dest/schemas.d.ts +1948 -2
- package/dest/schemas.d.ts.map +1 -1
- package/dest/schemas.js +49 -5
- package/dest/signer.d.ts.map +1 -1
- package/dest/signer.js +5 -5
- package/dest/types.d.ts +12 -5
- package/dest/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/keystore_manager.ts +29 -4
- package/src/loader.ts +77 -13
- package/src/schemas.ts +54 -5
- package/src/signer.ts +5 -9
- package/src/types.ts +12 -5
package/dest/schemas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG/D,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AACtC,eAAO,MAAM,mBAAmB,kDAGK,CAAC;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG/D,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AACtC,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AA4JtC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAgD,CAAC"}
|
package/dest/schemas.js
CHANGED
|
@@ -78,8 +78,8 @@ const proverKeyStoreSchema = z.union([
|
|
|
78
78
|
publisher: ethAccountsSchema
|
|
79
79
|
}).strict()
|
|
80
80
|
]);
|
|
81
|
-
// Validator keystore schema
|
|
82
|
-
const
|
|
81
|
+
// Validator keystore schema for v1 (feeRecipient required)
|
|
82
|
+
const validatorKeyStoreSchemaV1 = z.object({
|
|
83
83
|
attester: attesterAccountsSchema,
|
|
84
84
|
coinbase: optional(schemas.EthAddress),
|
|
85
85
|
publisher: optional(ethAccountsSchema),
|
|
@@ -87,10 +87,19 @@ const validatorKeyStoreSchema = z.object({
|
|
|
87
87
|
remoteSigner: optional(remoteSignerConfigSchema),
|
|
88
88
|
fundingAccount: optional(ethAccountSchema)
|
|
89
89
|
}).strict();
|
|
90
|
-
//
|
|
91
|
-
|
|
90
|
+
// Validator keystore schema for v2 (feeRecipient optional, can fall back to top-level)
|
|
91
|
+
const validatorKeyStoreSchemaV2 = z.object({
|
|
92
|
+
attester: attesterAccountsSchema,
|
|
93
|
+
coinbase: optional(schemas.EthAddress),
|
|
94
|
+
publisher: optional(ethAccountsSchema),
|
|
95
|
+
feeRecipient: optional(AztecAddress.schema),
|
|
96
|
+
remoteSigner: optional(remoteSignerConfigSchema),
|
|
97
|
+
fundingAccount: optional(ethAccountSchema)
|
|
98
|
+
}).strict();
|
|
99
|
+
// Schema v1 - original format
|
|
100
|
+
const keystoreSchemaV1 = z.object({
|
|
92
101
|
schemaVersion: z.literal(1),
|
|
93
|
-
validators: optional(z.array(
|
|
102
|
+
validators: optional(z.array(validatorKeyStoreSchemaV1)),
|
|
94
103
|
slasher: optional(ethAccountsSchema),
|
|
95
104
|
remoteSigner: optional(remoteSignerConfigSchema),
|
|
96
105
|
prover: optional(proverKeyStoreSchema),
|
|
@@ -101,3 +110,38 @@ export const keystoreSchema = z.object({
|
|
|
101
110
|
'root'
|
|
102
111
|
]
|
|
103
112
|
});
|
|
113
|
+
// Schema v2 - adds top-level publisher, coinbase, feeRecipient
|
|
114
|
+
const keystoreSchemaV2 = z.object({
|
|
115
|
+
schemaVersion: z.literal(2),
|
|
116
|
+
validators: optional(z.array(validatorKeyStoreSchemaV2)),
|
|
117
|
+
slasher: optional(ethAccountsSchema),
|
|
118
|
+
remoteSigner: optional(remoteSignerConfigSchema),
|
|
119
|
+
prover: optional(proverKeyStoreSchema),
|
|
120
|
+
fundingAccount: optional(ethAccountSchema),
|
|
121
|
+
publisher: optional(ethAccountsSchema),
|
|
122
|
+
coinbase: optional(schemas.EthAddress),
|
|
123
|
+
feeRecipient: optional(AztecAddress.schema)
|
|
124
|
+
}).strict().refine((data)=>data.validators || data.prover, {
|
|
125
|
+
message: 'Keystore must have at least validators or prover configuration',
|
|
126
|
+
path: [
|
|
127
|
+
'root'
|
|
128
|
+
]
|
|
129
|
+
}).refine((data)=>{
|
|
130
|
+
// If validators are present, ensure each validator has a feeRecipient or there's a top-level feeRecipient
|
|
131
|
+
if (data.validators) {
|
|
132
|
+
const hasTopLevelFeeRecipient = !!data.feeRecipient;
|
|
133
|
+
const allValidatorsHaveFeeRecipient = data.validators.every((v)=>v.feeRecipient);
|
|
134
|
+
return hasTopLevelFeeRecipient || allValidatorsHaveFeeRecipient;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}, {
|
|
138
|
+
message: 'Each validator must have a feeRecipient, or a top-level feeRecipient must be set for all validators',
|
|
139
|
+
path: [
|
|
140
|
+
'feeRecipient'
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
// Main keystore schema - accepts both v1 and v2
|
|
144
|
+
export const keystoreSchema = z.union([
|
|
145
|
+
keystoreSchemaV1,
|
|
146
|
+
keystoreSchemaV2
|
|
147
|
+
]);
|
package/dest/signer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAiC,MAAM,iCAAiC,CAAC;AAI3F,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EAKzB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAG3B,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,MAAM;IACX,UAAU,CAAC,EAAE,MAAM;IACnB,SAAS,CAAC,EAAE,MAAM;gBAJzB,OAAO,EAAE,MAAM,EACR,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA;CAK5B;AAED;;GAEG;AACH,qBAAa,WAAY,YAAW,SAAS;IAG/B,OAAO,CAAC,UAAU;IAF9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAErB,UAAU,EAAE,QAAQ;IAIxC,IAAI,OAAO,IAAI,UAAU,CAExB;IAED,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAIlD,aAAa,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAKjE,eAAe,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC;CAc1E;AAmBD;;GAEG;AACH,qBAAa,YAAa,YAAW,SAAS;aAE1B,OAAO,EAAE,UAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,KAAK;gBAFG,OAAO,EAAE,UAAU,EAClB,MAAM,EAAE,qBAAqB,EACtC,KAAK,GAAE,OAAO,UAAU,CAAC,KAAwB;IAG3D;;;;;;OAMG;WACU,cAAc,CACzB,eAAe,EAAE,qBAAqB,EACtC,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,GAAE,OAAO,UAAU,CAAC,KAAwB,GAChD,OAAO,CAAC,IAAI,CAAC;IAiEhB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAIxD;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAIvE,eAAe,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC;IAIzE;;OAEG;IACH;;OAEG;YACW,sBAAsB;IAcpC;;OAEG;YACW,+BAA+B;IAkB7C;;OAEG;YACW,iCAAiC;
|
|
1
|
+
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAiC,MAAM,iCAAiC,CAAC;AAI3F,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EAKzB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAG3B,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,MAAM;IACX,UAAU,CAAC,EAAE,MAAM;IACnB,SAAS,CAAC,EAAE,MAAM;gBAJzB,OAAO,EAAE,MAAM,EACR,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA;CAK5B;AAED;;GAEG;AACH,qBAAa,WAAY,YAAW,SAAS;IAG/B,OAAO,CAAC,UAAU;IAF9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAErB,UAAU,EAAE,QAAQ;IAIxC,IAAI,OAAO,IAAI,UAAU,CAExB;IAED,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAIlD,aAAa,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAKjE,eAAe,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC;CAc1E;AAmBD;;GAEG;AACH,qBAAa,YAAa,YAAW,SAAS;aAE1B,OAAO,EAAE,UAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,KAAK;gBAFG,OAAO,EAAE,UAAU,EAClB,MAAM,EAAE,qBAAqB,EACtC,KAAK,GAAE,OAAO,UAAU,CAAC,KAAwB;IAG3D;;;;;;OAMG;WACU,cAAc,CACzB,eAAe,EAAE,qBAAqB,EACtC,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,GAAE,OAAO,UAAU,CAAC,KAAwB,GAChD,OAAO,CAAC,IAAI,CAAC;IAiEhB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAIxD;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAIvE,eAAe,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC;IAIzE;;OAEG;IACH;;OAEG;YACW,sBAAsB;IAcpC;;OAEG;YACW,+BAA+B;IAkB7C;;OAEG;YACW,iCAAiC;IA2C/C;;OAEG;YACW,kBAAkB;IAyChC;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,UAAU;CAGnB"}
|
package/dest/signer.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { Secp256k1Signer, randomBytes, toRecoveryBit } from '@aztec/foundation/crypto';
|
|
7
7
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
8
8
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
9
|
-
import { withHexPrefix } from '@aztec/foundation/string';
|
|
9
|
+
import { bufferToHex, withHexPrefix } from '@aztec/foundation/string';
|
|
10
10
|
import { hashTypedData, keccak256, parseTransaction, serializeTransaction } from 'viem';
|
|
11
11
|
/**
|
|
12
12
|
* Error thrown for remote signer HTTP or JSON-RPC failures
|
|
@@ -155,9 +155,6 @@ import { hashTypedData, keccak256, parseTransaction, serializeTransaction } from
|
|
|
155
155
|
/**
|
|
156
156
|
* Make a JSON-RPC eth_signTransaction request.
|
|
157
157
|
*/ async makeJsonRpcSignTransactionRequest(tx) {
|
|
158
|
-
if (tx.type !== 'eip1559') {
|
|
159
|
-
throw new Error('This signer does not support tx type: ' + tx.type);
|
|
160
|
-
}
|
|
161
158
|
const txObject = {
|
|
162
159
|
from: this.address.toString(),
|
|
163
160
|
to: tx.to ?? null,
|
|
@@ -166,7 +163,10 @@ import { hashTypedData, keccak256, parseTransaction, serializeTransaction } from
|
|
|
166
163
|
nonce: typeof tx.nonce !== 'undefined' ? withHexPrefix(tx.nonce.toString(16)) : undefined,
|
|
167
164
|
gas: typeof tx.gas !== 'undefined' ? withHexPrefix(tx.gas.toString(16)) : undefined,
|
|
168
165
|
maxFeePerGas: typeof tx.maxFeePerGas !== 'undefined' ? withHexPrefix(tx.maxFeePerGas.toString(16)) : undefined,
|
|
169
|
-
maxPriorityFeePerGas: typeof tx.maxPriorityFeePerGas !== 'undefined' ? withHexPrefix(tx.maxPriorityFeePerGas.toString(16)) : undefined
|
|
166
|
+
maxPriorityFeePerGas: typeof tx.maxPriorityFeePerGas !== 'undefined' ? withHexPrefix(tx.maxPriorityFeePerGas.toString(16)) : undefined,
|
|
167
|
+
maxFeePerBlobGas: typeof tx.maxFeePerBlobGas !== 'undefined' ? withHexPrefix(tx.maxFeePerBlobGas.toString(16)) : undefined,
|
|
168
|
+
blobVersionedHashes: tx.blobVersionedHashes,
|
|
169
|
+
blobs: tx.blobs?.map((blob)=>typeof blob === 'string' ? blob : bufferToHex(Buffer.from(blob)))
|
|
170
170
|
};
|
|
171
171
|
let rawTxHex = await this.makeJsonRpcRequest('eth_signTransaction', txObject);
|
|
172
172
|
if (typeof rawTxHex !== 'string') {
|
package/dest/types.d.ts
CHANGED
|
@@ -78,18 +78,19 @@ export type ValidatorKeyStore = {
|
|
|
78
78
|
attester: AttesterAccounts;
|
|
79
79
|
/**
|
|
80
80
|
* Coinbase address to use when proposing an L2 block as any of the validators in this configuration block.
|
|
81
|
-
* Falls back to the attester address if not set.
|
|
81
|
+
* Falls back to the keystore-level coinbase, then to the attester address if not set.
|
|
82
82
|
*/
|
|
83
83
|
coinbase?: EthAddress;
|
|
84
84
|
/**
|
|
85
85
|
* One or more EOAs used for sending block proposal L1 txs for all validators in this configuration block.
|
|
86
|
-
* Falls back to the attester account if not set.
|
|
86
|
+
* Falls back to the keystore-level publisher, then to the attester account if not set.
|
|
87
87
|
*/
|
|
88
88
|
publisher?: EthAccounts;
|
|
89
89
|
/**
|
|
90
90
|
* Fee recipient address to use when proposing an L2 block as any of the validators in this configuration block.
|
|
91
|
+
* Falls back to the keystore-level feeRecipient if not set.
|
|
91
92
|
*/
|
|
92
|
-
feeRecipient
|
|
93
|
+
feeRecipient?: AztecAddress;
|
|
93
94
|
/**
|
|
94
95
|
* Default remote signer for all accounts in this block.
|
|
95
96
|
*/
|
|
@@ -100,8 +101,8 @@ export type ValidatorKeyStore = {
|
|
|
100
101
|
fundingAccount?: EthAccount;
|
|
101
102
|
};
|
|
102
103
|
export type KeyStore = {
|
|
103
|
-
/** Schema version of this keystore file (
|
|
104
|
-
schemaVersion:
|
|
104
|
+
/** Schema version of this keystore file (1 or 2). */
|
|
105
|
+
schemaVersion: 1 | 2;
|
|
105
106
|
/** Validator configurations. */
|
|
106
107
|
validators?: ValidatorKeyStore[];
|
|
107
108
|
/** One or more accounts used for creating slash payloads on L1. Does not create slash payloads if not set. */
|
|
@@ -112,5 +113,11 @@ export type KeyStore = {
|
|
|
112
113
|
prover?: ProverKeyStore;
|
|
113
114
|
/** Used for automatically funding publisher accounts if there is none defined in the corresponding ValidatorKeyStore*/
|
|
114
115
|
fundingAccount?: EthAccount;
|
|
116
|
+
/** Default publisher accounts for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
117
|
+
publisher?: EthAccounts;
|
|
118
|
+
/** Default coinbase address for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
119
|
+
coinbase?: EthAddress;
|
|
120
|
+
/** Default fee recipient address for all validators in this keystore. Can be overridden by individual validator configs. */
|
|
121
|
+
feeRecipient?: AztecAddress;
|
|
115
122
|
};
|
|
116
123
|
//# sourceMappingURL=types.d.ts.map
|
package/dest/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,iDAAiD;AACjD,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;AAEpC,qDAAqD;AACrD,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;AAEpC,kCAAkC;AAClC,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC;AAEzB;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,GAAG,GACH;IACE,eAAe,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAC9B,UAAU,GACV;IACE,OAAO,EAAE,UAAU,CAAC;IACpB,eAAe,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN,oHAAoH;AACpH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAEzF,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,UAAU,EAAE,GAAG,cAAc,CAAC;AAErE,MAAM,MAAM,oBAAoB,GAAG;IACjC,iFAAiF;IACjF,EAAE,EAAE,UAAU,CAAC;IACf,sDAAsD;IACtD,SAAS,EAAE,WAAW,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,UAAU,CAAC;AAE/D,oFAAoF;AACpF,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,sBAAsB,CAAC;AAEhE,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,GAAG,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,UAAU,CAAC;AAEjF,+DAA+D;AAC/D,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,eAAe,EAAE,GAAG,cAAc,CAAC;AAEpF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/node-keystore",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
]
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@aztec/ethereum": "2.1.
|
|
66
|
-
"@aztec/foundation": "2.1.
|
|
67
|
-
"@aztec/stdlib": "2.1.
|
|
65
|
+
"@aztec/ethereum": "2.1.11",
|
|
66
|
+
"@aztec/foundation": "2.1.11",
|
|
67
|
+
"@aztec/stdlib": "2.1.11",
|
|
68
68
|
"@ethersproject/wallet": "^5.7.0",
|
|
69
69
|
"tslib": "^2.4.0",
|
|
70
70
|
"viem": "npm:@aztec/viem@2.38.2",
|
package/src/keystore_manager.ts
CHANGED
|
@@ -228,7 +228,7 @@ export class KeystoreManager {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
|
-
* Create signers for validator publisher accounts (falls back to attester if not specified)
|
|
231
|
+
* Create signers for validator publisher accounts (falls back to keystore-level publisher, then to attester if not specified)
|
|
232
232
|
*/
|
|
233
233
|
createPublisherSigners(validatorIndex: number): EthSigner[] {
|
|
234
234
|
const validator = this.getValidator(validatorIndex);
|
|
@@ -240,6 +240,14 @@ export class KeystoreManager {
|
|
|
240
240
|
);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
// Fall back to keystore-level publisher
|
|
244
|
+
if (this.keystore.publisher) {
|
|
245
|
+
return this.createSignersFromEthAccounts(
|
|
246
|
+
this.keystore.publisher,
|
|
247
|
+
validator.remoteSigner || this.keystore.remoteSigner,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
243
251
|
// Fall back to attester signers
|
|
244
252
|
return this.createAttesterSigners(validatorIndex);
|
|
245
253
|
}
|
|
@@ -320,7 +328,7 @@ export class KeystoreManager {
|
|
|
320
328
|
}
|
|
321
329
|
|
|
322
330
|
/**
|
|
323
|
-
* Get coinbase address for validator (falls back to the specific attester address)
|
|
331
|
+
* Get coinbase address for validator (falls back to keystore-level coinbase, then to the specific attester address)
|
|
324
332
|
*/
|
|
325
333
|
getCoinbaseAddress(validatorIndex: number, attesterAddress: EthAddress): EthAddress {
|
|
326
334
|
const validator = this.getValidator(validatorIndex);
|
|
@@ -329,16 +337,33 @@ export class KeystoreManager {
|
|
|
329
337
|
return validator.coinbase;
|
|
330
338
|
}
|
|
331
339
|
|
|
340
|
+
// Fall back to keystore-level coinbase
|
|
341
|
+
if (this.keystore.coinbase) {
|
|
342
|
+
return this.keystore.coinbase;
|
|
343
|
+
}
|
|
344
|
+
|
|
332
345
|
// Fall back to the specific attester address
|
|
333
346
|
return attesterAddress;
|
|
334
347
|
}
|
|
335
348
|
|
|
336
349
|
/**
|
|
337
|
-
* Get fee recipient for validator
|
|
350
|
+
* Get fee recipient for validator (falls back to keystore-level feeRecipient)
|
|
338
351
|
*/
|
|
339
352
|
getFeeRecipient(validatorIndex: number): AztecAddress {
|
|
340
353
|
const validator = this.getValidator(validatorIndex);
|
|
341
|
-
|
|
354
|
+
|
|
355
|
+
if (validator.feeRecipient) {
|
|
356
|
+
return validator.feeRecipient;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Fall back to keystore-level feeRecipient
|
|
360
|
+
if (this.keystore.feeRecipient) {
|
|
361
|
+
return this.keystore.feeRecipient;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
throw new KeystoreError(
|
|
365
|
+
`No feeRecipient configured for validator ${validatorIndex}. You can set it at validator or keystore level.`,
|
|
366
|
+
);
|
|
342
367
|
}
|
|
343
368
|
|
|
344
369
|
/**
|
package/src/loader.ts
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handles loading and parsing keystore configuration files.
|
|
5
5
|
*/
|
|
6
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import type { Hex } from '@aztec/foundation/string';
|
|
7
9
|
|
|
8
10
|
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
9
11
|
import { extname, join } from 'path';
|
|
12
|
+
import { privateKeyToAddress } from 'viem/accounts';
|
|
10
13
|
|
|
11
14
|
import { keystoreSchema } from './schemas.js';
|
|
12
15
|
import type { EthAccounts, KeyStore } from './types.js';
|
|
@@ -205,12 +208,18 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
|
|
|
205
208
|
// Track attester addresses to prevent duplicates
|
|
206
209
|
const attesterAddresses = new Set<string>();
|
|
207
210
|
|
|
211
|
+
// Determine schema version: use v2 if any input is v2
|
|
212
|
+
const schemaVersion = keystores.some(ks => ks.schemaVersion === 2) ? 2 : 1;
|
|
213
|
+
|
|
208
214
|
const merged: KeyStore = {
|
|
209
|
-
schemaVersion
|
|
215
|
+
schemaVersion,
|
|
210
216
|
validators: [],
|
|
211
217
|
slasher: undefined,
|
|
212
218
|
remoteSigner: undefined,
|
|
213
219
|
prover: undefined,
|
|
220
|
+
publisher: undefined,
|
|
221
|
+
coinbase: undefined,
|
|
222
|
+
feeRecipient: undefined,
|
|
214
223
|
};
|
|
215
224
|
|
|
216
225
|
for (let i = 0; i < keystores.length; i++) {
|
|
@@ -220,8 +229,9 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
|
|
|
220
229
|
if (keystore.validators) {
|
|
221
230
|
for (const validator of keystore.validators) {
|
|
222
231
|
// Check for duplicate attester addresses
|
|
223
|
-
const attesterKeys =
|
|
224
|
-
for (
|
|
232
|
+
const attesterKeys = extractAttesterAddresses(validator.attester);
|
|
233
|
+
for (let key of attesterKeys) {
|
|
234
|
+
key = key.toLowerCase();
|
|
225
235
|
if (attesterAddresses.has(key)) {
|
|
226
236
|
throw new KeyStoreLoadError(
|
|
227
237
|
`Duplicate attester address ${key} found across keystore files`,
|
|
@@ -230,8 +240,18 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
|
|
|
230
240
|
}
|
|
231
241
|
attesterAddresses.add(key);
|
|
232
242
|
}
|
|
243
|
+
|
|
244
|
+
// When merging v1 validators into a v2+ result, preserve original fallback behavior
|
|
245
|
+
// by explicitly setting publisher/coinbase/feeRecipient if they're missing
|
|
246
|
+
if (keystore.schemaVersion !== schemaVersion) {
|
|
247
|
+
throw new KeyStoreLoadError(
|
|
248
|
+
`Cannot merge keystores with different schema versions: ${keystore.schemaVersion} and ${schemaVersion}`,
|
|
249
|
+
`keystores[${i}].schemaVersion`,
|
|
250
|
+
);
|
|
251
|
+
} else {
|
|
252
|
+
merged.validators!.push(validator);
|
|
253
|
+
}
|
|
233
254
|
}
|
|
234
|
-
merged.validators!.push(...keystore.validators);
|
|
235
255
|
}
|
|
236
256
|
|
|
237
257
|
// Merge slasher (accumulate all)
|
|
@@ -264,6 +284,45 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
|
|
|
264
284
|
}
|
|
265
285
|
merged.prover = keystore.prover;
|
|
266
286
|
}
|
|
287
|
+
|
|
288
|
+
// Merge top-level publisher (accumulate all, unless conflicting MnemonicConfigs)
|
|
289
|
+
if (keystore.publisher) {
|
|
290
|
+
if (!merged.publisher) {
|
|
291
|
+
merged.publisher = keystore.publisher;
|
|
292
|
+
} else {
|
|
293
|
+
const isMnemonic = (accounts: EthAccounts): boolean =>
|
|
294
|
+
typeof accounts === 'object' && accounts !== null && 'mnemonic' in accounts;
|
|
295
|
+
|
|
296
|
+
// If either is a mnemonic, warn and use last one (can't merge mnemonics)
|
|
297
|
+
if (isMnemonic(merged.publisher) || isMnemonic(keystore.publisher)) {
|
|
298
|
+
logger.warn(
|
|
299
|
+
'Multiple default publisher configurations found with mnemonic, using the last one (cannot merge mnemonics)',
|
|
300
|
+
);
|
|
301
|
+
merged.publisher = keystore.publisher;
|
|
302
|
+
} else {
|
|
303
|
+
// Both are non-mnemonic, accumulate them
|
|
304
|
+
const toArray = (accounts: EthAccounts): unknown[] => (Array.isArray(accounts) ? accounts : [accounts]);
|
|
305
|
+
const combined = [...toArray(merged.publisher), ...toArray(keystore.publisher)];
|
|
306
|
+
merged.publisher = combined as unknown as EthAccounts;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Merge top-level coinbase (last one wins, but warn about conflicts)
|
|
312
|
+
if (keystore.coinbase) {
|
|
313
|
+
if (merged.coinbase) {
|
|
314
|
+
logger.warn('Multiple default coinbase addresses found, using the last one');
|
|
315
|
+
}
|
|
316
|
+
merged.coinbase = keystore.coinbase;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Merge top-level feeRecipient (last one wins, but warn about conflicts)
|
|
320
|
+
if (keystore.feeRecipient) {
|
|
321
|
+
if (merged.feeRecipient) {
|
|
322
|
+
logger.warn('Multiple default feeRecipient addresses found, using the last one');
|
|
323
|
+
}
|
|
324
|
+
merged.feeRecipient = keystore.feeRecipient;
|
|
325
|
+
}
|
|
267
326
|
}
|
|
268
327
|
|
|
269
328
|
// Clean up empty arrays
|
|
@@ -284,38 +343,43 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
|
|
|
284
343
|
* @param attester The attester configuration in any supported shape.
|
|
285
344
|
* @returns Array of string keys used to detect duplicates.
|
|
286
345
|
*/
|
|
287
|
-
function
|
|
346
|
+
function extractAttesterAddresses(attester: unknown): string[] {
|
|
288
347
|
// String forms (private key or other) - return as-is for coarse uniqueness
|
|
289
348
|
if (typeof attester === 'string') {
|
|
290
|
-
|
|
349
|
+
if (attester.length === 66) {
|
|
350
|
+
return [privateKeyToAddress(attester as Hex<32>)];
|
|
351
|
+
} else {
|
|
352
|
+
return [attester];
|
|
353
|
+
}
|
|
291
354
|
}
|
|
292
355
|
|
|
293
356
|
// Arrays of attester items
|
|
294
357
|
if (Array.isArray(attester)) {
|
|
295
358
|
const keys: string[] = [];
|
|
296
359
|
for (const item of attester) {
|
|
297
|
-
keys.push(...
|
|
360
|
+
keys.push(...extractAttesterAddresses(item));
|
|
298
361
|
}
|
|
299
362
|
return keys;
|
|
300
363
|
}
|
|
301
364
|
|
|
302
365
|
if (attester && typeof attester === 'object') {
|
|
366
|
+
if (attester instanceof EthAddress) {
|
|
367
|
+
return [attester.toString()];
|
|
368
|
+
}
|
|
369
|
+
|
|
303
370
|
const obj = attester as Record<string, unknown>;
|
|
304
371
|
|
|
305
372
|
// New shape: { eth: EthAccount, bls?: BLSAccount }
|
|
306
373
|
if ('eth' in obj) {
|
|
307
|
-
return
|
|
374
|
+
return extractAttesterAddresses(obj.eth);
|
|
308
375
|
}
|
|
309
376
|
|
|
310
377
|
// Remote signer account object shape: { address, remoteSignerUrl?, ... }
|
|
311
378
|
if ('address' in obj) {
|
|
312
379
|
return [String((obj as any).address)];
|
|
313
380
|
}
|
|
314
|
-
|
|
315
|
-
// Mnemonic or other object shapes: stringify
|
|
316
|
-
return [JSON.stringify(attester)];
|
|
317
381
|
}
|
|
318
382
|
|
|
319
|
-
//
|
|
320
|
-
return [
|
|
383
|
+
// mnemonic, encrypted file just disable early duplicates checking
|
|
384
|
+
return [];
|
|
321
385
|
}
|
package/src/schemas.ts
CHANGED
|
@@ -97,8 +97,8 @@ const proverKeyStoreSchema = z.union([
|
|
|
97
97
|
.strict(),
|
|
98
98
|
]);
|
|
99
99
|
|
|
100
|
-
// Validator keystore schema
|
|
101
|
-
const
|
|
100
|
+
// Validator keystore schema for v1 (feeRecipient required)
|
|
101
|
+
const validatorKeyStoreSchemaV1 = z
|
|
102
102
|
.object({
|
|
103
103
|
attester: attesterAccountsSchema,
|
|
104
104
|
coinbase: optional(schemas.EthAddress),
|
|
@@ -109,11 +109,23 @@ const validatorKeyStoreSchema = z
|
|
|
109
109
|
})
|
|
110
110
|
.strict();
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
|
|
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
|
|
114
126
|
.object({
|
|
115
127
|
schemaVersion: z.literal(1),
|
|
116
|
-
validators: optional(z.array(
|
|
128
|
+
validators: optional(z.array(validatorKeyStoreSchemaV1)),
|
|
117
129
|
slasher: optional(ethAccountsSchema),
|
|
118
130
|
remoteSigner: optional(remoteSignerConfigSchema),
|
|
119
131
|
prover: optional(proverKeyStoreSchema),
|
|
@@ -124,3 +136,40 @@ export const keystoreSchema = z
|
|
|
124
136
|
message: 'Keystore must have at least validators or prover configuration',
|
|
125
137
|
path: ['root'],
|
|
126
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
|
@@ -9,7 +9,7 @@ import { Secp256k1Signer, randomBytes, toRecoveryBit } from '@aztec/foundation/c
|
|
|
9
9
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
10
10
|
import { Signature, type ViemTransactionSignature } from '@aztec/foundation/eth-signature';
|
|
11
11
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
12
|
-
import { withHexPrefix } from '@aztec/foundation/string';
|
|
12
|
+
import { bufferToHex, withHexPrefix } from '@aztec/foundation/string';
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
type TransactionSerializable,
|
|
@@ -243,10 +243,6 @@ export class RemoteSigner implements EthSigner {
|
|
|
243
243
|
* Make a JSON-RPC eth_signTransaction request.
|
|
244
244
|
*/
|
|
245
245
|
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
246
|
const txObject: RemoteSignerTxObject = {
|
|
251
247
|
from: this.address.toString(),
|
|
252
248
|
to: tx.to ?? null,
|
|
@@ -260,10 +256,10 @@ export class RemoteSigner implements EthSigner {
|
|
|
260
256
|
? withHexPrefix(tx.maxPriorityFeePerGas.toString(16))
|
|
261
257
|
: undefined,
|
|
262
258
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
259
|
+
maxFeePerBlobGas:
|
|
260
|
+
typeof tx.maxFeePerBlobGas !== 'undefined' ? withHexPrefix(tx.maxFeePerBlobGas.toString(16)) : undefined,
|
|
261
|
+
blobVersionedHashes: tx.blobVersionedHashes,
|
|
262
|
+
blobs: tx.blobs?.map(blob => (typeof blob === 'string' ? blob : bufferToHex(Buffer.from(blob)))),
|
|
267
263
|
};
|
|
268
264
|
|
|
269
265
|
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
|
};
|