Skip to content

Conversation

@jnmt
Copy link
Collaborator

@jnmt jnmt commented Feb 3, 2026

Description

This PR adds the context namespace to each request.

This is the first step for supporting the isolated namespace feature. The isolated namespace feature enables users to register/execute contracts on an isolated namespace without considering which namespace should be used to read/write assets when executing contracts.

For example, assume a Payment contract that can send money from one account (asset) to another account (asset) using the get(String assetId) and put(String assetId, T data) methods. The developer does not have to care about the namespace to get/put. With the namespace1 as a context, users of the namespace1 can register/execute this contract and get/put assets in their own namespace. Of course, the same contract can be run on a different namespace (e.g., namespace2) in an isolated manner, preventing access from other namespaces. So, users can easily build a multi-tenant service with the isolated namespace feature. See also the rough design doc for additional information.

Since the isolated namespace feature will introduce a lot of changes, this PR only introduces the changes for the protocol. I will create separate PRs for each small functionality after this PR. The current plan is as follows:

  • Register certificates
  • Register secrets
  • Register contracts
  • Execute contracts, including access control
  • Register functions in the non-privileged port

Related issues and/or PRs

If this PR addresses or references any issues and/or other PRs, list them here.

Changes made

Outline the specific changes made in this pull request. Include relevant details, such as added features, bug fixes, code refactoring, or improvements.

Checklist

The following is a best-effort checklist. If any items in this checklist are not applicable to this PR or are dependent on other, unmerged PRs, please still mark the checkboxes after you have read and understood each item.

  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation to reflect the changes.
  • I have considered whether similar issues could occur in other products, components, or modules if this PR is for bug fixes.
  • Any remaining open issues linked to this PR are documented and up-to-date (Jira, GitHub, etc.).
  • Tests (unit, integration, etc.) have been added for the changes.
  • My changes generate no new warnings.
  • Any dependent changes in other PRs have been merged and published.

Additional notes (optional)

Provide any additional information or notes that may be relevant to the reviewers or stakeholders.

Release notes

Provide release note text for this PR based on the guidelines at Guidelines for Writing Release Notes.

For example:

Added validation for the Consensus Commit mutation operation.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jnmt, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a fundamental enhancement by integrating a 'context namespace' into the client-side request architecture. This change enables operations to be logically grouped and isolated within distinct namespaces, improving the system's multi-tenancy capabilities and organizational structure. It touches upon core request models, client-side configuration, and the request signing mechanism to ensure consistent and secure handling of namespace-aware operations.

Highlights

  • Context Namespace Introduction: A new context_namespace field has been added to various client requests, including certificate registration, secret registration, contract registration, contract listing, contract execution, and ledger validation. This allows operations to be associated with a specific namespace.
  • Client Configuration and Service Updates: The ClientConfig class now supports configuring a context_namespace (defaulting to 'default'). The ClientService has been updated to include this namespace in the builders for all relevant requests before sending them.
  • Request Signing and Serialization: The RequestSigner utility has been modified to incorporate the context_namespace into the data serialization process for signing, ensuring that the namespace is part of the integrity check for requests.
  • Core Model Changes: The AbstractRequest class, which is the base for many request types, now includes a contextNamespace field and has updated its hashCode() and equals() methods to account for this new attribute. A new SecretRegistrationRequest model and a Namespaces utility class were also introduced.
  • Extensive Test Coverage: Numerous unit, integration, and permission tests across the client, common, and ledger modules have been updated or added to ensure the correct handling and propagation of the context_namespace.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • client/src/main/java/com/scalar/dl/client/config/ClientConfig.java
    • Added CONTEXT_NAMESPACE constant for configuration.
    • Introduced contextNamespace field and its getter.
    • Modified load() method to parse context_namespace from properties, with 'default' as fallback.
  • client/src/main/java/com/scalar/dl/client/service/ClientService.java
    • Imported Namespaces utility class.
    • Updated various methods (registerCertificate, registerSecret, registerContract, listContracts, executeContractInternal, validateLedger) to set contextNamespace in request builders if it's not the default.
  • client/src/main/java/com/scalar/dl/client/util/RequestSigner.java
    • Modified sign methods for ContractRegistrationRequest, ContractsListingRequest, ContractExecutionRequest, and LedgerValidationRequest to include contextNamespace in the data used for signature generation.
  • client/src/test/java/com/scalar/dl/client/service/ClientServiceTest.java
    • Imported Namespaces.
    • Added default contextNamespace mock in setUp for tests.
  • common/src/main/java/com/scalar/dl/ledger/contract/ContractManager.java
    • Added a null placeholder for contextNamespace in validateContract serialization (with a TODO for future implementation).
  • common/src/main/java/com/scalar/dl/ledger/crypto/SecretEntry.java
    • Added SecretRegistrationRequest import.
    • Introduced a static factory method from(SecretRegistrationRequest request).
  • common/src/main/java/com/scalar/dl/ledger/model/AbstractRequest.java
    • Added @Nullable private final String contextNamespace; field.
    • Updated constructor to accept contextNamespace.
    • Added getContextNamespace() getter.
    • Introduced serializeContextNamespace static helper method for byte serialization.
    • Modified hashCode() and equals() methods to include contextNamespace for proper comparison.
  • common/src/main/java/com/scalar/dl/ledger/model/AssetProofRetrievalRequest.java
    • Updated constructor to pass null for contextNamespace to the superclass.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/CertificateRegistrationRequest.java
    • Updated constructor to accept contextNamespace and pass it to the superclass.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/ContractExecutionRequest.java
    • Updated constructor to accept contextNamespace and pass it to the superclass.
    • Modified validateWith and serialize methods to include contextNamespace.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/ContractRegistrationRequest.java
    • Updated constructor to accept contextNamespace and pass it to the superclass.
    • Modified validateWith and serialize methods to include contextNamespace.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/ContractsListingRequest.java
    • Updated constructor to accept contextNamespace and pass it to the superclass.
    • Modified validateWith and serialize methods to include contextNamespace.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/ExecutionAbortRequest.java
    • Updated constructor to pass null for contextNamespace to the superclass.
    • Modified hashCode() and equals() methods to include the superclass's hash code and equality check.
  • common/src/main/java/com/scalar/dl/ledger/model/LedgerValidationRequest.java
    • Updated constructor to accept contextNamespace and pass it to the superclass.
    • Modified validateWith and serialize methods to include contextNamespace.
    • Modified hashCode() to include the superclass's hash code.
  • common/src/main/java/com/scalar/dl/ledger/model/SecretRegistrationRequest.java
    • New file: Defines a request for secret key registration, extending AbstractRequest and including contextNamespace.
  • common/src/main/java/com/scalar/dl/ledger/namespace/Namespaces.java
    • New file: Defines a DEFAULT constant for the default namespace name.
  • common/src/test/java/com/scalar/dl/ledger/model/CertificateRegistrationRequestTest.java
    • Added CONTEXT_NAMESPACE constant.
    • Updated constructor calls in tests to include CONTEXT_NAMESPACE.
    • Added new test cases for equals method to check contextNamespace differences.
    • Verified contextNamespace in getters test.
  • common/src/test/java/com/scalar/dl/ledger/model/ContractExecutionRequestTest.java
    • Added CONTEXT_NAMESPACE constant.
    • Updated constructor calls in tests to include CONTEXT_NAMESPACE.
    • Added new test cases for equals method to check contextNamespace differences.
    • Verified contextNamespace in getters test.
  • common/src/test/java/com/scalar/dl/ledger/model/LedgerValidationRequestTest.java
    • Added CONTEXT_NAMESPACE constant.
    • Updated constructor calls in tests to include CONTEXT_NAMESPACE.
    • Added new test cases for equals method to check contextNamespace differences.
    • Verified contextNamespace in getters test.
    • Updated serialize tests to include CONTEXT_NAMESPACE and verify byte differences.
  • common/src/test/java/com/scalar/dl/ledger/model/SecretRegistrationRequestTest.java
    • New file: Added comprehensive unit tests for SecretRegistrationRequest, covering constructor validation, equals method behavior (including contextNamespace), and getter functionality.
  • ledger/src/integration-test/java/com/scalar/dl/ledger/service/LedgerServiceEndToEndTest.java
    • Updated numerous prepareRequest and execute methods to pass null for contextNamespace in serialize and constructor calls, aligning with the new API.
  • ledger/src/integration-test/java/com/scalar/dl/ledger/service/LedgerServiceEndToEndTestBase.java
    • Replaced SecretEntry import with SecretRegistrationRequest.
    • Commented out System.setProperty and System.setSecurityManager lines related to security manager setup.
    • Updated registerCertificate and registerSecret methods to use SecretRegistrationRequest and pass null for contextNamespace.
    • Updated registerContracts to pass null for contextNamespace.
  • ledger/src/integration-test/java/com/scalar/dl/ledger/service/LedgerServiceIntegrationTest.java
    • Updated prepareRegistrationRequest and prepareExecutionRequest to pass null for contextNamespace.
  • ledger/src/integration-test/java/com/scalar/dl/ledger/service/LedgerServiceNamespaceEndToEndTest.java
    • Updated prepareRequestForCreate, prepareRequestForGet, prepareRequestForPayment, and prepareValidationRequest to pass null for contextNamespace.
  • ledger/src/main/java/com/scalar/dl/ledger/server/LedgerPrivilegedService.java
    • Removed SecretEntry import.
    • Modified registerSecret to directly accept SecretRegistrationRequest and convert it to SecretEntry internally using the new factory method.
  • ledger/src/main/java/com/scalar/dl/ledger/server/TypeConverter.java
    • Removed SecretEntry and Time imports.
    • Updated convert methods for CertificateRegistrationRequest, SecretRegistrationRequest, ContractRegistrationRequest, ContractsListingRequest, ContractExecutionRequest, and LedgerValidationRequest to correctly extract and set the contextNamespace from gRPC requests.
  • ledger/src/main/java/com/scalar/dl/ledger/service/BaseService.java
    • Added SecretRegistrationRequest import.
    • Modified register(SecretEntry entry) method signature to register(SecretRegistrationRequest request) and updated its implementation to use SecretEntry.from(request).
  • ledger/src/main/java/com/scalar/dl/ledger/service/LedgerService.java
    • Removed SecretEntry import and added SecretRegistrationRequest import.
    • Modified register(SecretEntry entry) method signature to register(SecretRegistrationRequest request).
  • ledger/src/main/java/com/scalar/dl/ledger/validation/ContractValidator.java
    • Added a null placeholder for contextNamespace in validate serialization (with a TODO for future implementation).
  • ledger/src/permission-test/java/com/scalar/dl/ledger/service/LedgerServicePermissionTest.java
    • Updated prepareExecutionRequest to pass null for contextNamespace.
  • ledger/src/test/java/com/scalar/dl/ledger/contract/ContractManagerTest.java
    • Updated createContractEntryWith to pass null for contextNamespace.
  • ledger/src/test/java/com/scalar/dl/ledger/server/LedgerPrivilegedServiceTest.java
    • Removed assertThat and ArgumentCaptor imports.
    • Updated registerCertificate and registerSecret tests to reflect the new contextNamespace parameter and direct usage of SecretRegistrationRequest.
  • ledger/src/test/java/com/scalar/dl/ledger/service/BaseServiceTest.java
    • Removed SecretEntry import.
    • Replaced secretEntry mock with secretRegistrationRequest mock.
    • Added configureSecretRegistrationRequest method.
    • Updated register_ProperSecretGiven_ShouldRegisterSecret test to use secretRegistrationRequest.
  • ledger/src/test/java/com/scalar/dl/ledger/service/LedgerServiceTest.java
    • Removed SecretEntry import.
    • Replaced secretEntry mock with secretRegistrationRequest mock.
    • Updated register_ProperSecretGiven_ShouldRegisterSecret test to use secretRegistrationRequest.
  • ledger/src/test/java/com/scalar/dl/ledger/service/LedgerValidationServiceTest.java
    • Updated serialize calls in tests to include null for contextNamespace.
  • rpc/src/main/proto/scalar.proto
    • Added context_namespace field to CertificateRegistrationRequest, SecretRegistrationRequest, ContractRegistrationRequest, ContractsListingRequest, ContractExecutionRequest, and LedgerValidationRequest messages.
Activity
  • The author jnmt initiated this pull request to introduce the concept of a context namespace for client requests.
  • The changes involve a significant refactoring of request models and client-side logic to support namespace-aware operations.
  • New data structures like SecretRegistrationRequest and Namespaces were added to facilitate this feature.
  • Existing core classes such as AbstractRequest, ClientConfig, and ClientService underwent modifications to integrate the new namespace functionality.
  • Comprehensive test updates were performed across various modules to validate the correct behavior of the new context_namespace parameter in different scenarios.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a context_namespace to various requests, which is a significant feature impacting many parts of the codebase. While the core implementation is present, there are several critical issues that need to be addressed before this can be merged.

Specifically, the signature validation logic for contracts is incomplete and marked with a TODO, which is a critical bug. The context_namespace is also lost when registering secrets. Furthermore, some requests are missing the context_namespace field, leading to inconsistencies. There is also a noticeable lack of tests for the new namespace functionality; existing tests are updated to use the default namespace, but no new tests cover non-default scenarios. I've added specific comments with details on these issues.

entry.getBinaryName(),
entry.getByteCode(),
entry.getProperties().orElse(null),
null, // TODO: use context namespace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Passing null for contextNamespace with a TODO comment is a critical issue. This will cause signature validation to fail for any contract registered with a non-default namespace. The ContractEntry class should be updated to store the contextNamespace from the ContractRegistrationRequest, and that value should be used here for correct signature validation. A similar issue exists in ContractValidator.java.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be fixed in another PR.

Comment on lines +144 to +150
public static SecretEntry from(SecretRegistrationRequest request) {
return new SecretEntry(
request.getEntityId(),
request.getKeyVersion(),
request.getSecretKey(),
Time.getCurrentUtcTimeInMillis());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The from(SecretRegistrationRequest request) method creates a SecretEntry but discards the contextNamespace from the request. The SecretEntry class itself has not been updated to store the namespace. This is a data loss issue that will likely cause problems, for example, if secrets need to be scoped by namespace. The SecretEntry class should be updated to include the contextNamespace.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SecretEntry will not include the context namespace. Anyway, registering secrets with context namespace will be supported in another PR.

ContractExecutionRequest.serialize(
ContractEntry.Key.deserialize(record.contractId()).getId(),
record.argument(),
null, // TODO: use context namespace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Passing null for contextNamespace with a TODO comment is a critical issue. This will cause signature validation to fail for any contract execution with a non-default namespace. The ContractEntry (from which the ContractMachine is created) should be updated to store the contextNamespace, and that value should be used here for correct signature validation. A similar issue exists in ContractManager.java.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be fixed in another PR.

int keyVersion,
byte[] signature) {
super(entityId, keyVersion);
super(null, entityId, keyVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The contextNamespace is hardcoded to null for AssetProofRetrievalRequest. This is inconsistent with other requests in this PR. The .proto definition for AssetProofRetrievalRequest is also missing the context_namespace field. Was this intentional? If not, it should be added for consistency. A similar issue exists for ExecutionAbortRequest.

Copy link
Collaborator Author

@jnmt jnmt Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intended. AssetProofRetrievalRequest and ExecutionAbortRequest will always be coming from the Auditor with the Auditor's signature in the default context.

Copy link
Contributor

@KodaiD KodaiD Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jnmt Even without context_namespace, can Ledger handle those requests from Auditor in a namespace-aware way? For example, can Auditor get an asset proof from the correct namespace?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KodaiD Thank you for the question! Yes, as the next line shows, the request can have the "target" namespace information.

@SuppressFBWarnings("EI_EXPOSE_REP2")
public ExecutionAbortRequest(String nonce, String entityId, int keyVersion, byte[] signature) {
super(entityId, keyVersion);
super(null, entityId, keyVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The contextNamespace is hardcoded to null for ExecutionAbortRequest. This is inconsistent with other requests in this PR. The .proto definition for ExecutionAbortRequest is also missing the context_namespace field. Was this intentional? If not, it should be added for consistency. A similar issue exists for AssetProofRetrievalRequest.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intended. AssetProofRetrievalRequest and ExecutionAbortRequest will always be coming from the Auditor with the Auditor's signature in the default context.

/** Constants related to namespaces. */
public final class Namespaces {
/** The default namespace name. */
public static final String DEFAULT = "default";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, we have NamespaceManager.DEFAULT_NAMESPACE for the default namespace name. However, both clients and servers want to refer to it, so I will newly introduce this. The places that use the old one will be refactored later.


public void register(SecretEntry entry) {
base.register(entry);
public void register(SecretRegistrationRequest request) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, I added SecretRegistrationRequest, the same as register(CertificateRegistrationRequest request).

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment on lines +908 to +910
if (!config.getContextNamespace().equals(Namespaces.DEFAULT)) {
builder.setContextNamespace(config.getContextNamespace());
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since contracts registered by old clients have a signature without context, the contract validation fails if the context namespace is included when executing the contract. To exclude the context namespace (i.e., as null) if it is default when validating the contract, new clients also need to sign without the context if it is default. It's complicated, so to avoid confusion, I think it's better to do the same for all the requests in both the client and servers (i.e., treat as null if it's the default namespace). cf. assertion in AbstractRequest

@jnmt jnmt self-assigned this Feb 4, 2026
@jnmt jnmt added the enhancement New feature or request label Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants