Coder Social home page Coder Social logo

unique-cell's Introduction

Unique Cell

A unique cell can be created on the Nervos CKB through TypeID which makes sure the unique cell cannot be updated or destroyed.

The unique cell data can store any format data, such as XUDT token information and the contract will not check the content and format of the cell data.

Unique Type Script

unique type script:
  code_hash: 
    unique_type
  args:
    type_id[0..20]  // The following will provide a detailed explanation on how to generate the type_id

How to generate unique type script args

https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#type-id

There are two ways to create a new cell with a specific type id.

  1. Create a transaction which uses any out point as tx.inputs[0] and has a output cell whose type script is Type ID. The output cell's type script args is the hash of tx.inputs[0] and its output index. Because any out point can only be used once as an input, tx.inputs[0] and thus the new type id must be different in each creation transaction.
  2. Destroy an old cell with a specific type id and create a new cell with the same type id in the same transaction.

Implementation can be found in generator-example/src/index.ts

const generateUniqueTypeArgs = (firstInput: CKBComponents.CellInput, firstOutputIndex: number) => {
  const input = hexToBytes(serializeInput(firstInput));
  const s = blake2b(32, null, null, PERSONAL);
  s.update(input);
  s.update(hexToBytes(`0x${u64ToLe(BigInt(firstOutputIndex))}`));
  return `0x${s.digest("hex").slice(0, 40)}`;
};

generator-example/src/lumos.ts

function generateUniqueTypeArgs(input: Input, index: number) {
  const hasher = new utils.CKBHasher();
  hasher.update(blockchain.CellInput.pack(input));
  hasher.update(Uint64.pack(index));
  return hasher.digestHex().slice(0, 42);
}

XUDT Information

The following is the info data format recommended by XUDT:

# general

# The number of decimals the XUDT token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation. 
# 0xF0-0xFF reserved
decimal: uint8  

# The length of the name in bytes
len: uint8

# The name of the XUDT token - e.g. USDT, means to convert 'Tether USDT' to hex form '0x5465746865722055534454'
name: variable max 255

# The length of the symbol in bytes
len: uint8

# The symbol of the XUDT token - e.g. USDT, means to convert 'USDT' to hex form '0x55534454'
symbol: variable max 255

# optional
...

Notice: The xUDT information format is NOT a key-value structure.

You can find the code about how to construct the xUDT information data in generator-example/src/lumos.ts

const coin = {
  decimal: 6,
  name: "UNIQUE COIN",
  symbol: "UNC",
};

const data = bytes.hexify(bytes.concat(
  Uint8.pack(coin.decimal),
  Uint8.pack(coin.name.length),
  new TextEncoder().encode(coin.name),
  Uint8.pack(coin.symbol.length),
  new TextEncoder().encode(coin.symbol),
));

Development

Build contracts:

make build

Run tests:

make test

unique-cell's People

Contributors

duanyytop avatar twhy avatar

Stargazers

 avatar  avatar 22388o⚡️  avatar

Watchers

Quake Wang avatar jjy avatar shaojunda avatar  avatar

unique-cell's Issues

Review by ian

0001-review.patch

Preview review locally:

git am 0001-review.patch
From 31e9a1611020878e459758e336beaab05256967b Mon Sep 17 00:00:00 2001
From: ian <[email protected]>
Date: Tue, 26 Mar 2024 03:23:37 +0000
Subject: [PATCH] review

---
 contracts/unique-type/src/entry.rs | 6 ++++++
 tests/src/tests.rs                 | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/contracts/unique-type/src/entry.rs b/contracts/unique-type/src/entry.rs
index 9b81ce0..810a2db 100644
--- a/contracts/unique-type/src/entry.rs
+++ b/contracts/unique-type/src/entry.rs
@@ -16,6 +16,9 @@ pub fn main() -> Result<(), Error> {
 
 fn check_type_id() -> Result<(), Error> {
     let unique_type = load_script()?;
+    // ℹ️ Informing: Global index of the first output in the script group
+    // ⛔️ Blocking: There may be multiple outputs having the same args. Is this the intended
+    // behavior?
     let first_output_index = QueryIter::new(load_cell_type, Source::Output)
         .position(|type_opt| {
             type_opt.map_or(false, |type_| type_.as_slice() == unique_type.as_slice())
@@ -40,11 +43,14 @@ fn check_type_id() -> Result<(), Error> {
 
 // Ensure that unique cells cannot appear in transaction inputs, that is, unique cells cannot be
 // updated and destroyed
+// 💭 Discussing: Why not using type_id + all-zeros lock?
 fn check_inputs() -> Result<(), Error> {
     let unique_type = load_script()?;
     let is_unique_input_exist = QueryIter::new(load_cell_type, Source::Input)
         .any(|type_opt| type_opt.map_or(false, |type_| type_.as_slice() == unique_type.as_slice()));
     if is_unique_input_exist {
+        // 💭 Discussing: The error name is misleading. I would recommend a name like
+        // InputUniqueCellForbidden
         return Err(Error::InputUniqueCellMismatch);
     }
     Ok(())
diff --git a/tests/src/tests.rs b/tests/src/tests.rs
index 1f373e5..7b02260 100644
--- a/tests/src/tests.rs
+++ b/tests/src/tests.rs
@@ -58,6 +58,8 @@ fn create_test_context(unique_error: UniqueError) -> (Context, TransactionView)
     let mut ret = [0; 32];
     blake2b.finalize(&mut ret);
     let unique_type_args = match unique_error {
+        // 💭 Discussing: Flipping any bit is more stable for test. However, the probability that
+        // the two ranges equal is negligible.
         UniqueError::UniqueTypeIdInvalid => Bytes::copy_from_slice(&ret[12..]),
         _ => Bytes::copy_from_slice(&ret[0..20]),
     };
-- 
2.43.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.