Skip to content

changeKeystorePassphrase silently drops blspublickey from validator keystores #793

Description

@palango

Summary

KeystoreBase.changeKeystorePassphrase destroys any non-standard top-level field in a V3 keystore. Celo validator keystores generated by geth carry a blspublickey field, so changing such a keystore's passphrase silently loses it.

Cause

packages/sdk/keystores/src/keystore-base.ts re-encrypts by decrypting the private key and building a fresh V3 object. That object only ever contains version, id, address and crypto, so everything else in the original file is dropped:

in : {address, blspublickey, crypto, id, version}
out: {address,               crypto, id, version}
              ^^^^^^^^^^^^ silently lost

There is no error and no warning — the write succeeds and the field is simply gone.

Reproduce

GETH_GEN_KEYSTORE1 in packages/sdk/keystores/src/test-constants.ts is a real geth-generated fixture containing a blspublickey. Persist it, call changeKeystorePassphrase, then re-read the raw entry: the field is absent.

Not a regression

This predates the removal of ethereumjs-wallet (#792). That library's toV3 had exactly the same behaviour, so the migration neither introduced nor worsened it. It was left alone there deliberately to keep that PR strictly behaviour-neutral and easy to review.

Suggested fix

Preserve unknown top-level fields across re-encryption — spread the parsed original and overwrite only crypto (and id), rather than constructing the object from scratch. Add a regression test using the GETH_GEN_KEYSTORE1 fixture asserting blspublickey survives a passphrase change.

Worth deciding at the same time whether importPrivateKey should be able to write such fields, or whether preservation on re-encryption is the whole scope.

Impact

Limited. @celo/keystores has no consumers inside this monorepo — celocli never reads or writes keystore files — so this only affects external npm consumers of the package who manage geth-generated validator keystores.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions