- 投稿日:2019-04-03T23:46:12+09:00
Macにgoをインストールするまで
macにgoをインストールするまで
インストール手順
anyenvのインストール
brew install anyenv # .bash_profileを直接変更しても良い echo 'eval "$(anyenv init -)"' >> ~/.bash_profile exec $SHELL -lgoenvのインストール
anyenv install goenv # インストールができてるか確認できる goenv -v exec $SHELL -l goenv install -l # 何もなければ最新のバージョンをインストール goenv install 1.12.1 # 特定ディレクトリ配下で異なるバージョン使いたければlocal使う goenv global 1.12.1 # インストールできてるか確認 go versionGOPATHの追加
hadaは$HOME直下にgoディレクトリを作成してそこをGOPATHにした
最終的な
.bash_profile
.bash_profileexport GOPATH=$HOME/go export GOBIN=$GOPATH/1.12.1/bin export PATH=$GOPATH/bin:$PATH eval "$(anyenv init -)"
go env
とかでgo周りの環境変数が正しく設定されてるか確認
GOPATHにバージョン名のディレクトリとかできるけど気にしない
/Users/yota.hada/go/1.12.1
depを入れる
go get -u github.com/golang/dep/cmd/dep # GOBINを設定してればdepコマンドが使えるはず dep versionvscode使ってる場合
goの拡張機能入れる
settingにGOPATHを追加する
settings.json"go.gocodeAutoBuild": true, "go.gopath": "/Users/yota.hada/go/1.12.1",最初にgoファイル開いたときに推奨のライブラリとかおすすめされるのでインストールしておく
- 投稿日:2019-04-03T23:13:25+09:00
【2019年4月版】Solidityでビルドしたバイナリがちゃんと動くかHyperledgerのUTでデバッグしてみる。
ちょっと、何言ってるかわからない。
えっと、Ethereum スマートコントラクトの Hyperledger 上でのデバッグ方法です。いや、やっぱりわかりませんね。
こちらの記事「Hyperledger fabric の EVM を試す」で Hyperledger 上で EVM が動かせて、Solidity でビルドしたスマートコントラクトがデプロイできてちゃんと動作する、というのはご紹介いたしました。
ところがですね・・・
デプロイ手順がめんどくさいweb3.js経由のデプロイしてしっかりブロックチェーンに書き込まれると後戻りができないのでその手前でごにょごにょしてみたいわけです。ま、要するにデプロイ手順がめんどくさいのです!!
今回のゴール
hyperledger-fabric で EVM のチェインコード(Hyperledger流のスマートコントラクト)を実行する実際のモジュールである "fabic-chaincode-evm" のUTコードに自前のスマートコントラクトを追加してデバッグしてみる、という試みです。
対象環境
OS: Windows 10
IDE: VSCode
言語: GO 1.12.1VSCodeはエディタですがもはやIDEでしょうということで。
対象のスマートコントラクト
実際にEVMで動くかどうか試してみたいのは前回の記事「イーサリアムのテストネットで初めてのオリジナルトークンを公開してみる」でデプロイした"マイERC20トークン"のスマートコントラクトです。OpenZeppelinをimportしたスマートコントラクトがHyperledgerで動くなら、ERC721トークンがHyperledgerに乗っかることも可能じゃないですかっ!?っていうことで、試してみたいわけです。
簡単ではございますが、こちらです。pragma solidity ^0.5.2; import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; contract MyTokenERC20Sample is ERC20, ERC20Detailed { string private _name = "Hyperledger Token"; string private _symbol = "HYP"; uint8 private _decimals = 18; uint value = 1000000; constructor() ERC20Detailed(_name, _symbol, _decimals) public { _mint(msg.sender, value); } }
_decimal
やvalue
が適当すぎるのはご愛嬌ということで・・・対象プロジェクト
Hyperledger配下には多数のプロジェクトがございますが、今回のターゲットは以下です。
環境構築
それではさっそくデバッグ環境の構築を行います。
GO言語環境の構築
fabric-chaincode-evm
の開発環境であるGo言語での開発環境構築を整えます。Go言語バージョン
1.12.1
のインストーラーを以下のダウンロードサイトからダウンロード&インストールをお願いします。インストール後、
$GOPATH/bin
をPATH
に追加しておきます。続いて
dep
を入れます。> go get -u github.com/golang/dep/cmd/depプロジェクトのクローン
go get
でプロジェクトを取得します。> go get -u github.com/hyperledger/fabric-chaincode-evmうまくいかない場合は
mkdir
で自前でフォルダ作成し、階層ずれないように注意しつつgit clone
します。> mkdir $GOPATH/src/github.com/hyperledger > cd $GOPATH/src/github.com/hyperledger > git clone https://github.com/hyperledger/fabric-chaincode-evm.git > cd fabric-chaincode-evmつづいて依存モジュールのインストール
dep
で一発です。> dep ensureVSCode の起動
VS Codeを起動し、Go言語用のプラグインをインストールしてください。Extentionの検索で
go
を調べるとMicrosoft提供のGoプラグインが見つかると思います。ターゲットの階層へ移動
いよいよ確信へと迫ります。
> cd evmccまずは試しにターミナルから
go test
と打って通常のUTが動くかどうか、確かめます。いや、動いてくれなきゃ困るけど・・・> go testVSCodeのデバッグ設定
続きましてVSCodeから単体テストのデバッグ起動を行うための設定をします。
デバッグ画面から ⚙ ボタンクリックによって
launch.json
が開きます。エディタの右下のAdd Configuration...
ボタンがありがたいです。
Add Configuration...
ボタンでGo: Launch test function
を選ぶとスニペット貼り付けてくれるので、以下のように設定を変更します。{ "name": "Launch test function", "type": "go", "request": "launch", "mode": "test", "program": "${workspaceFolder}/evmcc", "args": ["-ginkgo.v", "-ginkgo.trace"] },上記のように
go test
からginkgo
にフラグなどの引数を渡したい場合は-ginkgo.v
のように記述します。例えばログを詳細に出したい場合は以下のようにするわけです。
go test -ginkgo.vGinkgo について
さらっと Ginkgo についてご紹介すると GO言語での BDD ベースのテストフレームワークでございます。
他言語での BDD フレームワークに親しんでいる方は特に引っかかることもないと思います。
Describe
、Context
の 2 段階構成でIt
,Expect
と書けます。
またアサーションは標準でgomega
がおすすめなようです。以下は
evmcc_test.go
の一部です。evmcc_test.goDescribe("Init", func() { It("returns an OK response", func() { res := evmcc.Init(stub) Expect(res.Status).To(Equal(int32(shim.OK))) Expect(res.Payload).To(Equal([]byte(nil))) }) })テストケースの作成
さて環境構築は完了です。いよいよテストケースを追加してみます。
Solidity でビルドしたバイナリの準備
いつもの通り、Remix サーバーで上記で紹介したスマートコントラクトのコードを貼り付けます。
OpenZeppelin のコードが
solidity ^0.5.2;
の縛りが入っているのでこちらもそれに合わせます。
コンパイラを0.5.2
以上のものを選択し、コンパイラのロードが終了後Ctrl+S
などでコンパイルします。
コンパイルが無事に終わったようであればBytecode
ボタンをクリックでバイナリを取得し、適当なテキストエディタに貼り付けておきます。テストコードの追加
他のテストケースの冒頭部分を拝借して以下のようなコードを追加いたしました。
ここでは単にデプロイするだけのチェックです。Describe("ERC20 with OpenZeppelin Dapp", func() { var ( user0Cert = `-----BEGIN CERTIFICATE----- MIIB/zCCAaWgAwIBAgIRAKaex32sim4PQR6kDPEPVnwwCgYIKoZIzj0EAwIwaTEL MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt cGxlLmNvbTAeFw0xNzA3MjYwNDM1MDJaFw0yNzA3MjQwNDM1MDJaMEoxCzAJBgNV BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp c2NvMQ4wDAYDVQQDEwVwZWVyMDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPzs BSdIIB0GrKmKWn0N8mMfxWs2s1D6K+xvTvVJ3wUj3znNBxj+k2j2tpPuJUExt61s KbpP3GF9/crEahpXXRajTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA MCsGA1UdIwQkMCKAIEvLfQX685pz+rh2q5yCA7e0a/a5IGDuJVHRWfp++HThMAoG CCqGSM49BAMCA0gAMEUCIH5H9W3tsCrti6tsN9UfY1eeTKtExf/abXhfqfVeRChk AiEA0GxTPOXVHo0gJpMbHc9B73TL5ZfDhujoDyjb8DToWPQ= -----END CERTIFICATE-----` creator = marshalCreator("TestOrg", []byte(user0Cert)) deployCode = []byte("60c0604052601160808190527f48... b3068c0029") ) BeforeEach(func() { // Set contract creator stub.GetCreatorReturns(creator, nil) }) It("will create and store the runtime bytecode from the deploy bytecode and a user account", func() { // zero address, and deploy code is contract creation stub.GetArgsReturns([][]byte{[]byte(crypto.ZeroAddress.String()), deployCode}) res := evmcc.Invoke(stub) Expect(res.Status).To(Equal(int32(shim.OK))) }) })そして最後の
Expect
の箇所にブレークポイントを設定し、デバッグを走らせてみましょう。
ちゃんとブレークポイント決まりました!(よね?!)これでSolidityのビルドバイナリを貼り付ければダイレクトに実行中のEVM(の外側)がデバッグできる環境ができました。
プロパティ(引数なしメソッド)のテストコード
このスマートコントラクトは
ERC20 Details
を継承していますのでsymbol
などのプロパティがあります。これを取得して
Assert
するテストコードは以下のようになります。evmcc_test.gostub.GetArgsReturns([][]byte{[]byte(contractAddress.String()), []byte("95d89b41"}) res := evmcc.Invoke(stub) Expect(res.Status).To(Equal(int32(shim.OK))) // encoded bytes for "HYP" // It consists of three elements which take byte32 each: // - 0x32 the location of data // - 0x3 the length of array // - 0x728980 left-aligned 'HYP' // Payload is "00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000372898000000000000000000000000000000000000000000000000000000000000" Expect(string(res.Payload[64:67])).To(Equal("HYP"))まず1行目の
95d89b41
はsymbol
のメソッドがある番地です。これはRemixからスマートコントラクトを動かしてみて、symbol
の値を取得するとそのトランザクションログが流れますが、そのinput
の欄からコピーできます。
(というかそれ以外に計算方法などないのだろうか・・・??)またSolidityは文字列の扱いが強烈に大変です。生UTF-8バイナリがbytes32に入っている、という型としてきます。なんだかよくわからないけどそんなもんです。。。
なので上記のテストケースもres.Payload[64:67]
をstring
にする、という方法でHYP
と比較しています。Web3.js では。
Web3.js ではこのHexな文字列と元の文字列との交換は簡単で以下のように行います。
> web3.padRight(web3.fromAscii('HYP'), 34) "0x48595000000000000000000000000000"逆は
> web3.toAscii("0x48595000000000000000000000000000") "HYP "でOKです。ちょっと後半の
0000...
の箇所が空白が入ってしまうのはアレですが・・・メソッドのテストコード
引数付きのメソッドもだいたい似たようなものですが、メソッドの番地の後ろに引数のbyte値をつなげて呼び出す必要があります。これもRemixで叩いてみて、ログが流れますので
input
欄からコピーすれば丸ごと取得できます。実際には以下のようなコードとなります。
evmcc_test.go// 1000 -> 0x00000000000000000000000000000000000000000000000000000000000003e8 stub.GetArgsReturns([][]byte{[]byte(contractAddress.String()), []byte(transfer + hex.EncodeToString(user2Addr.Word256().Bytes()) + "00000000000000000000000000000000000000000000000000000000000003e8")}) res := evmcc.Invoke(stub) Expect(res.Status).To(Equal(int32(shim.OK))) stub.GetArgsReturns([][]byte{[]byte(contractAddress.String()), []byte(balanceOf + hex.EncodeToString(user2Addr.Word256().Bytes()))}) res = evmcc.Invoke(stub) Expect(res.Status).To(Equal(int32(shim.OK))) // 1000 -> 0x00000000000000000000000000000000000000000000000000000000000003e8 Expect(hex.EncodeToString(res.Payload)).To(Equal("00000000000000000000000000000000000000000000000000000000000003e8"))
transfer
はa9059cbb
、balanceOf
は70a08231
が割り当てられており、その後ろに引数となる値(ここではuser2Addr.Word256().Bytes()
や1000
のバイナリ値の文字列など)をくっつけて丸ごと投げています。戻り値が数値の場合も諦めてHexな文字列で比較してしまっています。
まとめ
以下が実際に追加した箇所のテストコードになります。
SolidityのTypeのエンコードや文字列の扱い(生UTF-8のbytes32)などかなり大変ですが、リアルにスマートコントラクトが動くのがわかるので、そしてどんだけ大きくてもガス代取られないしバグっても問題ないので、トライ&エラーするには大変有効であると思います。
以上!
- 投稿日:2019-04-03T21:06:17+09:00
Goでフロントも作れるVugu触ってみたよ
なにこれ
VuguがGo言語でフロントをVueやReactっぽく書ける様にしてくれるらしい。
https://www.vugu.org/
ちょっと触ってみた。Inspired by modern web UI libraries like Vue and React.
Single-file components.
Runs in most modern browsers.
Simple and sane dev and build environment. (Say goodbye to that node_modules folder!)
Write UIs with the ease of HTML+CSS for presentation, and the facility of Go for interface logic. It's pretty cool! See the Getting Started page.Vuguの読み方わからん。。。バグ?の訳無いよね。
Getting Started
Go 1.12以上が必要の様です。
とても簡単な導入チュートリアルです。とりあえず動かしてみるだけなら簡単です。こんな事やります。
- まずプロジェクトフォルダを作ります
- go.modを作ります。
go mod init
でつくれます。- Vuguのコンポーネントファイルを作成。root.vuguというファイルを作成してサンプルコードをコピペ
- 開発用のサーバ作成。これもdevserver.goというファイルを作成してサンプルコードをコピペ
- 開発サーバを立ち上げる
go run devserver.go
- ブラウザから
http://127.0.0.1:8844/
にアクセス- 驚く
簡単ですね。
軽くコード触った感じだとこれはVueですね。ちょこっと改造してみる
上記チュートリアルを行うと、ボタンのオンオフで文字表示のオンオフができる様になります。
これだけだとつまらないのでちょこっと改造します。
ElmのHello World的存在のカウンターアプリを作ってみます。こんな感じの超シンプルなカウンターアプリができます。
上記チュートリアルのroot.vuguを修正します。
<div class="my-first-vugu-comp"> <button @click="data.Toggle()">Test</button> <div vg-if="data.Show">I am here!</div> <br> <!-- カウンター --> <button @click="data.Increment()">+</button> <div><span vg-html='data.Count'></span></div> <button @click="data.Decrement()">-</button> <br> </div> <style> .my-first-vugu-comp { background: #eee; } </style> <script type="application/x-go"> type RootData struct { Show bool Count int } func (data *RootData) Toggle() { data.Show = !data.Show } func (data *RootData) Increment() { data.Count = data.Count + 1 } func (data *RootData) Decrement() { data.Count = data.Count - 1 } </script>単純にRootDataのメソッド
Increment()
とDecrement()
を定義してボタンアクションに応じてRootData構造体のCountの状態を変化させているだけです。ちょっと困った事
現在のCountを表示させる方法がわからん。。。
Documentを漁って、vg-html
を見つけ出して多分これだろ。って感じで試したら表示された。おわりに
新しく出たものですからね。documentはまだ少ないですね。
ひよっこの私にはちょっとまだ私には良さはわからず。。。
おとなしく他の人の情報待ちします。
- 投稿日:2019-04-03T11:02:15+09:00
GoでVueっぽくWebアプリが作れるVugu事始め
ツイートが100RT超えたので、Qiitaにも書いてみます。
Go 1.11がJavaScript APIをすべてサポートしたライブラリを開発し、WebAssemblyに新しい未来が見えました。それまでのWebAssemblyはDOMやネットワーク操作ができないとされてきたので、ループ処理の高速化や数値計算、またはCanvasをゴリゴリ使うゲームくらいしか使い道がないよね…といった評価でした。しかしJavaScript APIが実装されたことで、DOM操作やネットワーク処理が可能になり、WebアプリケーションをそのままGoに置き換えられるんじゃないかという可能性が出てきました。
GoではじめるWebAssebmly その1「Hello World」 | hifive開発者ブログ
とは言え、直接書くとコードがなかなか複雑というか、残念な感じになっていました。例えばネットワークのオンライン、オフラインをイベント通知を受け取る場合のコードは下記のようになります。
navigator := js.Global().Get("navigator") cb1 := js.NewCallback(func(args []js.Value) { if navigator.Get("onLine").Bool() { println("Network is Online"); } else { println("Network is Offline"); } }) window.Call("addEventListener", "online", cb1) window.Call("addEventListener", "offline", cb1)その内、良い感じにラッピングしたフレームワーク(しかも仮想DOMが使えるような)が出るんじゃないかと思っていたのですが、ついにVuguによって実現しそうです。
Vugu: A modern UI library for Go+WebAssembly
ということで、Getting startedに沿った進め方を紹介します。
Go 1.12のインストール
VuguはGo 1.12が必須です。ということでインストールします。goenv を使うと楽ちんです。
$ goenv install 1.12 $ goenv local 1.12go.modの作成
go.mod というファイルを作ります。内容は次の通りです。
module example.org/someone/testapproot.vuguの作成
root.vuguはWeb Component風にUI、Goがまとまったファイルになります。たぶん画面ごとにvuguファイルを作っていくのでしょう。root.vuguの内容は次の通りです。
<div class="my-first-vugu-comp"> <button @click="data.Toggle()">Test</button> <div vg-if="data.Show">I am here!</div> </div> <style> .my-first-vugu-comp { background: #eee; } </style> <script type="application/x-go"> type RootData struct { Show bool } func (data *RootData) Toggle() { data.Show = !data.Show } </script>見て分かりますが、scriptタグがapplication/x-goになっていて、その中はGoを記述します。RootDataを定義しておいて、それがイベント時に送られてくるので、その内容を書き換えるといった具合です。Vueとはちょっと書き方が違いますが、分からないものでもないでしょう。
開発用サーバを作る
ここは単純なGoです。
devserver.go
というファイルで作りますが、名前は何でも良いです。// +build ignore package main import ( "log" "net/http" "os" "github.com/vugu/vugu/simplehttp" ) func main() { wd, _ := os.Getwd() l := "127.0.0.1:8844" log.Printf("Starting HTTP Server at %q", l) h := simplehttp.New(wd, true) // include a CSS file // simplehttp.DefaultStaticData["CSSFiles"] = []string{ "/my/file.css" } log.Fatal(http.ListenAndServe(l, h)) }実行する
では実行します。単に実行するだけでvuguのダウンロードも行ってくれる辺り、Goは素晴らしいですね。
$ go run devserver.goこれで http://localhost:8844 でサーバが立ち上がります。
アクセスする
では実際にアクセスします。アクセスすると最初にローディングが走って、Webの画面が表示されます。このローディングの時にWebAssemblyやGoファイルが生成されます。
Hot reloadはないですが、HTTPサーバは落とさずに再読み込みするだけで表示が更新されます。ネットワークを見ると、ちゃんとWebAssemblyファイルが生成されているのが分かります。これは動的なようで、静的ファイルはありませんでした。
まとめ
guvuはまだリリースしたてで、Experimentalなステージです。しかし、Goで書けるので型付けがあり、柔軟な書き方ができること、さらにWebAssemblyによって高速なWebアプリケーション(後、普通のJavaScriptより難読化が進んでいる)が作れるのがメリットになるでしょう。何よりVueっぽく書けるのが個人的に一押しポイントです。
なお、DOMやネットワーク操作はWebブラウザ側のJavaScriptで実行されます。WebAssemblyでもDOM書き換えが高速化されたり、CORS制限を越えたネットワークアクセスができる訳ではないのでご注意ください。
ぜひVuguを体験してみてください!
- 投稿日:2019-04-03T08:27:19+09:00
ghq的なやつを作った
背景
loves
ghq
ghq
良いですよね。
無思考でGoPath配下の構造に倣ってプロジェクトを管理できるの、最高だと思います。ところで、僕は横着者なので、プロジェクトがPythonで出来ていようがC#だろうがVimScriptだろうが、
ghq
でgetしてたりします。
要するに「何も考えずにプロジェクト管理はghq
に委ねる」というスタンスをとりたいのです。
そして、そのスタンスだとghq
はちょっといくらか不足があり、それをPRとして本家に出そうと考えたときに、内部のちょっとしたメンテナンスしにくさを感じました。forked
ghq
ちょっとこれは根本的に違うもの作ったほうが自身のニーズを満たせそうだ、と思い立ったので、
別のプロジェクトとして gogh を作ってしまいました。
(あんまりそういうスタンスでのForkは良くないと思うんですが)
gogh
の目指すところ
- 目的
- GitHub(+GHE)でホストしているプロジェクトの、ローカルでの配置を管理する
ghq
にならい、Golang風構成(i.e../github.com/kyoh86/gogh
)でClone- 対象ホストごとに設定を切り替える。デフォルトは
github.com
をターゲットとする- プロジェクト間をまたぐような操作を極力サポートする
- ローカルでの操作も、リモートでの操作も
- 逆にプロジェクト内に収まるようなものは
hub
の領域と捉える。サポートしない。プロジェクトがまだない状態での操作
もサポート対象とする
- create
- fork
- etc...?
ghq
との差異
- 設定や一つ一つの機能をシンプルにする
- そのためにもGitHub以外のホストはサポートしない。
- 最大公約数的な機能ではなく、最小公倍数的な機能を作る。
ghq look
は作らない
jump into project
とされてはいるものの、実態は当該ディレクトリをWDとするシェルの起動。- つまり
cd -
は機能しないし、気づくとプロセスツリーがエライことになってる。- 代わりにzsh/bash functionとして似たような機能を提供する。(
gogogh
)- 重複した名前のプロジェクトも分かりやすく表示する
- 重複した名前のプロジェクトが増えてくると、全部長ったらしいパスで表示されたりするのは困る。
--unique
オプションの出力がとても難解なので、もっとシンプルに。-f=short
git config
によらない。
- いろんなツールの設定が
gitconfig
にあふれて管理めんどくさいし分かりづらい。- そして設定値の呼び出しがとても重い。
- 設定ファイル自体を対象ホストごとに分ける
git config
内に設定を持とうとしたこと(と、おそらく歴史的経緯)で、ホストごとに分けられる設定、分けられない設定がややこしい- ホストごとに設定しないと変な挙動を示すこともままある
GitHub
以外の何かは対応しない
- そちらは別の何かで管理するほうが良さそう
- 今の所そもそも向き合ったことがないけど…
hub
との間を埋める
- ghqでできることとhubでできることの間に、いつもちょっと面倒なこと、が発生していたのを解消する
- 新たにforkするとき:元プロジェクトをClone、forkしてプロジェクトを作る
- 新たにプロジェクト作るとき:ローカルにプロジェクトフォルダを作り、GitHub上にもリポジトリを作る。
- (些末な宗教)
github.com/onsi/gomega
とgithub.com/urfave/cli
が好きではない。github.com/stretchr/testify
とgithub.com/alecthomas/kingpin
がいい。- (実験的・ニーズ不明)単なるCLIとして作るのではなく、同時にライブラリとして使える何かを作ってみたい。(github.com/kyoh86/gogh/gogh package)。
hub
リスペクトなのだけど。