# IOTA Sandbox Guide ## Introduction * [IOTA Sandbox Developer Environment](https://blog.iota.org/iota-sandbox-developer-environment-c70c8206fe5f) * Sandbox 為 IOTA Community 釋出的沙盒服務,能夠讓開發者測試 IRI API,sanbox 可由 open source 專案自行建構,也可直接使用 IOTA Community 提供的免費服務。 * 以 IOTA Community 提供的免費服務而言,整個架構雖非 open source,但根據 Dominik Schiener 的說法,sanbox 其實實做上是一個 GPU farm 大量的提供 API 計算服務。 * 而 open source 版的 [sandbox]((https://github.com/iotaledger/sandbox)) 稍有不同,sandbox 為 fullnode 的反向代理,直接 relay IRI 所有的 API request,**除了 `attachToTangle` command** 這是一個特例,文章之後的章節會把重點放在這個 API command 上。 ![](https://i.imgur.com/PtThX0X.png) ## Develop Resource * [iotaledger/sandbox](https://github.com/iotaledger/sandbox) * sandbox token: 7ad7d36f-f833-44fd-b77e-59eea41e213b * [IOTA Python library wrapper example](https://github.com/iotaledger/iota.lib.py/blob/master/examples/routingwrapper_pow.py) ## Usage #### IOTA Community sandbox free service **Example (NodeInfo):** * full example: ``` # coding=utf-8 from __future__ import absolute_import, division, print_function, \ unicode_literals from iota import * from iota.adapter.sandbox import SandboxAdapter # Create the API object. iota =\ Iota( # To use sandbox mode, inject a ``SandboxAdapter``. adapter = SandboxAdapter( # URI of the sandbox node. uri = 'https://sandbox.iota.org/api/v1/', # Access token used to authenticate requests. # Contact the node maintainer to get an access token. auth_token = '7ad7d36f-f833-44fd-b77e-59eea41e213b', ), # Seed used for cryptographic functions. # If null, a random seed will be generated. seed = b'OTJANRBSZNFGBZGEKPQBRZFZTDIXMDBNSXBXWZWOREODAMUNPGFYXBKYRKEJHHXHKVZGUGUSXU9MZ9E9N', ) print(iota.get_node_info()) ``` * output: ``` {u'neighbors': 9, u'packetQueueSize': 0, u'appName': u'IRI', u'jreAvailableProcessors': 4, u'appVersion': u'1.4.1.2', u'transactionsToRequest': 14, u'jreMaxMemory': 3817865216, u'latestSolidSubtangleMilestoneIndex': 295580, u'latestMilestone': TransactionHash('UEBPVPIA9ZUSE9KJZUNGJDKTZJODFQXRKZVY9ZL9WFFJ99HEARZ9VOPCUDINBHSKESQXLILISGIUA9999'), u'time': 1512377263685, u'duration': 0, u'jreTotalMemory': 3239051264, u'jreFreeMemory': 307163392, u'latestSolidSubtangleMilestone': TransactionHash('UEBPVPIA9ZUSE9KJZUNGJDKTZJODFQXRKZVY9ZL9WFFJ99HEARZ9VOPCUDINBHSKESQXLILISGIUA9999'), u'tips': 5065, u'latestMilestoneIndex': 295580} ``` **Example (attachToTangle):** * full example: ``` # coding=utf-8 from __future__ import absolute_import, division, print_function, \ unicode_literals from iota import * from iota.adapter.sandbox import SandboxAdapter DEPTH = 7 MIN_WEIGHT_MAGNITUDE = 14 recipient_address = "ILXW9VMJQVFQVKVE9GUZSODEMIMGOJIJNFAX9PPJHYQPUHZLTWCJZKZKCZYKKJJRAKFCCNJN9EWOW9N9YDGZDDQDDC" # Create the API object. iota =\ Iota( # To use sandbox mode, inject a ``SandboxAdapter``. adapter = SandboxAdapter( # URI of the sandbox node. uri = 'https://sandbox.iota.org/api/v1/', # Access token used to authenticate requests. # Contact the node maintainer to get an access token. auth_token = '7ad7d36f-f833-44fd-b77e-59eea41e213b', ), # Seed used for cryptographic functions. # If null, a random seed will be generated. seed = b'OTJANRBSZNFGBZGEKPQBRZFZTDIXMDBNSXBXWZWOREODAMUNPGFYXBKYRKEJHHXHKVZGUGUSXU9MZ9E9N', ) # print("Hello NodeInfo:") # print(iota.get_node_info()) sender_tag = bytes("TEST") sender_message = "TEST" transfer_value = 0 txn = \ ProposedTransaction( address = Address( recipient_address ), message = TryteString.from_string(sender_message), tag = Tag(sender_tag), value = transfer_value, ) prepared_transferes = [] prepared_transferes.append(txn) txn_id = iota.send_transfer( depth=DEPTH, transfers=prepared_transferes, min_weight_magnitude=MIN_WEIGHT_MAGNITUDE ) print("Hello txn ID:") print (txn_id) ``` * output: ``` iota.adapter.BadApiResponse: 500 response from node: {u'message': u'failed to talk to IRI'} ``` * Reason: ``` Henrik Laxhuber [10:28 PM] @yillkid Some commands are disabled on public nodes for security reasons, including attachToTangle [10:28] The full list: `getNeighbors, removeNeighbors, addNeighbors, attachTotangle, interruptAttachingToTangle` ``` #### Open source sandbox project * Installation: ``` $ sudo apt-get install golang-glide $ sudo apt-get install golang-go $ mkdir $HOME/go $ mkdir $HOME/go/src $ export GOPATH="$HOME/go" $ git clone https://github.com/iotaledger/sandbox.git $ cd sandbox/ $ glide install $ go build -o sandbox-server ./cmd/server ``` * Error: ``` $ go build -o sandbox-server ./cmd/server # _/home/ubuntu/sandbox/cmd/server cmd/server/limiter.go:25: too many arguments in call to tollbooth.NewLimiter have (int64, time.Duration, nil) want (int64, *limiter.ExpirableOptions) cmd/server/limiter.go:28: too many arguments in call to tollbooth.NewLimiter have (int64, time.Duration, nil) want (int64, *limiter.ExpirableOptions) cmd/server/main.go:700: too many arguments in call to tollbooth.NewLimiter have (int64, time.Duration, nil) want (int64, *limiter.ExpirableOptions) ``` * Patch: 原因為 cmd/server/limiter.go 檔案內的相依套件: [tollbooth/limiter](https://github.com/didip/tollbooth/limiter) prototype 有異動,ttl parameter 在 v3.0.0 版中被[移除](https://github.com/didip/tollbooth/commit/49a474e4248186bbc2db5cb28391ed23e7764007#diff-007503cfdd6314e37d40f96773bf2e05)了。 因此修改 glide.yaml 檔案將 tollbooth/limiter 版本指定為 v2.2.0 * Execute: (error) ``` ./sandbox-server {"level":"fatal","ts":1512503265.3413632,"caller":"server/main.go:550","msg":"pubsub topic","error":"rpc error: code = InvalidArgument desc = Invalid resource name given (name=projects//topics/). Refer to https://cloud.google.com/pubsub/overview#names for more information.","name":"","stacktrace":"main.(*App).initPubSub\n\t/home/ubuntu/sandbox/cmd/server/main.go:550\nmain.main\n\t/home/ubuntu/sandbox/cmd/server/main.go:655\nruntime.main\n\t/usr/lib/go-1.8/src/runtime/proc.go:185"} ``` ## 比較 sandbox 與 iotaproxy iotaproxy 詳細的行為可參考[IOTAProxy 筆記](/s/HJ-Xs2itZ),簡單的說,iotaproxy 在技術上可以 relay 所有的 API request 到各個節點,但處理這些 API reuest 的最小單位為節點本身 (IRI),sandbox 在處理大部分的 API reuest 方面與 iotaproxy 相同。但在 `attachToTangle` 命令上,sandbox 選擇直接呼叫 ccurl 來做 POW. 最小的執行單位為 ccurl 命令。 ## Discussion * 我們在 11/23 號晚上與 Lewis 的餐敘中得知,sandbox 能夠以多執行緒的方式執行 POW (attachToTangle) 工作。 * 我大概看了一下 sandbox 的運作方式,整理一些資料如下: * [iotaledger/sandbox](https://github.com/iotaledger/sandbox): * 事實上 sandbox 只是一個非同步 (asynchronous) 的 IRI task manager. * Server 負責做 API task 的列隊管理,將所有的 API request replay 到 fullnode.除了 attachToTangle * 但 attachToTangle command 其實執行方面再單純不過,單純的在 worker 端將 [transaction trytes pass 給 host environment 做執行罷了](https://github.com/iotaledger/sandbox/blob/master/cmd/worker/worker.go#L64)。 * 整合好之後會是 web-backend (python) + sandbox (golang) + ccurl(c) 的結合。 * 我建議把 sandbox 直接用 pyhton celery 實現就好了。 * 我會另外開一篇文探討 ccurl 本身並筆記下來。 * 詳見 [ccurl 筆記](/s/SJ3xPQSZG)