Skip to content

Commit a53322d

Browse files
authored
feat: Use existing key to create an account (#18611)
Signed-off-by: Matt Hess <[email protected]>
1 parent 8af03e2 commit a53322d

File tree

5 files changed

+127
-38
lines changed

5 files changed

+127
-38
lines changed

hedera-node/test-clients/src/yahcli/java/com/hedera/services/yahcli/commands/accounts/CreateCommand.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,23 @@ public class CreateCommand implements Callable<Integer> {
5757
@CommandLine.Option(
5858
names = {"-k", "--keyType"},
5959
paramLabel = "keyType",
60-
description = "Type of key to use for the new account: ED25519 or SECP256K1",
60+
description =
61+
"Type of key to generate for the new account: ED25519 or SECP256K1 (superseded by --keyfile or --passFile)",
6162
defaultValue = "ED25519")
6263
String keyType;
6364

65+
@CommandLine.Option(
66+
names = "--keyFile",
67+
paramLabel = "keyFile",
68+
description = "Path to the key (PEM) file to use for the new account")
69+
String keyFile;
70+
71+
@CommandLine.Option(
72+
names = "--passFile",
73+
paramLabel = "passFile",
74+
description = "Path to the password file for the existing key (PEM) file")
75+
String passFile;
76+
6477
@Override
6578
public Integer call() throws Exception {
6679
final var yahcli = accountsCommand.getYahcli();
@@ -69,7 +82,7 @@ public Integer call() throws Exception {
6982
final var noveltyLoc = config.keysLoc() + File.separator + NOVELTY + ".pem";
7083
final SigControl sigType = ParseUtils.keyTypeFromParam(keyType);
7184
// Since we are creating an account, we expect the caller to explicitly specify the key type
72-
if (sigType == null) {
85+
if (!CreateSuite.existingKeyPresent(keyFile, passFile) && sigType == null) {
7386
COMMON_MESSAGES.warn("Invalid key type: " + keyType + ". Must be 'ED25519' or 'SECP256K1'");
7487
return 1;
7588
}
@@ -85,7 +98,9 @@ public Integer call() throws Exception {
8598
noveltyLoc,
8699
sigType,
87100
retries,
88-
effectiveReceiverSigRequired);
101+
effectiveReceiverSigRequired,
102+
keyFile,
103+
passFile);
89104
delegate.runSuiteSync();
90105

91106
if (delegate.getFinalSpecs().get(0).getStatus() == HapiSpec.SpecStatus.PASSED) {

hedera-node/test-clients/src/yahcli/java/com/hedera/services/yahcli/suites/CreateSuite.java

+30-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK;
66

77
import com.hedera.services.bdd.spec.HapiSpec;
8+
import com.hedera.services.bdd.spec.SpecOperation;
89
import com.hedera.services.bdd.spec.keys.SigControl;
910
import com.hedera.services.bdd.spec.transactions.TxnUtils;
1011
import com.hedera.services.bdd.spec.transactions.TxnVerbs;
@@ -39,6 +40,8 @@ public class CreateSuite extends HapiSuite {
3940
private final boolean receiverSigRequired;
4041

4142
private final String novelTarget;
43+
private final String keyLoc;
44+
private final String passLoc;
4245

4346
private final AtomicLong createdNo = new AtomicLong(0);
4447

@@ -49,14 +52,18 @@ public CreateSuite(
4952
final String novelTarget,
5053
final SigControl sigType,
5154
final int numBusyRetries,
52-
final boolean receiverSigRequired) {
55+
final boolean receiverSigRequired,
56+
final String keyLoc,
57+
final String passLoc) {
5358
this.memo = memo;
5459
this.specConfig = specConfig;
5560
this.novelTarget = novelTarget;
5661
this.sigType = sigType;
5762
this.numBusyRetries = numBusyRetries;
5863
this.initialBalance = initialBalance;
5964
this.receiverSigRequired = receiverSigRequired;
65+
this.keyLoc = keyLoc;
66+
this.passLoc = passLoc;
6067
}
6168

6269
@Override
@@ -73,13 +80,22 @@ final Stream<DynamicTest> doCreate() {
7380
final var newKey = "newKey";
7481
final var success = new AtomicBoolean(false);
7582
final var novelPass = TxnUtils.randomAlphaNumeric(12);
83+
84+
// Default operation of creating a new key is assigned
7685
NewSpecKey newSpecKey = UtilVerbs.newKeyNamed(newKey)
7786
.exportingTo(novelTarget, novelPass)
7887
.shape(sigType);
7988
newSpecKey = (sigType == SigControl.ED25519_ON) ? newSpecKey.includingEd25519Mnemonic() : newSpecKey;
89+
90+
// If an existing key is specified, use that instead of generating a new one
91+
SpecOperation keyOp = newSpecKey;
92+
if (usingExistingKey()) {
93+
keyOp = UtilVerbs.keyFromFile(newKey, keyLoc);
94+
}
95+
8096
return HapiSpec.customHapiSpec("DoCreate")
8197
.withProperties(specConfig)
82-
.given(newSpecKey)
98+
.given(keyOp)
8399
.when(UtilVerbs.withOpContext((spec, opLog) -> {
84100
int attemptNo = 1;
85101
do {
@@ -109,7 +125,10 @@ final Stream<DynamicTest> doCreate() {
109125
} while (attemptNo++ <= numBusyRetries);
110126
}))
111127
.then(UtilVerbs.withOpContext((spec, opLog) -> {
112-
if (success.get()) {
128+
final boolean completedSuccessfully = success.get();
129+
if (completedSuccessfully && usingExistingKey()) {
130+
System.out.println(".i. Key '" + keyLoc + "' used for new account");
131+
} else if (completedSuccessfully) {
113132
final var locs = new ArrayList<String>() {
114133
{
115134
add(novelTarget);
@@ -138,4 +157,12 @@ protected Logger getResultsLogger() {
138157
public AtomicLong getCreatedNo() {
139158
return createdNo;
140159
}
160+
161+
public static boolean existingKeyPresent(String keyLoc, String passLoc) {
162+
return keyLoc != null && !keyLoc.isBlank() && passLoc != null && !passLoc.isBlank();
163+
}
164+
165+
private boolean usingExistingKey() {
166+
return existingKeyPresent(keyLoc, passLoc);
167+
}
141168
}

hedera-node/test-clients/yahcli/README.md

+77-30
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,28 @@ _previewnet/keys/account1234.words_.) If the `-k SECP256K1` option is used, the
224224
Secp256k1 key. A PEM file and .pass file are still created, but this algorithm doesn't support mnemonic keys, so the
225225
`.words` file is _not_ created.
226226

227+
Yahcli now supports creating a new account with an existing key (either Ed25519 or Secp256k1) in PEM format. Use the
228+
`--keyFile` and `--passFile` options–both required–to specify the path to the PEM file and its corresponding passphrase file.
229+
These options supersede the key type option (`--keyType`) when specified, meaning there is no need to specify the key type
230+
when using an existing key.
231+
232+
For example:
233+
234+
```
235+
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n previewnet -p 2 accounts create -d hbar -a 1 /
236+
--memo "Created with existing key" /
237+
--keyFile previewnet/keys/existing-account.pem /
238+
--passFile previewnet/keys/existing-account.pass
239+
240+
```
241+
242+
Note that the existing key **is not moved or copied** to the target network's `keys/` directory. Since yahcli typically
243+
depends on the keys in the `keys/` directory for subsequent operations, you will need to ensure that the imported key files
244+
used to create the account (i.e. the PEM file and pass file) are placed in the appropriate `keys/` directory with the
245+
standard naming, `accountXXX.pem` and `accountXXX.pass`.
246+
247+
```
248+
227249
# Updating system files
228250
229251
For this example, we will run against a `localhost` network since we will modify a system file.
@@ -233,25 +255,29 @@ The DER-encoded RSA public key of the node is in a file _node3.der_, and its TLS
233255
in a file _node3.crt_. We place these files in the directory structure below.
234256
235257
```
258+
236259
localhost
237260
├── keys
238261
│   ├── account2.pass
239262
│   ├── account2.pem
240263
│   ├── account55.pass
241264
│   └── account55.pem
242265
└── sysfiles
243-
├── certs
244-
│   └── node3.crt
245-
└── pubkeys
246-
└── node3.der
266+
├── certs
267+
│   └── node3.crt
268+
└── pubkeys
269+
└── node3.der
270+
247271
```
248272
249273
We first download the existing address book,
250274
251275
```
276+
252277
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 2 sysfiles download address-book
253278
Targeting localhost, paying with 0.0.2
254279
Downloading the address-book...OK
280+
255281
```
256282
257283
Next we edit the newly-downloaded _localhost/sysfiles/addressBook.json_ and
@@ -262,49 +288,55 @@ we tell yahcli to compute their values from the _certs/node3.crt_ and _pubkeys/n
262288
files, respectively.
263289
264290
```
291+
265292
...
266-
}, {
267-
"nodeId" : 3,
268-
"certHash" : "!",
269-
"rsaPubKey" : "!",
270-
"nodeAccount" : "0.0.6",
271-
"endpoints" : [ {
272-
"ipAddressV4" : "127.0.0.1",
273-
"port" : 50207
274-
}, {
275-
"ipAddressV4" : "127.0.0.1",
276-
"port" : 50208
277-
} ]
293+
}, {
294+
"nodeId" : 3,
295+
"certHash" : "!",
296+
"rsaPubKey" : "!",
297+
"nodeAccount" : "0.0.6",
298+
"endpoints" : [ {
299+
"ipAddressV4" : "127.0.0.1",
300+
"port" : 50207
301+
}, {
302+
"ipAddressV4" : "127.0.0.1",
303+
"port" : 50208
304+
}]
278305
...
306+
279307
```
280308
281309
And now we upload the new address book, this time using the address book admin `0.0.55` as the payer:
282310
283311
```
312+
284313
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 55 sysfiles upload address-book
314+
285315
```
286316
287317
Finally we re-download the book to see that the hex-encoded cert hash and RSA public key were uploaded as expected:
288318
289319
```
320+
290321
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 2 sysfiles download address-book
291322
Targeting localhost, paying with 0.0.2
292323
Downloading the address-book...OK
293324
$ tail -17 localhost/sysfiles/addressBook.json
294-
}, {
295-
"nodeId" : 3,
296-
"certHash" : "0ae05bde15d216781a40e7bce5303bf68926f9440eec3cb20fabe9df06b0091a205fdea86911facb4e51e46c3890c803",
297-
"rsaPubKey" : "3636303839396438343537353933653537396565363861333263303630336535393936666162613530386439343438306333656236346463613538373835326461333830353730323933636535336564393932666465343835333234636162356433353565373438313334393534623139633231633366303863363161316535643965333530316334333234353937656334646538646435383866666266646434613566333634366262376335393830636264323164643634301216763393131336631636533313864636134616635373732323462646538396332633137336633666538643039326534623866383030373130376138643965323633333166353335356135383464383037373661306162636139326530303438646433373163666530353936656464366261303737303338313432383866313039613832383035383630363562376262663238353432303434376134343336383830633361393336613666666663646162313012153335633864666561306461306537353035383530346661396163333036396438653166643762623333343530663761346261303439310a",
298-
"nodeAccount" : "0.0.6",
299-
"endpoints" : [ {
300-
"ipAddressV4" : "127.0.0.1",
301-
"port" : 50207
302-
}, {
303-
"ipAddressV4" : "127.0.0.1",
304-
"port" : 50208
305-
} ]
306-
} ]
325+
}, {
326+
"nodeId" : 3,
327+
"certHash" : "0ae05bde15d216781a40e7bce5303bf68926f9440eec3cb20fabe9df06b0091a205fdea86911facb4e51e46c3890c803",
328+
"rsaPubKey" : "3636303839396438343537353933653537396565363861333263303630336535393936666162613530386439343438306333656236346463613538373835326461333830353730323933636535336564393932666465343835333234636162356433353565373438313334393534623139633231633366303863363161316535643965333530316334333234353937656334646538646435383866666266646434613566333634366262376335393830636264323164643634301216763393131336631636533313864636134616635373732323462646538396332633137336633666538643039326534623866383030373130376138643965323633333166353335356135383464383037373661306162636139326530303438646433373163666530353936656464366261303737303338313432383866313039613832383035383630363562376262663238353432303434376134343336383830633361393336613666666663646162313012153335633864666561306461306537353035383530346661396163333036396438653166643762623333343530663761346261303439310a",
329+
"nodeAccount" : "0.0.6",
330+
"endpoints" : [ {
331+
"ipAddressV4" : "127.0.0.1",
332+
"port" : 50207
333+
}, {
334+
"ipAddressV4" : "127.0.0.1",
335+
"port" : 50208
336+
}]
337+
} ]
307338
}
339+
308340
```
309341
310342
## Uploading special files
@@ -318,44 +350,54 @@ is used for a software update ZIP, and file `0.0.159` for a telemetry upgrade ZI
318350
To upload such artifacts, use the special files names as below,
319351
320352
```
353+
321354
$ tree localhost/sysfiles/
322355
localhost/sysfiles/
323356
├── softwareUpgrade.zip
324357
└── telemetryUpgrade.zip
358+
325359
```
326360
327361
Then proceed as with any other `sysfiles upload` command,
328362
329363
```
364+
330365
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 sysfiles upload software-zip
331366
...
332367
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 sysfiles upload telemetry-zip
333368
...
369+
334370
```
335371
336372
:repeat:&nbsp;Since `yahcli:0.4.1` you can add the `--restart-from-failure` option like,
337373
338374
```
375+
339376
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 sysfiles upload software-zip --restart-from-failure
377+
340378
```
341379
342380
If the hash of the file on the network matches the hash of a prefix of the bytes you're uploading, then yahcli will
343381
automatically restart the upload after that prefix. For example,
344382
345383
```
384+
346385
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 sysfiles upload software-zip
347386
Log level is WARN
348387
Targeting localhost, paying with 0.0.2
349388
.i. Continuing upload for 0.0.150 with 34 appends already finished (out of 97 appends required)
350389
...
390+
351391
```
352392
353393
### Checking a special file hash
354394
355395
You can also directly check the SHA-384 hash of a special file with the `sysfiles hash-check` subcommand,
356396
357397
```
398+
358399
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 sysfiles hash-check software-zip
400+
359401
```
360402
361403
# Preparing an NMT software upgrade
@@ -366,9 +408,14 @@ SHA-384 hash of this ZIP must be given so the nodes can validate the integrity o
366408
staging its artifacts for NMT to use. This looks like,
367409
368410
```
411+
369412
$ docker run -it -v $(pwd):/launch gcr.io/hedera-registry/yahcli:0.4.1 -n localhost -p 58 prepare-upgrade \
413+
370414
> --upgrade-zip-hash 5d3b0e619d8513dfbf606ef00a2e83ba97d736f5f5ba61561d895ea83a6d4c34fce05d6cd74c83ec171f710e37e12aab
371-
```
415+
>
416+
> ```
417+
>
418+
> ```
372419
373420
# Launching an NMT telemetry upgrade
374421

hedera-node/test-clients/yahcli/run/build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4-
TAG=${1:-'0.6.4'}
4+
TAG=${1:-'0.6.5'}
55
SCRIPT_SOURCE="${BASH_SOURCE[0]}"
66

77
READLINK_OPTS=""

hedera-node/test-clients/yahcli/run/publish.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4-
TAG=${1:-'0.6.4'}
4+
TAG=${1:-'0.6.5'}
55
SCRIPT_SOURCE="${BASH_SOURCE[0]}"
66

77
READLINK_OPTS=""

0 commit comments

Comments
 (0)