You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is a good fit for contributors who are already familiar with the Hiero C++ SDK and feel comfortable navigating the codebase.
Intermediate Issues often involve:
Exploring existing implementations
Understanding how different components work together
Making thoughtful changes that follow established patterns
The goal is to support deeper problem-solving while keeping the task clear, focused, and enjoyable to work on.
Important
🧭 About Intermediate Issues
Intermediate Issues are a great next step for contributors who enjoy digging into the codebase and reasoning about how things work.
These issues often:
Involve multiple related files or components
Encourage investigation and understanding of existing behavior
Leave room for thoughtful implementation choices
Stay focused on a clearly defined goal
Other kinds of contributions — from beginner-friendly tasks to large system-level changes — are just as valuable and use different labels.
👾 Description of the Task
AccountCreateTransaction::setECDSAKeyWithAlias — the recommended one-call way to set an account key and its derived EVM-address alias together — only accepts a private key (src/sdk/main/include/AccountCreateTransaction.h:102):
This shape blocks HSM and key-separation flows, where private key material never enters the application process — the caller holds only an ECDSAsecp256k1PublicKey and signing happens externally (HSM, KMS, hardware wallet, remote signer). Such callers today must fall back to composing two calls themselves:
That workaround works, but it bypasses the documented combined setter, is easy to get wrong (e.g. forgetting the alias entirely), and leaves the C++ SDK without parity for the public-key path being added across the sibling SDKs.
Note: the companion key-separation method setKeyWithAlias(key, ecdsaPrivateKey) (AccountCreateTransaction.h:114) has the same limitation. Whether to extend it in the same PR is left to contributor judgment (see Proposed Approach).
Add a new overload, mirroring the existing one (the existing private-key overload is retained unchanged):
/** * Set an ECDSA public key, derive its EVM address in the background, and set both the key and alias. * Intended for flows where the private key is held externally (e.g. an HSM) and only the public key * is available in-process. The corresponding private key must still sign the transaction. * * @param ecdsaPublicKey The ECDSA public key to be set. * @return A reference to this AccountCreateTransaction object with the newly-set key and alias. * @throws IllegalStateException If this AccountCreateTransaction is frozen. * @throws std::invalid_argument If the key is null.*/
AccountCreateTransaction& setECDSAKeyWithAlias(const std::shared_ptr<ECDSAsecp256k1PublicKey>& ecdsaPublicKey);
The implementation follows the existing pattern: requireNotFrozen(), null check throwing std::invalid_argument, then mKey = ecdsaPublicKey; and mAlias = ecdsaPublicKey->toEvmAddress(); (no dynamic_pointer_cast needed — the caller already hands us the typed public key).
Points that are left to contributor judgment — state your choices in the PR description:
Overload-resolution caveat. Once the overload exists, a literal setECDSAKeyWithAlias(nullptr) (or {}) becomes ambiguous. No in-repo call site does this (the only caller is AccountCreateTransactionIntegrationTests.cc:689, which passes a typed shared_ptr), but your null-check unit test must use a typed null, e.g. std::shared_ptr<ECDSAsecp256k1PublicKey>{}. Worth a sentence in the PR description.
Scope of the companion method. Decide whether to also add the analogous setKeyWithAlias(const std::shared_ptr<Key>&, const std::shared_ptr<ECDSAsecp256k1PublicKey>&) overload now or file it as a follow-up. Either is acceptable; keep the PR focused.
Related work. There is a companion issue proposing PublicKey::toEvmAddress() become a base-class virtual returning std::optional<EvmAddress>. There is no hard dependency in either direction (mAlias is already a std::optional<EvmAddress>, so mAlias = ecdsaPublicKey->toEvmAddress(); compiles before and after that change), but expect a trivial merge interaction if both land.
👩💻 Implementation Steps
Add the overload declaration directly after the existing private-key overload in src/sdk/main/include/AccountCreateTransaction.h (line 102), with Doxygen documentation matching the surrounding style.
key is set to the public key and getAlias() equals publicKey->toEvmAddress() (compare via toBytes()),
calling on a frozen transaction throws,
typed-null argument throws std::invalid_argument.
There are currently no unit tests at all for the existing private-key setECDSAKeyWithAlias overload — backfilling them in the same PR is welcome but optional.
Add an integration test in src/sdk/tests/integration/AccountCreateTransactionIntegrationTests.cc — mirror CreateTransactionWithAliasAndKeyECDSACanExecute (line 680). Simulate the HSM split: generate an ECDSAsecp256k1PrivateKey in the test, pass onlyprivateKey->getPublicKey() (cast to ECDSAsecp256k1PublicKey) to the new overload, then freezeWith(&getTestClient()).sign(privateKey) to play the role of the external signer, execute, and assert the receipt contains an account ID.
Build and run the tests:
cmake --preset linux-x64-debug -DBUILD_TESTS=ON
cmake --build --preset linux-x64-debug -j 6
# unit tests (no network needed)
ctest -C Debug --test-dir build/linux-x64-debug -R AccountCreateTransactionUnitTests
# integration tests (requires a running Solo network — see README.md)
ctest -C Debug --test-dir build/linux-x64-debug -R AccountCreateTransactionIntegrationTests
Run clang-format-17 against any file you touched.
✅ Acceptance Criteria
The new setECDSAKeyWithAlias(const std::shared_ptr<ECDSAsecp256k1PublicKey>&) overload exists with Doxygen documentation matching the surrounding style, sets mKey to the public key, and sets mAlias to the derived EVM address.
The existing private-key overload is unchanged (signature and behavior).
Unit tests cover: successful set + alias derivation, frozen-transaction throw, and typed-null std::invalid_argument throw.
An integration test exercises the external-signer flow (public key set on the transaction, signature provided separately) and verifies the account is created.
The PR description states the choices made on the judgment points above (null-ambiguity note, setKeyWithAlias scope decision).
No unrelated behavior or public API changes; all existing tests still pass.
📋 Step-by-Step Contribution Guide
To help keep contributions consistent and easy to review, we recommend following these steps:
Comment /assign to request the issue
Wait for assignment
Fork the repository and create a branch
Set up the project using the instructions in README.md
Make the requested changes
Sign each commit using -s -S
Push your branch and open a pull request
Read Workflow Guide for step-by-step workflow guidance.
Read README.md for setup instructions.
❗ Pull requests cannot be merged without S and s signed commits.
See the Signing Guide.
🤔 Additional Information
The integration test requires a local Solo network; see README.md for setup. CI also runs the integration suite.
Equivalent public-key alias setters are being introduced across the sibling SDKs (Java/JS/Go) as part of the HSM / key-separation work.
If you have questions while working on this issue, feel free to ask! Hiero-SDK-C++ Discord
🧩 Intermediate Friendly
This issue is a good fit for contributors who are already familiar with the Hiero C++ SDK and feel comfortable navigating the codebase.
Intermediate Issues often involve:
The goal is to support deeper problem-solving while keeping the task clear, focused, and enjoyable to work on.
Important
🧭 About Intermediate Issues
Intermediate Issues are a great next step for contributors who enjoy digging into the codebase and reasoning about how things work.
These issues often:
Other kinds of contributions — from beginner-friendly tasks to large system-level changes — are just as valuable and use different labels.
👾 Description of the Task
AccountCreateTransaction::setECDSAKeyWithAlias— the recommended one-call way to set an account key and its derived EVM-address alias together — only accepts a private key (src/sdk/main/include/AccountCreateTransaction.h:102):The implementation (src/sdk/main/src/AccountCreateTransaction.cc:52-70) only ever uses the private key to reach its public key:
This shape blocks HSM and key-separation flows, where private key material never enters the application process — the caller holds only an
ECDSAsecp256k1PublicKeyand signing happens externally (HSM, KMS, hardware wallet, remote signer). Such callers today must fall back to composing two calls themselves:transaction.setKeyWithoutAlias(publicKey).setAlias(publicKey->toEvmAddress());That workaround works, but it bypasses the documented combined setter, is easy to get wrong (e.g. forgetting the alias entirely), and leaves the C++ SDK without parity for the public-key path being added across the sibling SDKs.
Note: the companion key-separation method
setKeyWithAlias(key, ecdsaPrivateKey)(AccountCreateTransaction.h:114) has the same limitation. Whether to extend it in the same PR is left to contributor judgment (see Proposed Approach).Relevant files:
💡 Proposed Approach
Add a new overload, mirroring the existing one (the existing private-key overload is retained unchanged):
The implementation follows the existing pattern:
requireNotFrozen(), null check throwingstd::invalid_argument, thenmKey = ecdsaPublicKey;andmAlias = ecdsaPublicKey->toEvmAddress();(nodynamic_pointer_castneeded — the caller already hands us the typed public key).Points that are left to contributor judgment — state your choices in the PR description:
setECDSAKeyWithAlias(nullptr)(or{}) becomes ambiguous. No in-repo call site does this (the only caller isAccountCreateTransactionIntegrationTests.cc:689, which passes a typedshared_ptr), but your null-check unit test must use a typed null, e.g.std::shared_ptr<ECDSAsecp256k1PublicKey>{}. Worth a sentence in the PR description.setKeyWithAlias(const std::shared_ptr<Key>&, const std::shared_ptr<ECDSAsecp256k1PublicKey>&)overload now or file it as a follow-up. Either is acceptable; keep the PR focused.PublicKey::toEvmAddress()become a base-class virtual returningstd::optional<EvmAddress>. There is no hard dependency in either direction (mAliasis already astd::optional<EvmAddress>, somAlias = ecdsaPublicKey->toEvmAddress();compiles before and after that change), but expect a trivial merge interaction if both land.👩💻 Implementation Steps
setECDSAKeyWithAlias/setKeyWithoutAliasat lines 52-108.SetKeyWithAlias/SetKeyWithAliasFrozenpair at lines 138-167:getAlias()equalspublicKey->toEvmAddress()(compare viatoBytes()),std::invalid_argument.setECDSAKeyWithAliasoverload — backfilling them in the same PR is welcome but optional.CreateTransactionWithAliasAndKeyECDSACanExecute(line 680). Simulate the HSM split: generate anECDSAsecp256k1PrivateKeyin the test, pass onlyprivateKey->getPublicKey()(cast toECDSAsecp256k1PublicKey) to the new overload, thenfreezeWith(&getTestClient()).sign(privateKey)to play the role of the external signer, execute, and assert the receipt contains an account ID.clang-format-17against any file you touched.✅ Acceptance Criteria
setECDSAKeyWithAlias(const std::shared_ptr<ECDSAsecp256k1PublicKey>&)overload exists with Doxygen documentation matching the surrounding style, setsmKeyto the public key, and setsmAliasto the derived EVM address.std::invalid_argumentthrow.setKeyWithAliasscope decision).📋 Step-by-Step Contribution Guide
To help keep contributions consistent and easy to review, we recommend following these steps:
/assignto request the issueREADME.md-s -SRead Workflow Guide for step-by-step workflow guidance.
Read README.md for setup instructions.
❗ Pull requests cannot be merged without
Sandssigned commits.See the Signing Guide.
🤔 Additional Information
README.mdfor setup. CI also runs the integration suite.If you have questions while working on this issue, feel free to ask! Hiero-SDK-C++ Discord