カタパルトのネームスペースIDとモザイクIDの導出方法（Alpaca, Bison, Cow）

# はじめに

カタパルトのCowからネームスペースIDとモザイクIDの導出方法が変わったので書きます。

# ネームスペースID

## Alpaca, Bison

基本的には、名前から導出されています。

例えば、`nem`のネームスペースIDは、`84B3552D375FFA4B`です。

```javascript
const nem2Sdk = require("nem2-sdk").NamespaceId;
const namespaceIdNem = new NamespaceId("nem");
console.log(namespaceIdNem.toHex().toUpperCase())
// 84B3552D375FFA4B
```

ルートネームスペースの場合は、`0000000000000000`と名前を結合してハッシュ値をとります。

```javascript:ネームスペース（nem）
const nem = "6e656d"
const id = calcurateHash(toLE("0000000000000000") + nem)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// 84B3552D 375FFA4B
```

サブネームスペースの場合は、親ネームスペースIDと名前を結合してハッシュ値をとります。

```javascript:サブネームスペース（nem.catapult）
const catapult = "6361746170756C74"
const id = calcurateHash(toLE("84b3552d375ffa4b") + catapult)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// 1B558641 28318CF8
```

## Cow

Alpaca, Bisonとほとんど同じですが、最上位ビットが必ず`1`になるようになりました。例えば、`cat`のネームスペースIDは`B1497F5FBA651B4F`ですが、先ほどと同じように計算すると、`31497F5FBA651B4F`になります。

`0x31`は、`0011 0001`ですが、最上位ビットを立てると、`1011 0001`となり、`0xB1`となります。

```javascript:ネームスペース（cat）
const cat = "636174"
const id = calcurateHash(toLE("0000000000000000") + cat)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// 31497F5F BA651B4F
// 最上位ビットを立てると
// B1497F5F BA651B4F
```

サブネームスペースも同様です。

```javascript:サブネームスペース（cat.harvest）
const harvest = "68617276657374"
const id = calcurateHash(toLE("B1497F5FBA651B4F") + cat)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// 941299B2 B7E1291C
// 最初から最上位ビット立ってるパターン
```

# モザイクID

## Alpaca, Bison

ネームスペースIDと似たような感じです。ネームスペースIDとモザイク名を結合してハッシュをとります。

```javascript:モザイク（xem）
const xem = "78656d"
const id = calcurateHash(toLE("84B3552D375FFA4B") + xem)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// D525AD41 D95FCF29
```

## Cow

劇的に変わりました。

モザイクから名前という概念はなくなりました。

ノンス（ナンス）という任意の値と、公開鍵から導出されます。

また、最上位ビットが必ず`0`になるようになりました。

```javascript:モザイク（nonce=0）
const publicKey = '7F78559C556642FE132616910B1C9F2C36BC144D2D3A9E909092D64A0D0DE0DE'
const id = calcurateHash(toLE("00000000") + publicKey)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// 119E1566 1E9B2758
```


```javascript:モザイク（nonce=1）
const publicKey = '7F78559C556642FE132616910B1C9F2C36BC144D2D3A9E909092D64A0D0DE0DE'
const id = calcurateHash(toLE("00000001") + publicKey)
console.log(toLE(id.substring(8,16)) + " " + toLE(id.substring(0,8)))
// AAECBFD7 6AE7411B
// 最上位ビットを下げると
// 2AECBFD7 6AE7411B
```

# toLEとcalcurateHashについて

```javascript:toLE
const nem2lib = require("nem2-library")
function toLE(hex) {
    const uint8arr = nem2lib.convert.hexToUint8(hex)
    return nem2lib.convert.uint8ToHex(uint8arr.reverse())
}
```

```javascript:calcurateHash
const sha3_256 = require('js-sha3').sha3_256
function calcurateHash(hex) {
    const hash = sha3_256.create();
    hash.update(Buffer.from(hex, 'hex'));
    return hash.hex().toUpperCase();
}
```

# Cowでネメシスブロックに定義したIDを簡単に見る方法

nemgenをしたときのログから確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/3060fdc2-546f-01fc-4fbb-b0628edb4857.png)

# なんでNamespaceIdはMSBが1で、MosaicIdはMSBが0なの

Gimre氏が答えてくれました！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/a1e5ebf7-cb84-c565-83df-6afeb464bb92.png)

# Cowでモザイクに名前を設定したいときは

MosaicAliasTransactionを使って、ネームスペースと紐づけます。

# おわりに

これまでは、ネームスペース空間の中にモザイクがあるイメージでした。

Cowは、ネームスペースは名前定義の役割を持ち、モザイクはトークン・アセットを定義する役割を持つようになったと感じました。