ccc icon indicating copy to clipboard operation
ccc copied to clipboard

Add Molecule related features

Open Hanssen0 opened this issue 1 year ago • 9 comments

Background

In the CKB ecosystem, molecule is widely used. We initially have moleculec-es to generate molecule codecs for JS, but it's written in Golang, so it can not run in a JS runtime.

Later, we have related features in the Lumos, see @ckb-lumos/codec and @ckb-lumos/molecule. These two offer compile-time, runtime molecule parsing, and molecule schema defining in JS.

Nowadays, CCC plans to be a successor of Lumos to provide a better developer experience. So, we also want to add the molecule-related feature in CCC.

Plan

  • [x] Add molecule codecs to @ckb-ccc/core. Similar to @ckb-lumos/codec but with CCC types. #88
  • [ ] Add a package @ckb-ccc/molecule based on codecs. Similar to @ckb-lumos/molecule.
  • [x] Decorators to bind codecs to plain TS classes. e.g. #81 #106
@Molecule(codec)
class Script {
...
}
const bytes = Script.from({...}).toBytes();
Script.fromBytes(bytes);

This helps developers to use Molecule.

Hanssen0 avatar Aug 28 '24 05:08 Hanssen0

@homura will start this issue next week

Keith-CY avatar Sep 10 '24 10:09 Keith-CY

I need to postpone addressing this issue because of higher-priority tasks. I'll likely start it next week

homura avatar Sep 19 '24 08:09 homura

Let me break down the codec feature request.

In CCC, the code is organized using the OO pattern with many classes such as Script, Transaction, etc. The request is to enhance any class by adding a static fromBytes method for the class and a toBytes method for its instance.

The enhancer should take any class and create a new version of that class with the following:

  1. A new constructor that can create an enhanced instance
type Constructor<
  Instance, 
  Arguments extends unknown[] = any[]
> = new (...args: Arguments) => Instance;
  1. A new prototype method toBytes
type ToBytes<Instance> = Instance & { toBytes(): Bytes }
  1. A new static method fromBytes to create the enhanced instance
type FromBytes<Class, Instance> = Class & { fromBytes(bytes: Bytes): Instance }

Therefore, a Codec enhancer can be defined as:

type Codec<Class> =
  // take any class
  Class extends Constructor<infer OriginInstance>
    ? // add a static `fromBytes` method and a new constructor to create the new instance
      FromBytes<Class, ToBytes<OriginInstance>> & Constructor<ToBytes<OriginInstance>>
    : // ignore for non-class
      never;

To handle the FromBytes part, the codec must know how to convert Bytes in parameters to convert bytes into the constructor parameters.

To handle the ToBytes part, the codec must be able to access the members of the instance to convert them into the Bytes.

declare function enhance<T extends Constructor<any>>(
  class_: T,
  fromBytes: (bytes: Bytes) => ConstructorParameters<T>,
  toBytes: (instance: InstanceType<T>) => Bytes,
): Codec<T>;

TBD: the fromBytes and toBytes callbacks binding design in enhance

homura avatar Sep 27 '24 08:09 homura

https://github.com/microsoft/TypeScript/issues/4881

Currently, using the decorator does not allow for creating a well-typed class. Perhaps CCC should consider using a higher-order approach to achieve this feature. For example, consider the following demonstration:

class InternalScript {
  // ...
}

// Enhance an existing class like this
const Script = enhance(InternalScript)

// Or define a class like this
const Script = enhance(class Script {
  // ...
})

@Hanssen0 What do you think about this?

homura avatar Oct 10 '24 13:10 homura

Perhaps CCC should consider using a higher-order approach to achieve this feature.

I see no problem. The mixin approach gives us all we want.

Hanssen0 avatar Oct 11 '24 07:10 Hanssen0

We can propose the draft PR first so the progress would be more clear @homura

Keith-CY avatar Oct 18 '24 16:10 Keith-CY

I have submitted PR #81 to simplify the creation of a CCC class using a helper function. It works with molecule-es and Lumos as a transition program.

To make it work smoother with CCC, we should consider the following steps:

  • Introduce bigint codecs in CCC to replace the BI from Lumos.
  • Replace Lumos's Hash with CCC's Hex.
  • Regenerate blockchain.mol with CCC's basic codecs, including Hex and bigint codecs.

Once these changes are implemented, creating CCC classes would be similar to the case.

@Hanssen0 Do you think these changes meet the requirements?

homura avatar Oct 21 '24 03:10 homura

I have submitted PR #81 to simplify the creation of a CCC class using a helper function. It works with molecule-es and Lumos as a transition program. Do you think these changes meet the requirements?

Yes. This is a good transition plan.

Hanssen0 avatar Oct 22 '24 03:10 Hanssen0

https://github.com/ckb-devrel/ccc/pull/88

Hanssen0 avatar Dec 10 '24 11:12 Hanssen0