2017/09/20

JavaScriptの整数範囲はJSONに影響するのか?

以前、JSON-RPCをやるのにuint64_t対応したライブラリが見つからない、という話を書いた。

結局、内部でしか使わないからいいや、ということで、jsonrpc-cをforkして、uint64_tにだけ対応させることにした。


それはそれでよいのだけど、世の中にはあるんじゃなかろうかと探していた。
同じ疑問を持つ人がいた。
c++ - Does libjson support 64 bit int types? - Stack Overflow

libjsonは知らんのだが、回答からすると、JavaScriptは内部的に53bitまでの制限があるよ、ということらしい。
ECMAScript仕様のページにリンクが貼られていて、確かにごにょごにょ書かれている。


こちらは、ECMAのJSON仕様(pdf)だ。
ただ、JSONのtext format仕様なので、値の範囲がどうのこうのということは書かれていない。


だから、やはり安全にいくなら、uint64_tは文字列にする方がよいのだろう。
32bitずつにして、上下で表してもよいかもしれんが、とにかく表せないかもしれない書式を使うのは危ないかもしれん。
まあ、そんなことをいえばint64_tだって53bit以上あるのだから同じことか。


それだったら、いっそのこと全部の数字を文字列で表せばいいやん、みたいな気持ちになってしまうので、深追いは止めよう。
大人の対応というのは、最終的に自分への負担が減る対応にするべきなのだ。。。

2017/09/18

[vscode]gdbを使ってみよう(2017/09/18)

コンパイラとしてgcc系のものを使うことが多いので、デバッグもgdb系になる。
が、何十年もやっていながら、未だにgdbに慣れていない。。。

だが、世の中にはGUIで隠してくれるデバッガもある。
dddやinsight、eclipseもプラグインで対応できる。
nRF51をデバッグしていた頃はeclipseを使っていたのだが、起動が重たいので、動かすかどうかをためらうこともあった。

最近、Visual Studio Code(以下、vscode)を使うことが多くなったので、そっちでも同じようなことができそうな気配がする。
まずは、vscodeでgdbを使ったデバッグをしてみよう。


vscodeは更新が多く、また機能をextensionsで実現することも多いため、最新版ではここに書いていることが使えなくなっているかもしれない。

こちらは、2017/08/18に更新されているので、これを眺めながらやっていく。
C++ Programming | Visual Studio Code Docs


ビルドはコマンドラインでやってもよいのだが、せっかくなのでvscodeからやってみよう。
昔やった、lmdbのサンプルコードがあったので、それで試していく。
コード自体はどうでもよいのだが、Hello Worldみたいなサンプルではわかりづらいので、多少込みいったものを選んだだけだ。


サンプルは、こうやってビルドできた。

$ gcc -o tst ex1.c -llmdb -pthread

そのフォルダでvscodeを起動。

$ code .

ファイルで開くとダメそうな気がするので、ディレクトリ指定で開くとよいかもしれん。
その状態で Ctrl+Shift+B を押すと、タスクがないよ、というメッセージが出てくる。
「Configure Build Task」の方をクリックすると、4択になるので「Others」を選択。
すると、.vscode/tasks.jsonというディレクトリとファイルを作ってくれる。

tasks.jsonは、こんな感じで書く。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "gcc",
            "type": "shell",
            "command": "gcc -Wall -ggdb -o tst ${relativeFile} -llmdb -pthread",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

リンク先よりもversionが上がっているので、変わりやすいのかもしれん。


"group"を書いて、"kind"を"build"にしないと、Ctrl+Shift+Bでビルドしてくれなかった。
"problemMatcher"を書いておくと、それに引っかかった出力がタブ「PROBLEMS」に出てくれる。
${file}だとフルパスになるためか、PROBLEMSをクリックしてもファイルがないと言われてしまった。
${relativeFile}だとvscodeを開いたディレクトリからの相対パスになるようで、そっちだとOKだった。


makeしたい場合は、こんな感じで書いた。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "make",
            "type": "shell",
            "command": "make",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

ただ、これは統合開発環境じゃないから仕方ないのだが、problemMatcherは出力をなぞるだけのため、Makefile内でディレクトリ移動してMakefileを呼び出す、みたいなことをやっていると、ファイルを見つけられないようだ。

make用のExtensionsがあるのかもしれんが、まあ今回はよかろう。


次はgdb。

https://vscode-doc-jp.github.io/docs/languages/cpp.html#%E3%83%87%E3%83%90%E3%83%83%E3%82%B0
https://code.visualstudio.com/docs/languages/cpp#_debugging-your-code

どっちを見ても、launch.jsonというファイルを作れ、と書いてある。
仕方ないので、.vscodeディレクトリで右クリックし、「New File」でlaunch.jsonを作った。
そうするとlaunch.jsonファイルがタブで開き、右下辺りに「Add Configuration...」というボタンが出てきた。

ボタンを押すと、versionなどのテンプレートが出てきたので、Enterを押して確定。
まだボタンが出ているので押してみると、追加する中身のテンプレートが選べるようだった。
せっかくなので、C++のLaunchするやつを選択。
これはありがたい。


と、ここまでやってリンク先を見たら、Debug Viewにしてやればファイル作成などは勝手にやってくれたみたいだ。。。
悔しいので、.vscode/launch.jsonを消してやり直す。

まず、左側のデバッグっぽいアイコンをクリックし、Debug Viewにする。
設定してくれそうなアイコンが出てくるので、クリック。
そうすると、さっきのような選択が出てくるので、C++のgdbできそうなものを選択。
まあ、できるファイルは同じっぽいな。


"program"は書き換えないといかんだろう。
"${workspaceRoot}/tst"にする。
ファイル保存して、Viewにあるデバッグ開始しそうなアイコンをクリック!

・・・開始エラー?
よくわからんのでもう一度押すと、今度は動いて、設定していたブレークポイントで止まったようだ。
たぶん、launch.jsonの"stopAtEntry"を設定しておくと、その関数で止まるようになってるんじゃなかろうか。


変数名にマウスを当てると中身が見えるし、構造体も出てくれる。
整数型は10進数で、ポインタは16進数で表示するようだ。
16進数で見たい場合は、WATCHとして追加するしかなさそうだ。
例えば、env->me_flagsという値を16進数で見たかったら、「env->me_flags,h」のように指定するそうだ。
https://github.com/Microsoft/vscode-cpptools/issues/379

2016年12月のことだから、今は別の手段があるかもしれん。。。が、それっぽいのは見つからなかった。
まあ、こういうのは、だいたい解決されていくものだし、方法がないわけではないからよかろう。


こんな感じで、gdbを使うだけであればlaunch.jsonを作るだけでよさそうだ。

2017/09/17

[btc]confオプションはフルパスで書くべし

testnetでなかなかマイニングされないので、regtestに切り替えようとしている。
まあ、testnetは有志によるものっぽいから、何が起きても文句は言えない。。。


まず、testnetとregtestを同時に動かしておけるかどうか。
これは、ダメそうだ。
bitcoindがHTTP serverになるようで、2つめを起動したらエラーになった。

Error: Unable to start HTTP server. See debug log for details.

引数で何か設定すればよいのかもしれんが、まあそこまで切実ではないので、よかろう(実はできるのだが、後述)。


次は、confファイル。
bitcoindはデフォルトで~/.bitcoin/bitcoin.confを見に行くが、regtestのために書き換えるのが面倒だから、regtest用のconfファイルを読み込ませたい。

regtest=1
server=1
txindex=1
rpcuser=xxx
rpcpassword=xxxxx
rpcport=18443

こんな感じか。
rpcportを設定したのは、まあ、確認みたいなものだ。

$ bitcoind -conf=./regtest.conf

そして別のコンソールから確認。

$ bitcoin-cli -conf=./regtest.conf getblockcount
74242

ん??
regtestなのにブロックがあるし、やるたびに増えていってるからどこかからダウンロードしているようだぞ。
networkinfoで見ると、やはりピアが見えているし、ポート番号も8333だ。
ということは、mainnetを見に行ってるらしい。


こうやるのがよさそうだ。

$ bitcoind -conf=./regtest.conf -regtest

納得がいかないのだが、仕方ない。

regtest.confから「regtest=1」を削ってもよいかも。
ただ、bitcoin-cliの方は-confで設定したregtestを見ているようで、-regtestオプションを付けなくてもよいようだ。
まあ、bitcoindが付けているのだから、両方付けた方が統一されていてよいかもしれん。


では、最後にJSON-RPC。

$ curl --user xxx:xxxx --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockcount", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18443/

ダメだ、接続できない。
wiresharkでbitcoin-cliしたときのポートを見ると、18332になってる。
全然confファイルの言うことを聞いてくれんやつだ。。。

そして、ポート番号を18332にしてもダメ。
認証に失敗しているようだから、rpcuserなんかも見てないということか??
しかし、getnetworkinfoで見ると、なんか18444を監視している。
いっちょんいうことばきいてくれんっちゃけんねぇ。。。


このregtest.confを、カレントディレクトリではなく~/.bitcoinの中に置き、-conf=regtest.confとディレクトリ無しにすると、すんなり動く。
-regtestもいらないし、JSON-RPCも書いてある通りの設定になる。
よくわからんが、その方がいろいろやるよりも安全な気がする。


自動実行するときは、systemdに登録しているのだが、そのときはたぶんUserで指定した人の~/.bitcoin/bitcoin.confを使っているのだろう。
ここを見ると、/etc/bitcoin/bitcoin.confを例にしているので、そういうのはありなんだ。。。
https://github.com/bitcoin/bitcoin/blob/master/doc/init.md

systemdのservice設定を見ると、conf指定だが、フルパスで書いているな。
https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service

まさか・・・。

$ bitcoind -conf=`pwd`/regtest.conf

はい、そういうことでした。
confはフルパスで書くべし、でした。

最初に試した、testnetとregtestを同時に動かす、もconfファイルを相対パスで指定していたのでうまく動いていないだけだった。
datadirを別にすれば、regtestを複数立てることもできるんじゃなかろうか。意味はなさそうだがね。

2017/09/16

[bow]lmdbのmdb_env_open()でエラーになる

msg queueを使うプログラムを作っていたのでUbuntu16.04で作業していたのだが、socketに変更したので今のbash on Ubuntu on Windowsでも動かせるようになったんじゃなかろうか、ということでやってみた。

・・・そこに行き着く前に、lmdbのmdb_env_open()でエラーが返ってきた。。。


エラーの内容は、exec format error。
ENOEXECというやつだ。

ずーっとたどると、mmap()でエラーを返しているようだった。
gdbを使わず、printfデバッグで探していたので、たどるのが大変だった・・・。
GUI環境じゃないところで、まだgdbを使えないのだよ、私は。


この辺りかな?
mmap's problem · Issue #658 · Microsoft/BashOnWindows

いろいろ書いてあってよくわからんが、まあ、たぶんbowのバグなんだろう。
2017年秋バージョンに期待だ。

[btc]testnet3

bitcoindでは、ほとんどtestnetを使っている。
bitcoin.confにも「testnet=3」と書いている。

が、btcdなんかは1と書く(3だとエラー)。
つまり、testnetは実質、testnet3しかないというになるだろう。

そもそも、testnet3ってなんだ??


Testnet - Bitcoin Wiki

このページの最終更新日は2017年2月8日なので、新しいといってよいだろう。

testnetには3つあります。

testnet2は、testnetと異なるgenesis blockを持つ最初のtestnet resetだ。
testnet3は、現在のtest networkだ。

2行目の訳が怪しいので、原文を読んでおくれ。
とにかく、初代testnet、testnet2、testnet3があり、今はtestnet3ということだ。

引数だって「-testnet」だし、bitcoin.confが「=1」でも「=3」でも特に動作は変わらないようだ。
bitcoindでも、bool扱いしているように見えるから、0でなければtestnetになるんじゃなかろうかね。