# 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)