暗号通貨Qtumのoffline stakingについて

qtum.org

Qtumという暗号通貨を買った。この暗号通貨はProof of Stakeを採用している。マイニング報酬を得るために普通はクライアントをずっと立ち上げておかなければいけないのだけれど、Qtumはstakingを他人にdelegate(委任)することができる。

で、良く分からずにその辺の操作をしていたら、4,000円分くらい溶けた。悲劇を繰り返さないようにメモを書いておく。

Delegationを開始するには約1 QTUM、delegationを中止するには約0.02 QTUM掛かるので注意。

あと、delegationを受け付けるようにした。マイニング報酬のうち5%を私が受け取る。デフォルト設定だと最小100 QTUMからのところ、最小10 QTUMから受け付けるようにしている。よければ使ってください。ただ、delegateする前にこの記事を一通り読むことをおすすめします。

https://gist.github.com/kusano/c9be0020210b5dee82e2a6063293af26

Qtumとは

coin.z.com

日本語だとこれが一番詳しいだろうか。

BitcoinとEthereumのいいとこ取りというか、プログラムの作りとしては、Bitcoinがベースになっている。Bitcoinの送金の認証の部分は簡単なスクリプト言語になっている。ここに、コントラクトを作成する命令や、コントラクトを実行する命令を追加している。

一通り触ってみた感じ、とても出来が良い。ブロックチェーンエクスプローラーがしっかりしているのも良い。

qtum.info

Proof of Stake(PoS)とは

以前に書いた。

qiita.com

Bitcoinの電力消費は以前から話題になっている。それを解決するProof of ○○として記憶容量があるのだけど、それもちょうど今日話題になっていた(その用途なら新品よりも中古のHDDを買い漁りそうな気もするが……)。

pc.watch.impress.co.jp

取引の正当性を証明するのに何らかのリソースを使うのではなく、そのコインを持っていることのみを使うのは究極の解決策のような気がしてくる。

問題があるとしたら、電力なり記憶領域なりを利用して採掘されたわけではないコインに価値を感じるか?というところだろうか。100万円分の電力を消費して採掘されたコインなら100万円分の価値があるように思えるが、コインから生まれたコインに価値を感じるか?という。本当は順序が逆で、100万円分の価値があるから100万円分の電力が注ぎ込まれるのだろうけど。

あとは、仮想通貨全体に占める採用例はそれほど多くはないので、何か致命的な問題が残っているというリスクもあるかもしれない。

QtumのPoSのパラメタはシンプルで、1ブロックあたり4 QTUM(半減期で減っていく)。所持しているQTUMの量に応じた確率で採掘できる。ただし、取引が採掘に使えるのは取引が入っているブロックから500ブロック経過した後。採掘間隔は平均2分に調節されるので、16時間。この16時間があることによって、チェーンが分岐したときに双方がチェーンを伸ばしたがるということを防いでいるのかもしれない。

公式のチュートリアルでの推奨やクライアントの仕組みとして大きな取引を100 QTUMくらいの取引に分けるようになっているのは、この16時間があるから。採掘したら新規取引扱いになるので500ブロックは採掘できなくなる。金額が大きいと16時間がバカにならない。

今、状況を見てみたところ、採掘に参加しているコインの総量は2,000万QTUMくらいで、期待年利は4.6% 参加するコインの総量が増えれば年利は下がるし、減れば上がる。Whitepaperによると、発行数は1億QTUMで、最初に5,1000万QTUMが販売されたらしいから、こんなものか。

f:id:kusano_k:20210421012621p:plain

Offline staking

Super stakingとも呼ばれている。

PoSのもう一つの問題として、採掘するためにはクライアントを動かし続けないといけないことがある。まあ、誰かしらクライアントと動かしていないとネットワークが破綻するのでこれは良いのだけど。ただ、ネットワークに繋ぐということはホットウォレットということであり、そこに例えば1億円分の仮想通貨を入れておくのは怖い。逆に、1,000円分の仮想通貨のためにクライアントを動かし続けるのも面倒。金額が安ければ採掘しなかったことによる損も小さいのだが、損した気分にはなる。

そこで、Qtumでは誰かに採掘をdelegate(委任)することができる。これは面白い。あくまで自分の採掘をdelegateしているだけであって、マイニングプールとは異なる。AさんとBさんがCさんに採掘をdelegateして、CさんがAさんの取引を使って採掘に成功したとき、採掘報酬は(QTUMの所有者である)Aさんと(実際に採掘してくれた報酬として)Cさんで分け合うことになる。Bさんはもらえない。

最初は、「え? そんなことできるの?」と思ったけど、話は簡単。DelegateするAさんは事前に「報酬はx%でCさんにdelegateします」という情報を署名付きで流しておく、Cさんは「今この瞬間、Aさんの取引は採掘できる条件を満たしてますよね?」とブロックを作る。他の参加者は、Cさんが本当にAさんからdelegateされているかや、Cさんがx%以外の報酬を取っていたりしないかを見張る。詳しくは、

github.com

これを全てコントラクトで実装していたら、「なるほど、BitcoinとEthereumを合わせるとそんなこともできるのか」となってとても綺麗な話だったのだけど、そんなことはなかった。Delegateするところはコントラクトだが、採掘するところはBitcoinプロトコルがガッツリ書き換えられている。それならそれで、delegateするところも無理にコントラクトを使わなくて良いと思うんだよな……。

Delegateするコントラクトはこれ。6,064バイト。

github.com

これだけでかければ、delegateするのに1 QTUM分くらいのガス(コントラクトを実行する手数料)が掛かるか……と思ったけど、そうではなかった。

コントラクトのソースコードはこれ。わざわざ、ガスを2,000,000消費するようになっている。

https://github.com/qtumproject/offline-staking-contract/blob/bd7b160f574f3a34c4f12ca009477d90ddc01c54/offline-staking.sol#L66-L72

      // we need to make this function call expensive to avoid spam, so here we consume ~2M gas that will go to miners
        if(gasleft()<0x1E9480) revert("Not enough gas left to consume, the recommended gas limit to call this function is 2,250,000");
        uint gas=gasleft();
        while(true) {
            dummy=0x0;
            if(gas-gasleft()>=0x1E8480)break;
        }

で、それに気が付かずに、数回無駄にdelegateしたり解除したりしてお金を溶かしました。確認画面にはちゃんとガスの使用量上限とガスの料金は書かれていたから、計算すれば良かったのだけど。送金が0.001 QTUMくらいでできるのに、採掘のdelegateにそんなにコストが掛かるとは思わなかった……。

f:id:kusano_k:20210421015753p:plain

罠があって、初期設定だと、あるアドレスAをdelegateする → そのコントラクトを実行するのにアドレスAからQTUMが支払われる → 残金が別のアドレスBに送信される → アドレスAの残金が0になる ということが起こる。「Use change address」のチェックを外しましょう。そもそもなぜこんな設定があるかというと、店Aに支払ったときと店Bに支払ったときの送金元アドレスが同じだと、同じ人が支払ったと紐付けられてしまうというプライバシー的な問題があるから。それができてしまうようになるというリスクはある。

f:id:kusano_k:20210421021505p:plain

あるいは、「コインコントロール機能を有効化する」にチェックを入れると、送金時に下のようなダイアログを表示できて、自分に送金された取引の一覧から使用する取引を選んだり、残金の送金先を手動で設定したりできる。ちゃんと100 QTUMごとに分かれているかを確認するのにも使える。

f:id:kusano_k:20210421021948p:plain

Delegateしたアドレスの残高が0になってしまっても慌てる必要は無い。自分の持っている他のアドレスからdelegateしたアドレスに送金すれば良いだけ。送金手数料はdelegateする手数料よりとても安い。

Offline stakingに対する攻撃

stake-a-thon.qtum.org

Offline stakingを受け付けていて(掲載を申請した)アドレスの一覧が公開されている。これに載っている人に悪意があったり、あるいは載せることで悪意のある人に目を付けられたときに何が起こるか。公式ブログにも色々と書かれている。

blog.qtum.org

Offline stakingを受け付ける側に悪意がある場合。

  • DelegateされたQTUMを勝手使ってしまう
    • これはできない
    • これができないから、大金(大QTUM)をコールドウォレットに入れて、自分の管理する別のクライアントにdelegateするということができる
      • ハッキングでネットワークに繋いでいるクライアントに何をされても、損するのはそのクライアントに入れているお金だけ
  • 「Delegationを受け付けるよ」と言いながら、採掘しない
    • これはできる
    • 採掘できればdelegation報酬分を得するからそんなことはしないだろうと期待するしかない
    • エクスプローラーで採掘できたかどうかは見られるので、期待値より少なければ怪しい
    • 頑張ってスクリプトを書けば、「このブロックが採掘されたタイミングで先に私の取引で採掘できたはずでは?」と怪しむことはできるかもしれない
      • でも、PoSを採掘してみると分かるけど、手元で採掘に成功しても他の誰かに先を越されることは普通にある
    • 「あ、こいつ採掘していないな」と分かって他の人に乗り換えるのにも、1 QTUM掛かってしまう
    • 悪意というか、飽きて止めるというのが多そう
    • このリスクが大きいので、自分で採掘することにした
  • 掲載されているdelegation報酬が嘘
    • クライアントに設定した報酬より安いと採掘されない、高い場合はその報酬がそのまま支払われる
    • これもできる
    • そもそも、delegationを受け付ける側は特にコントラクトを実行したりはしないようで、外部からクライアントで最小報酬を何%にしているのか確認するすべが無い
    • 嘘を付いてもメリットは無いだろうと思うしかない

Offline stakingをdelegateする側に悪意がある場合。

  • 勝手にdelegateする
    • 上記の一覧に載っていなくても、エクスプローラーからOffline stakingをしているアドレスを探すことはできる
    • まあ、delegateされて損することは無いだろう
    • 自分用に最小報酬を0%にしている場合は、ちょっとイラっとする
      • ので、上記のFAQだとそういうときはwhitelistで運用しろと言っている
  • 最小報酬未満でdelegateする
    • そういう取引はクライアントが採掘しないはず
  • 大量にdelegationを送りつける
    • 負荷が高まりそう
      • 「この取引で採掘できるかな?」というのを毎秒試しているので
    • これを防ぐため、delegationのコントラクトはガスを大量に消費するし、Minimum UTXO Valueが設定できるようになっているのだろうか

Super stakingします

ということで自分で採掘することにしたので、ついでにdelegationも受け付けるようにした。

gist.github.com

私は未だにNEETCOIN(今でも参加しているのが700万NEET程度しかいないので、1,000 NEETくらいの手持ちで毎日何回も採掘できている)や、XPCoinも採掘しているから、しばらくは続けると思います。止めるときは、なるべく↑のGistに書くようにします。保証はしませんが。

デフォルトでは100 QTUM未満は受け付けないようになっているのだけど、ここを10 QTUMにしているので少額でもどうぞ。

ただ、ソースコードのこの部分がちょっと気になる。

            // Check the super staker min utxo value
            if(coinTxPrev.out.nValue < DEFAULT_STAKING_MIN_UTXO_VALUE)
                return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "stake-delegation-not-min-utxo", strprintf("CheckProofOfStake() : Stake for block at height %i do not have the minimum amount required for super staker", nHeight));

https://github.com/qtumproject/qtum/blob/cb6fefeab03bb88544660c37b39ddf7c94e7a278/src/pos.cpp#L240

DEFAULT_STAKING_MIN_UTXO_VALUE は100 QTUM。コメントやソースコードを追うに、これはdelegationを受け付ける私が100 QTUMを持っていれば良いと思うのだけど……。

開発者直々のコメントが付いていた。Delegateする側はいくら少なくても良いらしい。

JB395 commented 18 hours ago Qtum offline staking accepts delegated addresses with any quantity of QTUM.

あと、度々書いているようにdelegateするには約1 QTUM必要なので、小額でdelegateして得かどうかは良く考えてほしい。現在の年利は4.6% 2021年末に半減期で報酬が2 QTUMになる予定。