Skip to content

Conversation

phroi
Copy link
Contributor

@phroi phroi commented Sep 14, 2025

Changes

  • Transformed Epoch into a class and added utility methods
  • Added comprehensive TypeDoc-style comments for Epoch-related helpers and the Epoch class (constructor, factory from, zero/one/oneCycle, arithmetic add/sub, comparison compare/eq, normalization normalized, and toUnix conversion).
  • Documented deprecated helpers: epochFrom, epochFromHex, epochToHex.
  • Explained invariants and behaviors: positive denominator enforcement, fraction reduction via GCD, negative-index normalization (borrowing whole units), carrying fractional overflow into whole number, and common-denominator alignment when adding.
  • Documented module-level constants and utilities: epochInMilliseconds and gcd.
  • Kept backward-compatible array-style properties [0], [1], [2] and documented their deprecation.

Closes #302

Love & Peace, Phroi %208

Copy link

changeset-bot bot commented Sep 14, 2025

🦋 Changeset detected

Latest commit: 920cc53

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
Name Type
@ckb-ccc/core Minor
@ckb-ccc/eip6963 Patch
@ckb-ccc/joy-id Patch
@ckb-ccc/lumos-patches Patch
@ckb-ccc/nip07 Patch
@ckb-ccc/okx Patch
@ckb-ccc/rei Patch
@ckb-ccc/shell Patch
@ckb-ccc/spore Patch
@ckb-ccc/ssri Patch
@ckb-ccc/udt Patch
@ckb-ccc/uni-sat Patch
@ckb-ccc/utxo-global Patch
@ckb-ccc/xverse Patch
@ckb-ccc/ccc Patch
ckb-ccc Patch
@ckb-ccc/connector Patch
@ckb-ccc/connector-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

netlify bot commented Sep 14, 2025

Deploy Preview for liveccc ready!

Name Link
🔨 Latest commit 920cc53
🔍 Latest deploy log https://app.netlify.com/projects/liveccc/deploys/68f1698dd9133c00085d2de4
😎 Deploy Preview https://deploy-preview-314--liveccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 17 (🔴 down 24 from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

netlify bot commented Sep 14, 2025

Deploy Preview for apiccc ready!

Name Link
🔨 Latest commit 920cc53
🔍 Latest deploy log https://app.netlify.com/projects/apiccc/deploys/68f1698d0930060008e00d3f
😎 Deploy Preview https://deploy-preview-314--apiccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 80 (🔴 down 8 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 94 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

netlify bot commented Sep 14, 2025

Deploy Preview for docsccc ready!

Name Link
🔨 Latest commit 920cc53
🔍 Latest deploy log https://app.netlify.com/projects/docsccc/deploys/68f1698d7a12080008bef8b5
😎 Deploy Preview https://deploy-preview-314--docsccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 71 (🔴 down 1 from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (no change from production)
SEO: 92 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

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.

Summary of Changes

Hello @phroi, 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 significantly refactors the Epoch representation within the @ckb-ccc/core package by converting it from a basic array-like structure to a full-fledged TypeScript class. This change aims to enhance the robustness, maintainability, and usability of epoch-related operations. The new Epoch class encapsulates complex logic for handling fractional parts, normalization, and arithmetic, while also providing a clear, well-documented API. This modernization improves type safety and prepares the codebase for more advanced features by integrating Epoch more deeply with the Molecule serialization framework.

Highlights

  • Epoch Class Introduction: The Epoch data structure has been transformed from a simple tuple [number, index, length] into a dedicated TypeScript class, providing a more object-oriented approach to epoch management.
  • New Utility Methods: The Epoch class now includes comprehensive utility methods for creation (from, zero, one, oneCycle), comparison (compare, eq), arithmetic (add, sub), normalization (normalized), and conversion (toUnix).
  • Improved Documentation: Extensive TypeDoc-style comments have been added to the Epoch class and its methods, detailing invariants, behaviors (e.g., positive denominator, fraction reduction via GCD, negative-index normalization), and usage.
  • Backward Compatibility & Deprecation: Existing tuple-based epochFrom, epochFromHex, and epochToHex helpers are deprecated, along with array-style accessors [0], [1], [2] on the Epoch class, encouraging migration to the new class methods.
  • Refactored DAO Claim Epoch Calculation: The calcDaoClaimEpoch function has been updated to leverage the new Epoch class, improving its logic and readability.
  • Zero Constant Usage: Replaced direct numFrom(0) calls with the Zero constant for improved consistency and clarity in numerical operations.
  • Generic toHex for Entities: A toHex method has been added to the base mol.Entity.Base class, allowing any Molecule entity to be easily converted to its hexadecimal representation.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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

netlify bot commented Sep 14, 2025

Deploy Preview for appccc ready!

Name Link
🔨 Latest commit 920cc53
🔍 Latest deploy log https://app.netlify.com/projects/appccc/deploys/68f1698dde4ff50008d38920
😎 Deploy Preview https://deploy-preview-314--appccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 67 (🔴 down 10 from production)
Accessibility: 89 (🟢 up 1 from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

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 significant improvement by refactoring the Epoch type into a class, enhancing readability, type safety, and maintainability. The changes are well-structured, moving epoch-related logic to a new dedicated file and providing backward compatibility. The documentation is thorough and helpful. I've found one area for improvement in the compare method to ensure its correctness with very large numbers, which I've detailed in a specific comment. Overall, this is a high-quality contribution.

@phroi
Copy link
Contributor Author

phroi commented Sep 14, 2025

/gemini review

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 is a great improvement, refactoring Epoch from a tuple-based type into a dedicated class with comprehensive utility methods and documentation. This significantly enhances readability and maintainability. The related changes, such as using the Zero constant and updating the calcDaoClaimEpoch function, are also positive. I've identified one critical issue regarding a breaking change in the serialization format of the Epoch class and one minor typo in a code example. Addressing the serialization issue is crucial for backward compatibility.

@phroi
Copy link
Contributor Author

phroi commented Sep 14, 2025

@Hanssen0 feel free to review 🤗

Phroi %16

@phroi
Copy link
Contributor Author

phroi commented Sep 14, 2025

/gemini review

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 is a great improvement, refactoring the Epoch type into a full-fledged class with comprehensive utility methods and excellent documentation. The new class-based approach significantly enhances readability and maintainability, especially evident in the simplification of calcDaoClaimEpoch. The deprecation of old helper functions and the introduction of backward-compatible properties are well-handled. I've found one area for improvement to make the new gcd utility function more robust.

@phroi
Copy link
Contributor Author

phroi commented Sep 14, 2025

/gemini review

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 is a great improvement, refactoring the Epoch type into a well-designed class with comprehensive documentation and utility methods. The approach to backward compatibility at the API level is commendable.

However, I've found a critical issue in the serialization of the new Epoch class. The implementation uses mol.struct, which changes the binary format from a packed u64 to a molecule struct. This breaks on-chain compatibility. I've left a detailed comment with a suggested fix to align the serialization with the expected CKB format.

Once this serialization issue is addressed, this will be an excellent contribution.

Copy link
Member

@Hanssen0 Hanssen0 left a comment

Choose a reason for hiding this comment

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

For me, this implementation looks more like a mathematical aspect of a mixed number, rather than a CKB epoch. I suggest that we should separate these two concepts and make the Epoch stricter than this, to avoid "incorrect" index or length.

@phroi phroi mentioned this pull request Sep 15, 2025
1 task
@phroi
Copy link
Contributor Author

phroi commented Sep 26, 2025

/gemini review

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 is a great improvement, refactoring the tuple-based Epoch into a full-featured class with comprehensive utility methods. The new Epoch class is well-designed with robust logic for construction, comparison, arithmetic, and normalization. The changes across the codebase to adopt this new class, such as removing the old helpers and using Zero for consistency, are well-executed. I've found one issue in a documentation example that should be addressed to avoid confusion for developers.

@phroi phroi force-pushed the feat/epoch-utils branch 2 times, most recently from 0997efb to 63aa8e4 Compare September 26, 2025 11:01
@phroi
Copy link
Contributor Author

phroi commented Sep 26, 2025

@Hanssen0 I solved our previous naming issue and propagated changes, feel free to review once again!

epoch (Uint64)

About Uint64, currently a len of exactly 56 bits is allowed, should I allow for any len and crop to 56?

@Hanssen0
Copy link
Member

epoch (Uint64)

About Uint64, currently a len of exactly 56 bits is allowed, should I allow for any len and crop to 56?

https://docs.rs/crate/ckb-gen-types/1.0.0-rc1/source/schemas/blockchain.mol#76

We should explicitly accept 64 bits only, to be consistent with CKB's molecule definition. I can accept a struct here if it doesn't modify the data length.

I might suggest that we add NumLike to EpochLike, so we can use Epoch.from to handle any numbers.

phroi and others added 5 commits October 16, 2025 17:05
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@phroi
Copy link
Contributor Author

phroi commented Oct 16, 2025

/gemini review

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 is a great initiative to refactor the Epoch representation into a dedicated class with utility methods, which significantly improves code clarity and usability. The changes are well-documented and the new methods for arithmetic and comparison are valuable additions. However, I've identified a few critical issues: one with the serialization/deserialization logic of the new Epoch class, and another with a reference error in calcDaoClaimEpoch. I've also included a suggestion for optimizing the add method. After addressing these points, this will be a very strong contribution.

Comment on lines +49 to +67
@mol.codec(
mol
.struct({
padding: mol.Byte8,
value: mol.struct({
denominator: mol.Uint16LE,
numerator: mol.Uint16LE,
integer: mol.uint(3, true),
}),
})
.mapIn((encodable: EpochLike) => {
const value = Epoch.from(encodable);
return {
padding: "0x0000000000000000",
value,
};
})
.mapOut((v) => v.value as Epoch),
)
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 mol.codec for Epoch is incorrectly defined as a 15-byte struct with padding. A CKB epoch is a uint64 (8 bytes) value where number, index, and length are bit-packed. This implementation will lead to incorrect serialization and deserialization of epoch values.

The codec should be based on mol.Uint64LE and perform the correct bitwise operations for packing and unpacking the epoch fields. This change will also require updating the Epoch.from method to handle bigint values, for which I've left a separate comment.

@mol.codec(
  mol.Uint64LE.mapIn((epochLike: EpochLike) => {
    const { integer, numerator, denominator } = Epoch.from(
      epochLike as EpochLike,
    );
    return (denominator << 40n) | (numerator << 24n) | integer;
  }),
)

Comment on lines +139 to +156
static from(epochLike: EpochLike): Epoch {
if (epochLike instanceof Epoch) {
return epochLike;
}

let integer: NumLike, numerator: NumLike, denominator: NumLike;
if (Array.isArray(epochLike)) {
[integer, numerator, denominator] = epochLike;
} else {
({ integer, numerator, denominator } = epochLike);
}

return new Epoch(
numFrom(integer),
numFrom(numerator),
numFrom(denominator),
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To support the corrected mol.codec which decodes an epoch into a bigint, the Epoch.from factory method needs to be updated to handle NumLike (including bigint) inputs. This will allow it to construct an Epoch instance from its raw uint64 representation.

  static from(epochLike: EpochLike | NumLike): Epoch {
    if (epochLike instanceof Epoch) {
      return epochLike;
    }

    if (Array.isArray(epochLike)) {
      const [integer, numerator, denominator] = epochLike;
      return new Epoch(
        numFrom(integer),
        numFrom(numerator),
        numFrom(denominator),
      );
    }

    if (typeof epochLike === "object" && epochLike !== null) {
      const { integer, numerator, denominator } = epochLike as {
        integer: NumLike;
        numerator: NumLike;
        denominator: NumLike;
      };
      return new Epoch(
        numFrom(integer),
        numFrom(numerator),
        numFrom(denominator),
      );
    }

    // Handle NumLike for raw value
    const raw = numFrom(epochLike);
    const integer = raw & 0xffffffn;
    const numerator = (raw >> 24n) & 0xffffn;
    const denominator = (raw >> 40n) & 0xffffn;
    return new Epoch(integer, numerator, denominator);
  }

@phroi
Copy link
Contributor Author

phroi commented Oct 16, 2025

We should explicitly accept 64 bits only, to be consistent with CKB's molecule definition. I can accept a struct here if it doesn't modify the data length.

Sounds good, done with the following:

@mol.codec(
  mol
    .struct({
      padding: mol.Byte8,
      value: mol.struct({
        denominator: mol.Uint16LE,
        numerator: mol.Uint16LE,
        integer: mol.uint(3, true),
      }),
    })
    .mapIn((encodable: EpochLike) => {
      const value = Epoch.from(encodable);
      return {
        padding: "0x0000000000000000",
        value,
      };
    })
    .mapOut((v) => v.value as Epoch),
)

I might suggest that we add NumLike to EpochLike, so we can use Epoch.from to handle any numbers.

Hmmm, it would fit with the original spec description (and our Overlord hints too in that direction), but what benefits would it bring to a dev workflow compared to this struct implementation?

Love & Peace, Phroi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Merge iCKB Utils Epoch features into CCC

2 participants