Skip to content

cndid int #114

Description

@dumblepy

Candidの intNimの int / int64 ではなく、任意精度整数型に対応させるべきです。

Candid仕様上、int はビット幅に上限がない整数です。wire formatはSLEB128です。したがって int64 でも厳密な型対応にはなりません。(ICP Developer Docs) Nimの組み込み整数型は最大でも通常 int64 で、任意精度ではありません。(Nim Programming Language)

nicp_cdk なら、私はCDK専用の型を作るのを推奨します。

type
  CandidInt* = object
    negative*: bool
    magnitude*: seq[byte]  # little-endian limbs/bytes

あるいはもう少し実装しやすく、

type
  CandidInt* = object
    sign*: int8            # -1, 0, +1
    limbs*: seq[uint32]    # little-endian

です。

そしてマッピングを明確にします。

Candid | Nim -- | -- int8 | int8 int16 | int16 int32 | int32 int64 | int64 int | CandidInt(任意精度) nat8 | uint8 nat16 | uint16 nat32 | uint32 nat64 | uint64 nat | CandidNat(任意精度)

特に、intint64 にするのは避けるべきです。今回のPlayground timestamp程度なら int64 に収まりますが、Candid型システムとしては不正確です。

nicp_cdkならさらにこうしたい

CandidIntCandidNat を別々に巨大整数として実装するより、

type
  CandidNat* = object
    limbs*: seq[uint32]

CandidInt* = object
negative*: bool
magnitude*: CandidNat

にすると扱いやすいです。

SLEB128/ULEB128も、

proc encodeULEB128*(value: CandidNat): seq[byte]
proc decodeULEB128Big*(data: openArray[byte], offset: var int): CandidNat

proc encodeSLEB128*(value: CandidInt): seq[byte]
proc decodeSLEB128Big*(data: openArray[byte], offset: var int): CandidInt

に変更します。

現状の、

proc encodeSLEB128*(n: int32): seq[byte]

int32 / int64 系Candid型の補助には使えても、Candid int のencoderとして使うべきではありません

便利さのための変換

ユーザーに毎回BigIntを書かせる必要はありません。

proc candidInt*(x: int): CandidInt
proc candidInt*(x: int64): CandidInt
proc candidInt*(x: string): CandidInt

proc candidNat*(x: uint): CandidNat
proc candidNat*(x: uint64): CandidNat
proc candidNat*(x: string): CandidNat

として、

let a = candidInt(123)
let b = candidInt("170000000000000000000000000000000")
let c = candidInt("-999999999999999999999999999999")

とできるようにするのがよいです。

さらに CandidValue も、

of ctInt:
intVal*: CandidInt

of ctNat:
natVal*: CandidNat

に変えるのが型として正しいです。

結論としては Candid int = 独自の任意精度 CandidIntCandid nat = 独自の任意精度 CandidNat が最も妥当です。 int64 を暫定対応にするより、このタイミングでCandidの型定義そのものを直した方が後で楽です。

Candidの intNimの int / int64 ではなく、任意精度整数型に対応させるべきです。

Candid仕様上、int はビット幅に上限がない整数です。wire formatはSLEB128です。したがって int64 でも厳密な型対応にはなりません。([ICP Developer Docs]1) Nimの組み込み整数型は最大でも通常 int64 で、任意精度ではありません。([Nim Programming Language]2)

nicp_cdk なら、私はCDK専用の型を作るのを推奨します。

type
  CandidInt* = object
    negative*: bool
    magnitude*: seq[byte]  # little-endian limbs/bytes

あるいはもう少し実装しやすく、

type
  CandidInt* = object
    sign*: int8            # -1, 0, +1
    limbs*: seq[uint32]    # little-endian

です。

そしてマッピングを明確にします。

Candid Nim
int8 int8
int16 int16
int32 int32
int64 int64
int CandidInt(任意精度)
nat8 uint8
nat16 uint16
nat32 uint32
nat64 uint64
nat CandidNat(任意精度)

特に、intint64 にするのは避けるべきです。今回のPlayground timestamp程度なら int64 に収まりますが、Candid型システムとしては不正確です。

nicp_cdkならさらにこうしたい

CandidIntCandidNat を別々に巨大整数として実装するより、

type
  CandidNat* = object
    limbs*: seq[uint32]

  CandidInt* = object
    negative*: bool
    magnitude*: CandidNat

にすると扱いやすいです。

SLEB128/ULEB128も、

proc encodeULEB128*(value: CandidNat): seq[byte]
proc decodeULEB128Big*(data: openArray[byte], offset: var int): CandidNat

proc encodeSLEB128*(value: CandidInt): seq[byte]
proc decodeSLEB128Big*(data: openArray[byte], offset: var int): CandidInt

に変更します。

現状の、

proc encodeSLEB128*(n: int32): seq[byte]

int32 / int64 系Candid型の補助には使えても、Candid int のencoderとして使うべきではありません

便利さのための変換

ユーザーに毎回BigIntを書かせる必要はありません。

proc candidInt*(x: int): CandidInt
proc candidInt*(x: int64): CandidInt
proc candidInt*(x: string): CandidInt

proc candidNat*(x: uint): CandidNat
proc candidNat*(x: uint64): CandidNat
proc candidNat*(x: string): CandidNat

として、

let a = candidInt(123)
let b = candidInt("170000000000000000000000000000000")
let c = candidInt("-999999999999999999999999999999")

とできるようにするのがよいです。

さらに CandidValue も、

of ctInt:
  intVal*: CandidInt

of ctNat:
  natVal*: CandidNat

に変えるのが型として正しいです。

結論としては Candid int = 独自の任意精度 CandidIntCandid nat = 独自の任意精度 CandidNat が最も妥当です。 int64 を暫定対応にするより、このタイミングでCandidの型定義そのものを直した方が後で楽です。

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions