質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Solidity

Solidityは、仮想通貨イーサリアム上で実行できるプログラミング言語。スマートコントラクトやDAppsなどの開発・実装に用いられます。コントラクト指向・高水準な言語のため、イーサリアム上で動作するEVM Codeに翻訳することが可能です。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

Q&A

解決済

1回答

1616閲覧

Go言語によるコントラクトコードのイベント監視方法

AK4747471

総合スコア9

Solidity

Solidityは、仮想通貨イーサリアム上で実行できるプログラミング言語。スマートコントラクトやDAppsなどの開発・実装に用いられます。コントラクト指向・高水準な言語のため、イーサリアム上で動作するEVM Codeに翻訳することが可能です。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

1グッド

1クリップ

投稿2019/09/05 03:25

前提・実現したいこと

下記書籍に沿って、スマートコントラクトを実装したDAppsの開発演習をしています。
「試して学ぶ スマートコントラクト開発(マイナビ出版)」

実際にropstenネットワークにコントラクトコードをデプロイし、トランザクションの発行まで確認したのですが、イベントの発火が行われません。イベントが発火するとブラウザ常に新しいトークルームが生成されるというものになっています。

発生している問題・エラーメッセージ

トランザクションとイベントの監視を、Go言語によって行なっています。
エラーメッセージは出ていないのですが、Go言語の無限ループがされていないように見えます。
ソースコードとログを下記に記載いたします。

もしくはtopics["RoomCreated"]が入ってきていないのではないかと思っています。
何かご意見ありましたら参考にさせていただきたく投稿いたしました

solidityによるコントラクトコードです。

solidity

1contract RoomFactory is Destructible, Pausable { 2 3 event RoomCreated( 4 address indexed _creator, 5 address _room, 6 uint256 _depositedValue 7 ); 8 9 function createRoom() external payable whenNotPaused { 10 address newRoom = (new Room).value(msg.value)(msg.sender); 11 emit RoomCreated(msg.sender, newRoom, msg.value); 12 } 13}

Go言語によるイベント監視コードです。

想定では、for文直下のlog.Println("イベント検知中")により、ログに「イベント監視中」が無限に出続けるのではないかと考えています。

go

1func main() { 2 3 log.Println("Starting Event Server!!") 4 db := connectDB() 5 defer db.Close() 6 7 // ③Ethereumネットワークに参加中のノードに接続 8 client, err := ethclient.Dial(os.Getenv("GETH_URL")) 9 // client, err := ethclient.Dial("ws://127.0.0.1:8545") 10 if err != nil { 11 log.Fatalf("err: %v\n", err) 12 } 13 14 // ④Solidityで定義したイベントをハッシュ化する 15 topics := map[string]common.Hash{ 16 "RoomCreated": crypto.Keccak256Hash([]byte("RoomCreated(address,address,uint256)")), 17 } 18 log.Println("solidityで定義したイベントをハッシュ化する", topics) 19 20 // ⑤どのコントラクトのどのTopicを対象にイベントを検知処理するか設定 21 query := ethereum.FilterQuery{ 22 Addresses: []common.Address{common.HexToAddress(os.Getenv("ROOM_FACTORY_ADDRESS"))}, 23 Topics: [][]common.Hash{{ 24 topics["RoomCreated"], 25 }}, 26 } 27 log.Println("どのコントラクトのどのTopicを対象にイベントを検知処理するか設定:", query) 28 29 // ⑥client.SubscribeFilterLogsでコントラクトとの接続を開始 30 event := make(chan types.Log) 31 sub, err := client.SubscribeFilterLogs(context.Background(), query, event) 32 if err != nil { 33 log.Fatal(err) 34 } 35 log.Println("コントラクトとの接続:", event, sub, err) 36 37 roomFactoryAbi, err := abi.JSON(strings.NewReader(string(bindings.RoomFactoryABI))) 38 if err != nil { 39 log.Fatal(err) 40 } 41 log.Println("roomFactoryAbiをオブジェクト化:", roomFactoryAbi, err) 42 43 // ⑦イベント検知のための無限ループ 44 45 for { 46 47 log.Println("イベント検知中") 48 49 // ⑧select文を使ってチャネルの監視を行い、コントラクトとの接続が切断された場合はエラーメッセージを返す 50 select { 51 52 case err := <-sub.Err(): 53 log.Println("イベントエラー") 54 log.Println(err) 55 close(event) 56 57 case vLog := <-event: 58 log.Println("Topicsのエラー") 59 if len(vLog.Topics) == 0 { 60 log.Println("Topicsが存在しません") 61 } 62 63 // ⑩イベントを検知した場合はeventチャンネルを通じてイベントデータを返す。 64 log.Println("イベント検知準備") 65 66 switch vLog.Topics[0] { 67 case topics["RoomCreated"]: 68 var roomCreatedEvent RoomCreatedEvent 69 log.Println("イベントを検知") 70 if err := roomFactoryAbi.Unpack(&roomCreatedEvent, "RoomCreated", vLog.Data); err != nil { 71 log.Printf("Failed unpack: %v\n", err) 72 continue 73 } 74 75 // データベースに新しいデータを登録する処理 76 room := Room{ 77 Address: roomCreatedEvent.Room.Hex(), // デプロイされた新しいルームのコントラクトアドレス 78 CreateTxHash: vLog.TxHash.Hex(), // Transaction Hash 79 OwnerAddress: common.BytesToAddress(vLog.Topics[1].Bytes()).Hex(), // デプロイしたユーザーのアドレス 80 WeiBalance: roomCreatedEvent.DepositedValue.Uint64(), // デプロイ時に指定したDeposit額 81 EventCode: getEventCode(4), // イベントコード 82 OwnerID: 1, // ダミー 83 } 84 85 if err := db.Create(&room).Error; err != nil { 86 log.Printf("Failed create room: %v\n", err) 87 } 88 89 break 90 } 91 } 92 } 93} 94

試したこと

イベント監視コードのログです

ログに「イベント検知中」が一回しか出ていません。
なので、イベント監視のコードが常時監視していないのではないかと思っています。

test_event | 2019/09/05 02:56:37 Starting Event Server!! test_event | 2019/09/05 02:56:37 データベースに接続 test_event | 2019/09/05 02:56:38 solidityで定義したイベントをハッシュ化する map[RoomCreated:[104 73 247 164 9 173 151 211 156 95 250 7 75 247 101 51 11 241 165 116 218 153 212 196 131 17 150 236 215 126 168 218]] test_event | 2019/09/05 02:56:38 どのコントラクトのどのTopicを対象にイベントを検知処理するか設定: {<nil> <nil> <nil> [[125 137 92 95 62 226 4 96 16 225 156 245 254 164 133 206 67 15 12 205]] [[[104 73 247 164 9 173 151 211 156 95 250 7 75 247 101 51 11 241 165 116 218 153 212 196 131 17 150 236 215 126 168 218]]]} test_event | 2019/09/05 02:56:39 コントラクトとの接続: 0xc000075680 &{0xc000414680 0xb37700 {0xa5d340 0xc000075680 18} eth 0x1feed340575875d6fe33bb68948a66c4 0xc0000757a0 {{0 0} 0} 0xc000075740 {{0 0} 0} 0xc0004476e0} <nil> test_event | 2019/09/05 02:56:39 roomFactoryAbiをオブジェクト化: {function () returns() map[createRoom:function createRoom() returns() destroy:function destroy() returns() destroyAndSend:function destroyAndSend(address _recipient) returns() owner:function owner() constant returns(address) pause:function pause() returns() paused:function paused() constant returns(bool) renounceOwnership:function renounceOwnership() returns() transferOwnership:function transferOwnership(address _newOwner) returns() unpause:function unpause() returns()] map[OwnershipRenounced:event OwnershipRenounced(address indexed previousOwner) OwnershipTransferred:event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) Pause:event Pause() RoomCreated:event RoomCreated(address indexed _creator, address _room, uint256 _depositedValue) Unpause:event Unpause()]} <nil> test_event | 2019/09/05 02:56:39 イベント検知中

なにかヒントになることがありましたらご教示頂けますと助かります。

gnx_vw903👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

イベントが届けば

  • イベントを検知
  • イベント検知中

というように表示されるのではないでしょうか。
「イベントが届いてない、エラーも発生していない」から一度表示してイベントの受信待ちになっていると思います。

投稿2019/09/05 06:01

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AK4747471

2019/09/05 06:05

確かに先日、何かの原因でWebSocket通信が切れた時に「イベント検知中」のログが表示されたのを確認してます。(他の仕込んであるログ表示もされました) イベント情報が渡されていない可能性で少し深掘りしてみます。 ご意見出していただきありがとうございます!
AK4747471

2019/09/05 12:52

event := make(chan types.Log) でチャネルを作成しているのはわかったのですが、チャネルにデータを渡す記述がないため、イベントの発火が検知できていないということでしょうか?
AK4747471

2019/09/05 19:03

張り付いた結果、なんとかイベント検知できるようになりました! ``` []common.Address{common.HexToAddress(os.Getenv("ROOM_FACTORY_ADDRESS"))} この文を変更 ↓ []common.Address{common.HexToAddress("コントラクトアドレス")} ``` としたら検知しました! docker-compose.ymlで環境変数を設定していたのですが、それがよくなかったのかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問