Counterparty から Monaparty を最小工数で作るための技術

# この文章について

Counterparty の Monacoin 版である Monaparty は、本年6月に 1000XCP 相当の ICO を開発原資として、同 12月に Proof of Burn イベントまで漕ぎ着けました。
当時の価格で140万円程度で、開発人件費としては、1〜3ヶ月程度となります。
普通に作っていては原価割れしてしまう条件で、いかにして無駄を省いて開発完了させるか。広い意味での技術が求められる案件でした。

今後、似たようなプロジェクトを立ち上げる方々のために、行ったことを記録しておきます。

# サーバの無料枠を確保する

運用コストで人件費の次に大きいのはサーバ費です。
ICO 達成により Monaparty の開発が決定したとき、真っ先に行ったのは Microsoft のスタートアップ支援プログラムである [BizSpark](https://www.microsoft.com/ja-jp/startups/BizSpark.aspx) の審査申し込みでした。
BizSpark の支援を受けると、毎月定額の Azure クラウド利用権が付与されます。
これにより ICO による調達額の殆どを開発人件費に回せるようになりました。

BizSpark は強力ですが、審査もあり、通らない可能性もあります。その場合でも GCP や AWS に無料枠はあります。
Twitter などで眺めていると、無料枠を知らず廉価な VPS で苦労している開発初心者も多いようです。
ぜひ活用しましょう。

# master, develop ブランチは本家追随用にする

ここは意見が別れるところかもしれませんが、Monaparty では git の master と develop は本家追随用とし、monaparty と monaparty-develop を別にしました。

手元では remote で origin (Monaparty) と upstream (Counterparty) との区別はつきます。
よって、わけなくても良いという考え方もできます。
しかし、Monaparty として Counterparty の develop にどれくらい追随できているのかということを可視化しやすい、というメリットがあり、分ける方を推します。

## 具体的なワークフロー

具体例を挙げると、こんな感じになります。

まず、定期的に本家 (upstream) を引っ張ってきて、 Monaparty 側 (origin) に push します。

```
git checkout develop
git fetch --all
git rebase upstream/develop
git push 
```

この origin/develop ブランチの内容を読み、 monaparty-develop 側にどう取り込むのかを検討します。
(検討中に upstream/develop に commit があっても、検討が終わるまで無視)

# 他人に流用してもらえるようにする

Counterparty から Monaparty が作れるなら、Litecoin を使った Liteparty も用意に作れるはずです。
(SegWit 非対応コインでは今後難しくなるはずですが、一部機能を無効にすれば、無理ではない)

Monaparty では、移植当初は Monacoin のことしか考えていませんでしたが、途中から敢えて Altparty を作りやすいように方針変更しました。

象徴的な commit は https://github.com/monaparty/counterparty-lib/commit/dc1b332bf0f462c0d1cf6dc95a06a115837e0865 です。

`'XCP'` や `'BTC'` など文字列定数となっているところを、`coifig.XCP` や `config.BTC` に書き換えています。
その上で、Monaparty では[以下のように書き換える](https://github.com/monaparty/counterparty-lib/blob/9d4b64375d2c77b8215ca7446b28894afdf7c8b5/counterpartylib/lib/config.py#L34-L35)ことで Monacoin に対応させています。

```
# Currency agnosticism
BTC = 'MONA'
XCP = 'XMP'

BTC_NAME = 'Monacoin'
XCP_NAME = 'Monaparty'
```

Litecoin で実現したければ、こう変更するだけで済みます。[^probably]

[^probably]: 試してはいませんが、おそらく問題ない。

```
# Currency agnosticism
BTC = 'LTC'
XCP = 'XLP'

BTC_NAME = 'Litecoin'
XCP_NAME = 'Liteparty'
```

また、このような改変であれば、本家に取り込むお願いをする余地が大きくなります。
本家のほうが人的リソースが豊富なので、取り込んでもらうことで、Monaparty 側のコード保守コストが下がります。

# chainparams を入れ替える方法を探す

Bitcoin 系のオルトコインの多くは chainparams を入れ替えるだけで Bitcoin 用のライブラリが使えます。[^described]
[^described]: これは[アドベントカレンダ11日目の記事](https://qiita.com/cryptcoin-junkey/items/fc6d62c22d4444d98c45)にも書きました。
入れ替えの具体的な方法は言語/ライブラリにより様々で、先人が公開していたりいなかったりします。
最悪、Bitcoin 用ライブラリに手を入れれば済みますが、手を入れたライブラリ全体を保守することになり、コストが高くのでやりたくないですね。

Counterparty-lib は Python で書かれていて、[Python-bitcoinlib](https://github.com/petertodd/python-bitcoinlib) という、ド直球なパッケージが使われています。
この bitcoin を wrap するパッケージを探したところ、[Python-altcoinlib](https://github.com/rnicoll/python-altcoinlib) という、これまたド直球な名前のものが見つかりました。

ここまでくればゴールは目前で、実装済みの Litecoin や Dogecoin のコードを見ながら [Monacoin 用のコードを追加する](https://github.com/monaparty/python-altcoinlib/commit/bd07b0e90e1fb949191c0230d4d540c9272b0cfb)だけです。

もちろん差分は[プルリクとして本家に送ります](https://github.com/rnicoll/python-altcoinlib/pull/8)。本家に取り込んでもらえれば、将来的な保守コストは下がります。

# とにかく本家にプルリクを出す

取り込んでもらえるかどうかは関係なく、プルリクは出すべきです。
取り込まれなかったとしても、誰かレビューしてもらえることは、大きなコスト削減につながります。
実際 Monaparty でも[プルリクで指摘を受けてしょうもないバグに気づいた](https://github.com/CounterpartyXCP/counterwallet/pull/845)ということがありました。

上流をリスペクトして協力する意思があるという表明にもなりますし、リスペクトされていると思えば fork が困るような仕様変更が行われる可能性も下がるはず。

# まとまっていないまとめ

以上、Monaparty を PoB イベントに漕ぎ着けるまでに行ったことを粗めに列挙しました。
Monacoin は他のオルトコインよりも Bitcoin 系サービスが移植されているほうとは思いますが、まだカバーできていないものも残っているように思います。
雑文が、移植の際になんらかお役に立てれば幸いです。