CoinomiのMonacoinサーバがどうなっているのか調べてみた
CoinomiというAndroid用ウォレットでMonacoinが使えるようになっている。
このウォレットではelectrum-serverを使っているはずなので、ソースコードにサーバのアドレスが書かれているはずである。 調べてみると wallet/src/main/java/com/coinomi/wallet/Constants.java で定義されていた。
new CoinAddress(MonacoinMain.get(), new ServerAddress("mona-cce-1.coinomi.net", 5022),
new ServerAddress("mona-cce-2.coinomi.net", 5022)),
Litecoinも以下のように定義されている。
new CoinAddress(LitecoinMain.get(), new ServerAddress("ltc-cce-1.coinomi.net", 5002),
new ServerAddress("ltc-cce-2.coinomi.net", 5002)),
すべてcoinomi.netのサブドメインとなっているようだ。
Monacoin用のElectrumはまだないと思うので、とりあえずLitecoinでつないでみたところ、ちゃんと使えた。
$ electrum-ltc -1 -s ltc-cce-2.coinomi.net:5002:t
他にもいろいろとaltcoinがあるしtestnetもいくつかあるので、実験用にも使えそうである。
Transaction feeをケチると認証されない件
Bitcoinの送信でtx feeを0.00001BTCにして成功したことがあったので、何度か同じように試してみたが失敗することがあったので調べてみた。
Transaction fees - Bitcoin Wiki
Sending A transaction may be safely sent without fees if these conditions are met:
- It is smaller than 1,000 bytes.
- All outputs are 0.01 BTC or larger.
- Its priority is large enough (see the Technical Info section below)
つまり、以下の条件のときはtx feeなしで成功するかも、とのこと。
- 1,000バイトより少ない
- 出力が 0.01 BTCより多い
- プライオリティが十分に高い
3つ目が分かりにくいが、以下の計算式で求められるとのこと。
priority = sum(input_value_in_base_units * input_age)/size_in_bytes
例として、入力が次の2つ、10 confirmationsの5 BTCが1つと、3 confirmationsの2 BTCのときで、出力サイズが500バイトだとすると、プライオリティは以下の計算式となるようだ。
(500000000 * 10 + 200000000 * 3) / 500 = 11,200,000
要は額が大きくて、長いこと移動されていないコインはプライオリティが高いということだろう。
Otherwise, the reference implementation will round up the transaction size to the next thousand bytes and add a fee of 0.1 mBTC (0.0001 BTC) per thousand bytes[1].
つまり、上記の3つの条件が揃わないときは1,000バイト毎に0.0001 BTCをtx feeとして渡さないとうまくいかないようだ。
Electrum-DOGEも動かしてみた
Electrum-DOGEも動いたのでメモしておく。 ネットワークは doge-cce-1.coinomi.net tcp 5003 を使えばいける。doge-cce-2もついでに追加しておくとよい。 TX Feeは1DOGE(約0.015円)なので、テスト用には一番良いかもしれない。少し入手しておこうかと思う。
[追記] 動いたと思いましたが、着信がunverifiedのまま進みませんでした。例外も出ているので何か問題があるようです。
Litecoin用のElectrumを使ってみた
Electrumが結構お気に入りなので、Litecoin用のElectrumも使ってみた。
使い方はREADME.rstでは以下のようになっている。
./electrum-ltc
インストールするにはこんな感じか。
pyrcc4 icons.qrc -o gui/qt/icons_rc.py
python setup.py sdist --format=zip,gztar
sudo pip install --pre dist/Electrum-LTC-2.6.tar.gz
ただ、これだけだと初期ノードにつながらないので、以下のサイトにあるノードを追加した。
差分は以下のような感じ。ついでにRPCのポート番号を7777から7778に変更。
[追記] こんなことをしなくてもsetconfigでできました。
$ electrum-ltc setconfig rpcport 7778
立ち上げた後、コンソールでgetservers()すると7ノードほど表示された。 なお、上記パッチをあてる前に起動してしまった場合は ~/.electrum-ltc/recent_servers を一度消しておいた方がよさそう。
daemonとして立ち上げる場合は electrum-ltc daemon start とすればよい。
$ electrum-ltc daemon start
helpを見れば色々とコマンドが見れる。RPCなので、curlとかからでも操作できるので便利。
dRubyで並列処理
(※12月の1日から25日まで、日替わりで Ruby の Tips を紹介するイベント、 Ruby Advent Calendar jp: 2009 の 11 日目です。昨日は no6v さんでした。明日は id:willnet さんの予定です。)
RubyのThreadは時分割なので並列処理を行いたいときにちょっと困ります。そんなときにはdRubyを使ってみるのはいかがでしょうか。
#!/usr/bin/ruby require 'drb/drb' class MonteCarlo def initialize(seed) srand(seed) end def dice(n) best = rand n.times do r = rand best = r if r < best end best end end PROCESSORS = (ARGV[0] || 1).to_i pids = [] workers = PROCESSORS.times.map do |i| uri = "druby://localhost:#{12345 + i}" pids << fork { DRb.start_service(uri, MonteCarlo.new(i)); sleep } DRbObject.new_with_uri(uri) end begin n = 5000000 / PROCESSORS q = Queue.new sleep 0.1 ts = workers.map do |foo| Thread.start(foo) {|f| q.push(f.dice(n))} end ts.each{|t| t.join} p q.size.times.map{q.pop}.min ensure pids.each {|pid| Process.kill(:TERM, pid)} end
このサンプルコードは500万回の疑似乱数の中から最も0に近い実数を見つけだすというプログラムです。sleep 0.1の部分は見なかったことにしてください。サンプルなので内容はあまり意味がありませんが、要は並列処理したい部分をMonteCarloのdiceの中に書いてあげればいいわけです。このプログラムは以下のように並列処理数を指定して実行します。
$ ruby montecarlo.rb 2
この例では2つのプロセスを並列で動かします。最近のデュアルコアのCPUでは2を指定しましょう。コアがもっと多い人は「界王拳4倍!」とか唱えながら4とかを指定するといいでしょう。コアが1つしかない方はヤムチャの気分になってあきらめてください。というのは冗談で、コア数を超えていても一応動きますので試してみてください。
メインのプロセスはforkで生成された子プロセス2つに命令を送り、待つためのスレッドがそれぞれ生成され、joinで終了を待ちます。
結果はQueueに格納され、これを個数分popして取り出し、その中から最小値を取り出して表示して終了します。Queueは便利ですね。
以下はベンチマークです。平均とかは取っていないのでかなり適当ですが。それにしてもやっぱりCore i7は速いですね。こんなことにしかこのPCを活かせていないのが悲しいですが。
プロセス数 | CoreDuo | Core i7 |
---|---|---|
1 | 7.284s | 4.482s |
2 | 3.882s | 2.120s |
3 | 3.898s | 1.417s |
4 | 3.876s | 1.102s |
5 | 3.695s | 1.163s |
6 | 3.754s | 0.997s |
7 | 3.716s | 0.958s |
8 | 3.666s | 0.974s |
9 | 3.738s | 1.029s |
10 | 3.713s | 0.983s |
11 | 3.905s | 0.981s |
12 | 3.776s | 0.952s |
13 | 3.697s | 0.934s |
18 | 3.816s | 0.896s |
32 | 3.669s | 0.907s |
64 | 4.036s | 0.942s |
96 | 4.643s | 0.973s |
Ruby1.9.1
プロセス数 | CoreDuo | Core i7 |
---|---|---|
1 | 4.675s | 2.082s |
2 | 2.677s | 1.112s |
3 | 2.656s | 0.791s |
4 | 2.609s | 0.625s |
5 | 2.746s | 0.705s |
6 | 2.649s | 0.656s |
7 | 2.581s | 0.641s |
8 | 2.626s | 0.616s |
9 | 2.691s | 0.646s |
10 | 2.617s | 0.632s |
11 | 2.619s | 0.629s |
12 | 2.573s | 0.633s |
16 | 2.705s | 0.639s |
32 | 2.619s | 0.662s |
64 | 3.144s | 0.625s |
96 | 3.010s | 0.797s |
なお、このプログラムはlinuxでしか試していませんので、動かなかった場合はがんばって動くようにしてもらえると助かります。また、MacRubyな方はこんなことしなくても普通にスレッドで動かせばよいらしいです。(くやしー!)
new Objectはスケールするか?
$ cat a.scala import scala.concurrent.ops._ import java.lang.System.{currentTimeMillis => curt} def foo(n: Int) = { (0 until n).foreach { _ => new Object } } def bench(weight: Int, ncore: Int) { val s = curt (0 until ncore).map(_ => future(foo(weight))).toList.foreach(_()) val e = curt println("%d: %d ms".format(ncore, e - s)) } (0 to 3).foreach { _ => bench(40000000, 1) bench(20000000, 2) bench(10000000, 4) } $ scala a.scala 1: 868 ms 2: 598 ms 4: 594 ms 1: 783 ms 2: 587 ms 4: 596 ms 1: 784 ms 2: 587 ms 4: 593 ms 1: 785 ms 2: 590 ms 4: 589 ms
CoreDuoで実行したので4はあまり意味がないです。