2014年8月11日月曜日

サーバーサイドJAVAの環境を整える


Monacoindの基本的な動きは大体分かったので、実際にWEBサービスの形にしてみようと思います。

Linuxもそんなに詳しくないので、色々と試しながらやってみます。

使う言語はJava。

なぜJavaかというと、過去に、Google App Engine for Java(GAE/J)でWEBサービスを作るというような記事を書いて、フレームワークについても調べて、Slim3やべぇなどと騒いだあげくに、何も作らなかったので、贖罪の意味を込めてJavaを使います。

今回は環境作りです。


まずは、Apacheをインストールします。

$ sudo apt-get update
$ sudo apt-get upgrade

$ sudo apt-get install apache2

この時点で既にApacheは起動しているようで、http://localhostにアクセスすると以下が表示されます。

「あなたの予想に反して~」はどこ行っちゃったんでしょう。
It works!なんて言われても、こっちのほうが予想外です。

とりあえず設定ファイルなどは触らずに次行きます。


次は、Tomcatをインストールします。

$ sudo apt-get install tomcat7

これで必要なJavaなどもまとめてインストールされ、tomcat7ユーザが作成されます。

同じくこの時点でTomcatは起動しているようで、http://localhost:8080にアクセスすると以下が表示されます。

続いて、ドキュメントやらWeb Management Interfaceやらexampleやらをインストールします。

$ sudo apt-get install tomcat7-docs tomcat7-admin tomcat7-examples

以下二つはそのまま見れます。

tomcat7-docs

tomcat7-examples

以下二つは認証が必要です。
tomcat7-admin (manager webapp)
tomcat7-admin (host-manager webapp)

tomcat-users.xmlを編集し、manager-guiとadmin-guiへアクセスするためのIDを作成します。

任意のIDとパスワードを設定します。

$ sudo nano /etc/tomcat7/tomcat-users.xml

tomcat-usersタグの中に以下を追加。
<tomcat-users>
    <user username="admin" password="password" roles="manager-gui,admin-gui"/>
</tomcat-users>

保存したら再起動します。
$ sudo service tomcat7 restart

それぞれ、自分で設定したIDとパスワードでログインします。

tomcat7-admin (manager webapp)


tomcat7-admin ( host-manager webapp)


最後にApacheとの連携の設定を行います。

Apache&Tomcatの連携は、静的なコンテンツはApacheに担当させ、動的なコンテンツをTomcatに担当させるという、良く見る構成です。

ただ、Tomcat単体で動かした場合より低速になったりするようですし、そもそもJSPなどでページを作って行くと、Apacheに担当させるような静的なコンテンツは少なくなり、Apacheは無くても良いという説もあります。

Apacheの拡張機能などを使わないのであれば、Tomcat単体運用も選択肢の一つのようですね。

でもとりあえず連携させときます。

tomcatのserver.xmlを開いて、8080ポートを閉じ、8009ポートを開けます。
$ sudo nano /etc/tomcat7/server.xml

以下をコメントアウトします。
<!--
<Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000" URIEncoding="UTF-8" redirectPort="8443" />
-->

以下のコメントアウトを削除します。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


AJPモジュールの設定ファイルを作成し、連携の設定を行います。
$ sudo nano /etc/apache2/mods-available/proxy_ajp.conf

以下を入力して保存します。
ProxyPass /tomcat/ ajp://localhost:8009/

AJPモジュールを有効化します。
$ sudo a2enmod proxy_ajp

http://localhost/tomcat/にアクセスすると、ApacheからTomcatに飛ばされて、TomcatのIt works !が表示されます。


これでApacheもTomcatもデフォルトで起動するようになっているので、あとは何か作るだけです。
気長にやります。


2014年8月4日月曜日

JSON-RPCを使ってmonacoindを操作する2 WEB Walletを作るには?


Bitcoin API calls 和訳版を参考に、WEB Walletを作るには?という視点でmonacoindで色々やってみました。

流れ的には以下のような感じでしょうか。


getaccountaddressでDeposit用のアドレスを作成。
その際、ユーザ固有のアカウントをアドレスに紐付ける。

既存のものではなく、新しいアドレスを作成するには、getnewaddressで新規作成する。
アカウントのアドレスリストは、getaddressesbyaccountで取得する。

getbalanceでアカウントの残高を確認。
listtransactionsでトランザクション履歴を確認。

sendfromで指定のアドレスへWithdrawする。


では、それぞれのメソッドを確認していきます。


  • getaccountaddress

指定したアカウントに支払いを受けるための、最新のアドレスを返します。
なければ作成、あればそれを返す。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"getaccountaddress","params":["testAc"]}' -H 'content-type:text/plain;' http://127.0.0.1:9359
{"result":"MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC","error":null,"id":"1"}

MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSCがtestAcにおけるDeposit用のアドレスとなります。

  • getnewaddress

呼ぶたびに新しいアドレスを返します。(以下は2回呼んだ結果)

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"getnewaddress","params":["testAc"]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":"MUh5HD2VEC1UGZxxF1TRcKKsFCbGfmjEpq","error":null,"id":"1"}
{"result":"MS6WsHkyb9cFrHrxKFmi7bARwwpvNRvhsH","error":null,"id":"1"}

内部的にどうなっているのか、先ほど使ったgetaccountaddressで確認してみます。

{"result":"MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC","error":null,"id":"1"}

受信用アドレスは、新しいアドレス生成前と変わっていません。


  • getaddressesbyaccount

指定したアカウントのアドレスリストを返します。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"getaddressesbyaccount","params":["testAc"]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":["MUh5HD2VEC1UGZxxF1TRcKKsFCbGfmjEpq","MS6WsHkyb9cFrHrxKFmi7bARwwpvNRvhsH","MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC"],"error":null,"id":"1"}

もともとのアドレスに加え、新規で生成したアドレスがアカウントに紐付いています。


ここで0.01MONAほど入金してみます。

getaddressesbyaccountで確認すると、アドレスが増えています。

{"result":["MLGDvB3UoYEV9FvWkq2xkvFrxh6bPLniQE","MUh5HD2VEC1UGZxxF1TRcKKsFCbGfmjEpq","MS6WsHkyb9cFrHrxKFmi7bARwwpvNRvhsH","MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC"],"error":null,"id":"1"}

getaccountaddressで確認すると、新しいアドレスが入金用アドレスに変わっています。

{"result":"MLGDvB3UoYEV9FvWkq2xkvFrxh6bPLniQE","error":null,"id":"1"}

  • getbalance

指定したアカウントの残高を返します。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"getbalance","params":["testAc"]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":0.01000000,"error":null,"id":"1"}

  • listtransactions

トランザクション履歴を返します。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"listtransactions","params":["testAc"]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":[{"account":"testAc","address":"MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC","category":"receive","amount":0.01000000,"confirmations":6,"blockhash":"d4dd988599a7649897a80ed94dd5f9e3642c9be33d76fa067bda3dcf352802b0","blockindex":18,"blocktime":1407077735,"txid":"9ee8386695853db90dd2d37abc46e65874a68db51e4daf2721e1ce1a3441156b","normtxid":"0e36640249a1b732c99311e8babbc85a7db43f7640b136188e5a78853b014d6f","time":1407077288,"timereceived":1407077288}],"error":null,"id":"1"}

categoryreceiveのトランザクション履歴が確認出来ます。


  • sendfrom

指定したアカウントから送金します。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"1","method":"sendfrom","params":["testAc","MR2j3u5oNWZzAAxeHtSinHUEVNiSbkn8zJ",0.001]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":"92828b7bf40b85b41f7deeb4e8f90ed2a14ced8efa83875132ca9319967f771f","error":null,"id":"1"}

listtransactionsで再度トランザクション履歴を確認してみます。

{"result":[{"account":"testAc","address":"MVPMzNXWwu4db4uwUzFm3NbDLRvpjmfkSC","category":"receive","amount":0.01000000,"confirmations":7,"blockhash":"d4dd988599a7649897a80ed94dd5f9e3642c9be33d76fa067bda3dcf352802b0","blockindex":18,"blocktime":1407077735,"txid":"9ee8386695853db90dd2d37abc46e65874a68db51e4daf2721e1ce1a3441156b","normtxid":"0e36640249a1b732c99311e8babbc85a7db43f7640b136188e5a78853b014d6f","time":1407077288,"timereceived":1407077288},{"account":"testAc","address":"MR2j3u5oNWZzAAxeHtSinHUEVNiSbkn8zJ","category":"send","amount":-0.00100000,"fee":-0.00100000,"confirmations":0,"txid":"92828b7bf40b85b41f7deeb4e8f90ed2a14ced8efa83875132ca9319967f771f","normtxid":"8a13b422a5c0adbe08b4b410d22457e1570142bfde66068a708ec19eddc8aee4","time":1407078088,"timereceived":1407078088}],"error":null,"id":"1"}

categorysendのトランザクションが増えました。


WEB Walletなんてのは実装としては意外と簡単なんですね。

セキュリティとか考えなければ、ですが。

2014年8月3日日曜日

JSON-RPCを使ってmonacoindを操作する


JSON-RPCの動きを検証するために、jqueryなどを使って適当なJavascriptでテストページを作ったのですが、クロスオリジンの問題でうまく動きません。

ポートが異なるだけで別オリジン扱いのようなので、どうしようもないのかな?と思っていたところ、動きをテストするだけならもっと簡単な方法がありました。

cURLという、様々なプロトコルでデータを送受信できるユーティリティを使います。

試しにインストールして使ってみましょう。

$ sudo apt-get install curl
$ curl http://monacoin.org/ja/

これでだーっと標準出力にサイトのソースが表示されます。


では実際にmonacoindを操作してみましょう。

monacoindとJSON-RPCを使って会話をするために必要なIDとPWは、初回起動時にmonacoin.confに設定しているはずです。

そのIDとPWを使ってデフォルトのrpcportにアクセスすると、ちゃんと返事があります。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"getinfo","params":[]}' -H 'content-type:text/plain;' http://127.0.0.1:9402

{"result":{"version":80700,"protocolversion":70002,"walletversion":60000,"balance":0.01800000,"blocks":208195,"timeoffset":44,"connections":8,"proxy":"","difficulty":1105.55691097,"testnet":false,"keypoololdest":1405931648,"keypoolsize":104,"paytxfee":0.00000000,"mininput":0.00001000,"errors":""},"error":null,"id":"curltext"}


monacoin.confの他の設定項目についても見てみます。

いくつかある設定項目の内、重要なのはrpcallowipとrpcportです。
server、listenについては設定しなくても返事があるので、qtを使う時に必要な設定なのか、デフォルトが有効な設定のようです。

まずrpcportを設定すると、待ち受けるポートをデフォルトの9402から変更出来ます。

rpcport=9359

monacoin.confで上記のように設定すると、以下のように9359ポートで動いているのが分かります。

$ curl --user 'rpcuserid:rpcpassword' --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"getinfo","params":[]}' -H 'content-type:text/plain;' http://127.0.0.1:9359

{"result":{"version":80700,"protocolversion":70002,"walletversion":60000,"balance":0.01800000,"blocks":208196,"timeoffset":44,"connections":6,"proxy":"","difficulty":938.68052376,"testnet":false,"keypoololdest":1405931648,"keypoolsize":104,"paytxfee":0.00000000,"mininput":0.00001000,"errors":""},"error":null,"id":"curltext"}

次に、rpcallowipを設定すると、別のIPからでもアクセス出来るようになります。

以下のコメントアウトした1行目のように設定にすると、ネットワークごとアクセス許可が出来ます。

が、基本的にはlocalhostからのみの接続とすべきでしょう。
そうであれば、デフォルトでlocalhost限定なので、わざわざ設定しなくても良さそうですが、設定しろとよく書いてあるので、念のため。

#rpcallowip=192.168.0.*
rpcallowip=127.0.0.1

ちなみにrpcpasswordを間違えると、以下のようにHTMLでレスポンスがあります。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML>
<HEAD>
<TITLE>Error</TITLE>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>
</HEAD>
<BODY><H1>401 Unauthorized.</H1></BODY>
</HTML>