2017年9月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になるんじゃなかろうかね。

2017年9月14日

[tech]IPFS

世の中にはいろいろと技術があり、「これどうやってるんだろう??」というものも多い。
IPFSも、私にとっては「ど、どうやってるんだ??」という技術の一つだ。

なんというか、ブロックチェーンと非常に似たものを感じる。


ブロックチェーンでの開発を行っていると、何かに依存した状況を極力作りたくない。
「ああ、この情報をサーバに置きさえすれば解決するのに・・・」と思ったとしても、それをやってしまうと依存が生じてしまう。
まあ、多少はよいか、という考え方もあるのかもしれないが、やっぱりここまできたらねー、という意地みたいなものも出てくる。


そこで、IPFSだ。
全然技術的に理解はできていないのだが、ファイルをアップロードすると、適当にファイルを分割されて、適当に冗長性を持たせつつ、適当に分散させて、ノードを提供している人たちに持たせている。
たぶん、ブロックチェーンのフルノードみたいに、全員が同じものを持つ、というものではないように思う。
また、単に分割してばらまくわけでもなさそうだ。

それを取得するには、アップロードしたときに渡されるハッシュ値を使う。
ファイル名に相当するのかな。
それを使うと、そのハッシュ値に相当するものがファイルとして取得できるようだ。


サイトにある「Try it」を試しただけで、それ以上は入り込んでいない。
私がやったときは、子猫の画像が取得できた。


まあ、Bitcoinのブロックチェーンだって、こんだけ人々がアクセスしてもハッシュ値でトランザクションが一意に表せているので、IPFSの参加者くらいであれば十分にまかなえているのかもしれないし、ハッシュ値のサイズだって違うかもしれない。

だから、ハッシュ値でファイル名の代わりにする、という考え方はまだわかるのだが、残りの重要な部分はさっぱりわからん。
RAIDみたいな感じを持ってしまうけど、たぶんどこかのIPFSノードが動いていないくらいだったら問題ないんじゃなかろうか。


これは、なんというか、ぞくぞくする怖さを感じましたな。
こういう技術が生まれてくることに、まだまだ視野が狭かったなー、と感じざるを得ない。
いや、自分で生み出せたかも、とかじゃなくて(無理無理...)、世の中で未発見のものは、発見されたとしても私には理解ができないものなんじゃなかろうか、などと考えていたことに対してだ。

一般技術者としては、その発明/発見に敬意を表しつつ、理解し、より使いやすい形にしたり、安全にしたり、応用したりするのがまっとうなやり方かな、と思う。

2017年9月11日

[c/c++][linux]stdoutへのリダイレクトが期待通りにできない

共通で使っている処理があり、そこは出力を標準出力に行っている。
ただ、一部だけ、どうしてもファイルに掃き出したいと考えた。
元の方は書き換えたくなかったので、呼び出し元で標準出力をファイルにつなげてやればよいだろう。

この処理は何回も呼び出し、それぞれ別のファイルに出力したい。
だから単純なリダイレクトではないのだけど、まあclose()してやるだけだろう。。。


うまくいかなかった。

リダイレクトを分割したいが、うまくいかない

ファイルは3つできるのだが、中身は3.txtにしか入っていない。
そして、3.txtには全部の出力が入っているのだ。
fdをclose()させていないが、あんまり関係が無かった。

標準出力は出力タイミングまでバッファにためるタイプだったはずなので、SYNCっぽいものをあれこれ追加したのだが、どれもダメだ。


じゃあ、標準エラー出力だったらバッファにためないからいいんじゃなかろうか、ということでやってみると、OKだった。

stderrならうまくいく


ということは、システムコール側ではなく、もっと上位層で制御されているということか。
ならば、ファイルディスクリプタの1をfsync()するのではなく、stdoutの方をfflush()したらいいんじゃなかろうか?

fflush(stdout)するとOK

OKだった。
なるほどねぇ。


ただ、一部だけリダイレクトさせるのも格好が悪いので、結局実装としては別の関数にしてFILE*を取るようにしたのであった。

2017年9月9日

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (19) : 完

動かん(18)で、XSDKでRunした場合はZyboのLinuxではなく、素の環境で動いているんじゃないか、という疑惑が発覚した(私の中で)。

素の環境というのは、リセットベクタから起動した後、OSを介さずにC Runtimeだけ動かし、すぐにmain()から動き始める、という意味だ。

バイナリの種類が違いそうだというのは、fileコマンドの結果によるものだ。
PetaLinux用の/bin/bashと比較しよう。


$ file bash
bash: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=bf9ec80803a2f03da139c81eddb5bc276cb5250b, stripped


$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped


dynamically linkedかstatically linkedだけでは判断できないのだが、「for GNU/Linux」とまで出力されては、違いがあることを認識せざるを得まい。


Windows版のXSDK v2017.2には、どっちのコンパイラもあるようだ。

image

aarch32は、archがARM32bit版の意味かな?
他にもフォルダがあり、aarch64やmicroblazeもある。
こんだけコンパイラがいっぱい入っていれば、ダウンロードサイズも大きくなるわな。。。

単なるarmフォルダもあり、こっちはarm-xilinx-eabiやarm-xilinx-linux-gnueabiもある。

SDK\2017.2\gnu\arm\nt\bin>arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2015.05-17) 4.9.2


SDK\2017.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin>arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC Snapshot 6.2-2016.11) 6.2.1 20161114

ほー。
久しぶりにSourceryという名前を見た。


選択は、プロパティ画面で、「C/C++ Build > Tool Chain Editor」からできそうだった。

image

何も考えずに作ったプロジェクトは、上の図のように選択されていた。
プロジェクトは新規作成したので、どこかで選択できるようになっているはず。

これか。

image

OS Platformがデフォルトで「standalone」になっていたのだ。
これが「linux」ならよいのか。


「linux」にすると、何やら更新が行われ、少し設定項目が変わったようだ。

image

Windowsでやるときも設定できるのだろうか?
そのままウィザードを進めると、テンプレートから空アプリかhelloworldかが選べるので、今回はhelloworldを選択。
自動でビルドしてくれるので、できているELFファイルをSDカードにコピーして、PetaLinux起動。
Zyboで立ち上げて、実行。

・・・動くやん。。。


20回に達する前に解決してよかった、と前向きに考えよう。
長い連載で理解したのはこういうことだ。

  • XSDKでアプリのプロジェクトを作るとき、デフォルトでは「standalone」になっていて、これはOS無しで動くバイナリ
  • OS設定を「Linux」にすると、Windows版のXSDKであってもARM Linuxで動くELFファイルを作ってくれる
  • PetaLinuxのCustom moduleではxparameters.hを読んでくれないので、なんとかせんといかんようだ

なお、どのコンパイラが選択されているかは、XSDKのPreferencesにある「Xilinx SDK > Toolchain Preferences」から確認できそうだ。

image

ZynqはCortex-A9だったと思うので、Linaroがデフォルトのようだ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (18)

18回目になるのに、まだ解決しないとは・・・。
いや、そもそも最初の目的はなんだったっけ?

第1回を見ると、Zyboのチュートリアル通りにやってみたものの、EclipseベースのSDKから実行すると動くのだが、実行ファイルをPetaLinux上にコピーして実行してもIllegal Instructionが発生した、ということのようだ。
じゃあPetaLinuxの環境でビルドせんといかんのじゃなかろうか、と。
まずは簡単なものから、と考えて見ていったら、Interface誌にJEポートをGPIO制御するドライバサンプルがあって・・・、というのが、現状だ。


しかし、XSDKのベースとしている環境を変更する、という方向もありかもしれん。
せっかくXSDKがあるのだから、コマンドラインでビルドするPetaLinuxはLinux環境やドライバまでで、アプリはXSDKでやっていきたいではないか。


久々にXSDKを立ち上げ、helloworldアプリをビルドした。
そして、XSDKからRunさせると、ちゃんと"Hello Wrold"がコンソールに出力される。
ここでいうコンソールは、ZyboのUSBをPCに接続して開いたTeraTermのUARTコンソールだ。

そのhello.elfを、ビルドしたPetaLinuxが入っているSDカードにコピーして実行すると、やっぱりIlletal Instructionになる。
Zyboチュートリアルのときは、ハードウェアが関係して、不正なアクセスか何かが発生してダメなのかと思っていたけど、そうではないということか?


まずは、fileコマンドで確認しよう。
PC Linux上で確認する。

$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

staticリンクだから、ライブラリがないということではないだろう。
まあ、そうだったら別のエラーになるはずだ。


Illegal Instruction | Zedboard

む、「Linux Application」と「Standalone Application」の違いがあるのか。
よく考えれば、XSDKから実行するときは、ZyboにLinuxが立ち上がってなくても動作しているし、XSDKからLinux環境ごと転送して起動させているような様子もない。すぐ実行されるし。

ということは、このELFファイルはLinux環境向けではない・・・?
普通のLinux環境向けバイナリはどうなるんだっけ。。。

$ file /bin/grep
/bin/grep: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a28bf08898e693819102c974c8e54fdcf6f8a7a6, stripped

ああ、そうなのか。。。
XSDKってなんとなくLinux用のバイナリを作ると考えていたのだけど、よく考えたらFreeRTOSもサポートしているので、素のバイナリも生成することができないといかんのか。


コンパイラ変更とかでよいのかしら?
解決は次回にして、今回はここまでにしよう。

2017年9月8日

[btc]TXIDとSegwitのTXIDとWTXID

TXID、というものがある。
Transaction IDの略だ。

IDというと、どこかで管理したりしていそうだが、Bitcoinはどこかに依存することがないというか、全体に依存しているというかで、データのためのデータはそんなにないと思う。

ただ、トランザクションを一意に表す数字がないと不便なのも確か。
だから、トランザクション自体のデータからハッシュ計算してIDを求めている。


さて、Segwitが出る以前。
TXIDはシンプルで、トランザクションデータ全体をSHA256し、それをさらにSHA256した値(32byte)だった。

トランザクションの構成は、こうだ。

  • version
  • txin
  • txout
  • locktime

bitcoindでトランザクションを作ったことがある人はわかるだろうが、順番としては、

  • 署名が空のトランザクションを作る
  • 署名する

という手順を踏む。
署名したトランザクションはブロックチェーンに公開することができるので、署名するのは最後なのだ。
だから、TXIDが計算できるのは署名後ということになる。


さて、時代はSegwit。
Segregated Witnessという名前の通り、署名が分離されたトランザクションになる。
トランザクションから分離したということは・・・TXIDからも分離されたのだ(そういう理屈なのかどうかは、知らん)。

しかし、トランザクションデータには署名が入っている。
細かく言えば、txメッセージで送信するトランザクションデータには署名が載っている。
ではSegwitなトランザクションのTXIDはなんなのかというと、計算方法が以前と異なるのである。
計算式はシンプルなTXID時代からするとかなり面倒になったのだが、署名部分は計算から除外するようになった。

だから、非SegwitトランザクションのTXID計算方法と、SegwitトランザクションのTXID計算方法は異なるのだ。


だいたい話は終わりなのだが、余談としてWTXIDのことも書いておこう。

ずばり、WTXIDは、Segwitトランザクションを以前と同じTXID計算方法で求めた値のことだ。
ただ、WTXIDの使いどころが分からないので、計算をしたことがなく、検証まではできていない。
https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-id

2017年9月7日

[c/c++]JSON-RPCでuint64_tに対応するのは難しいか

最近、サーバ型というかdaemon型というか、バックグラウンドで動くアプリを作っている。
それに対して外部から指示を与えたいことがあるのだが、今までLinuxのメッセージキューを使っていた。
それで困っていなかったのだが、他の類似するツールを見るとJSON-RPCでやりとりしていることが分かった。

長いものに・・・巻かれるしかないのか・・・。

同じ形式でAPIを受け付けるように作っておけば、外側の部分は自分で作らずに済むし、そうしておくことによって他の人から使ってもらえる可能性も上がる(たぶん)。

あきらめて、JSON-RPCのパラメータを受け付けるように改造することにした。


こういうときは、githubなどからライブラリを探して、それを使うのがよいだろう。
Google検索して見つかった一番上が、こちら。

httpの方が汎用性が高いのかもしれないが、TCPのsocketをつくってwrite/read()すれば動くので、作るのが楽そうだ。


半分ほど実装していて思い出したが、今回はuint64_tを使っているのだった。
しかし、この子はintかdoubleしか持っていない。
doubleでは丸められる可能性があって困るのだ。。

そういえば、と別の場所で使っているjanssonも見直してみたが、long long型の対応になっているのでint64_tはいけるものの、uint64_tは無理だろう。

よく考えれば、Cは標準型でそこまでしか対応していないし、JavaみたいにBigDecimalみたいな標準もないため、そもそも対応すること自体が難しいだろう。
janssonのbignum版を作っている人もあったが、整数型はgmpかopensslを使うことになるようだ。
うーん、それはちょっと今回の方針にあわない。。。


今回はintかuint64_tまでしか使わないので、自分でuint64_t対応を追加すればよいのだろうが、気力が湧かない(それでいいのか)。
ひとまず、逃げの手段として、uint64_tは文字列に変換して、読み出すときはまたuint64_tとして戻すことにした。
array型で、順番がこちらで決められるからできる技だ。
ただ、serverもclientも自前じゃないとダメなんだけどね。。。


gccなら__int128があるようで、それならuint64_tのサイズでも収まるから少し気は楽になるが、うーん、やっぱり、なんかねー。
この辺りは、pythonみたいに自由な幅にできる言語が有利ですな。

2017年9月5日

[btc]regtestでsegwitするにはブロック数がいる

最近、というわけでもないが、testnetが今ひとつ順調ではないように見える。

数日前は、トランザクションが1つ(というか、coinbaseだけ)のブロックが多く、トランザクションが全然さばけていないようだった。
https://testnet.blockexplorer.com/blocks-date/2017-08-31

今日は普通だと思っていたのだけど、なんかsegwitのトランザクションだけ除外されていないか?
そういう真似ができるのかどうか知らんが、数時間前に発行したsegwitのトランザクションがマイニングされないのに、faucetから送ってもらったトランザクションはすぐにマイニングされていたのだ。


よくわからんが、不安定で作業にならないので、regtestを使うことにした。
初めてのregtestだ。


Bitcoinを使ったアプリケーションのテスト環境 - Develop with pleasure!

bitcoin.confを書き換える程度で動かせた。
regtest時のbitcoin-qtは水色だった。

書いてあるように、bitcoin-cliなどでgenerateコマンドを使うと、その数だけブロックを生成してくれる。
これで、マイニングされたことになるので、ビクビクしなくてよいのだ。


しかし・・・segwitのトランザクションを作ろうとaddwitnessaddressしたのだが、segwitは対応していないとか出てくる。。。
regtestなのに!

検索すると、ちゃんと調べてくれた人が見つかった。
How to activate segwit on regtest

あー、101ブロックしか生成していなかったけど、432ブロック以上ないとsegwitがActiveにならないんだ。
しかし、432ブロックというのはなんだろうか?

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/bip68-sequence.py#L371
BIP68関連らしい。

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/segwit.py#L198
こちらも432だが、144 * 3ということになっている。

144 = 24(時間) * 60(分) / 10(ブロック毎分)

ということかな?
mainnetの時間で3日分というのが432の根拠のようだ。

なんで3日なのかというのは、わからんかったが、まあいいや。

2017年9月4日

[win][修復]Windows10が立ち上がらなくなったので復旧 - 2

まさかの第2弾。
というよりも、OSが立ち上がらないということはしばしばあると思うので、その記録だ。

hiro99ma blog: [win][修復]Windows10が立ち上がらなくなったので復旧


予備で用意しているPCがあり、そのWindows10が起動しなくなった。
用意しているというか、マザーボードやCPUが古くなったので一式買い替えたのだが、その前に使っていたPCだ。
Windowsも新しいPCに持っていこうと思ったのだが、マザーボードが変わるとインストールできないという話を聞いたので、そちらは別途購入したのだ。

最後にWindows Updateしたのが1年くらい前だったので、たぶんその間は起動していないのだと思う。
無事に起動したので、過去のデータはもう不要だろう、とWindowsのリセットで全データ消去を選択。
自動的に再起動してクリーンアップが進んだのだが、途中かどこかでブルースクリーンが発生し、再起動を繰り返すようになってしまったのだ。

クリーンアップしたらきれいな状態で立ち上がるだろう、と思っていたので、修復ディスクは作っていたものの、復旧ディスクは作っていない。
復旧ディスクって、USBメモリ1本使うので、もったいない、と思ったのが正直なところだ。


ブルースクリーンになるのはログイン画面が出る前なのだが、F4を押して起動させるとあのメニューは出てくる。
そこでまたPCのリセットを行ったが、エラーが起きましたというだけで何もできない。
修復ディスクで起動させても、同じようなものだった。

復旧ディスクであれば何でもよいかと思い、ThinkPadで作っていた復旧ディスクで起動したのだが、起動させている間にネットで検索すると、どうも共有できるものではないらしい。
ThinkPadはWin10 Home、予備PCはWin10 Proだったのだが、予備PCにWin10 Homeとかいうパーティションが作られてしまった。。。
もちろん、復旧もできなかった。

このWin10はWin7からのネットワークアップグレードでできているので、Win7のディスクはあるものの、Win10用は何もないのだ。


もうあきらめるしかないかと思ったのだが、もう1つ手段があった。
新しいPC用に買ったWindows10のインストールディスクだ。
これが、使えた。
ディスクから起動すると復旧させるボタンが出てくるのだが、それは押さずに普通のインストールを進める。
プロダクトIDを入力するところをスキップさせると、起動時にネットワーク認証を行うらしい(画面にそう出ていた)。
そうやって進めると、無事に起動できる状態になった。

よかったよかった。
復旧ディスクを急いで作ったのは、言うまでもない。


復旧ディスクって、もうすぐ2017年秋バージョンのリリースが行われるそうなのだが、新しくなるごとに更新した方がよいのだろうか?
そこら辺がよくわからんね。