.avm
格式的合約Runtime.Log
與 Runtime.Notify
事件監控請按照 安裝 章節的說明進行開始操做。html
此項目的主要功能包含在 cli 應用程序的 np-prompt
命令中。詳情請參見 使用命令行與 NEO 區塊鏈交互node
咱們發佈了一個 Youtube 視頻 幫助你快速上手。在CityOfZion 的 Youtube 頻道下還有其它視頻可供參考。python
須要安裝 libleveldb 庫。安裝 Python 3.6 或 Python 3.7 以避免由於與當前維護者版本不一樣遇到問題。注意不支持 Python 3.5 及更低版本。c++
安裝 neo-python
前須要安裝平臺相關項目。git
Ubuntu 從16.10 開始在官方存儲庫中支持 Python 3.6 。github
首先,請使用如下命令確保 Ubuntu 是最新的:web
sudo apt-get update && sudo apt-get upgrade
複製代碼
你可使用如下命令安裝 Python 3.7 和全部系統依賴:docker
sudo apt-get install python3.7 python3.7-dev python3.7-venv python3-pip libleveldb-dev libssl-dev g++
複製代碼
你也可使用如下命令直接安裝 Python 3.6 和全部系統依賴:macos
sudo apt-get install python3.6 python3.6-dev python3.6-venv python3-pip libleveldb-dev libssl-dev g++
複製代碼
對於較舊的 Ubuntu 版本,你須要使用一個像 Felix Krull 的 deadsnakes PPA 這樣的外部存儲庫 (更多內容,閱讀 here):編程
(本文檔中第三方軟件連接的使用由您自行決定並承擔風險,且您贊成對計算機系統的任何損壞或此類活動致使的數據丟失承擔所有責任。)
apt-get install software-properties-common python-software-properties
add-apt-repository ppa:deadsnakes/ppa
apt-get update
apt-get install python3.6 python3.6-dev python3.6-venv python3-pip libleveldb-dev libssl-dev g++
複製代碼
# Install Python 3.6:
yum install -y centos-release-scl
yum install -y rh-python36
scl enable rh-python36 bash
# Install dependencies:
yum install -y epel-release
yum install -y readline-devel leveldb-devel libffi-devel gcc-c++ redhat-rpm-config gcc python-devel openssl-devel
複製代碼
在 Windows 操做系統上安裝 neo-python
須要進行特別的操做,還可能遇到一些常見問題須要解決,相關內容請查看 Installation (Windows)
brew install leveldb
複製代碼
若是您遇到與此相似的問題:
from ._plyvel import ( # noqa
ImportError: dlopen(neo-python/venv/lib/python3.6/site-packages/plyvel/_plyvel.cpython-35m-darwin.so, 2): Symbol not found: __ZN7leveldb2DB4OpenERKNS_7Options
ERKSsPPS0_
Referenced from: neo-python/venv/lib/python3.6/site-packages/plyvel/_plyvel.cpython-35m-darwin.so
Expected in: flat namespace
複製代碼
解決方案:更新到 plyvel 1.0.4: pip install -r requirements.txt
在 OSX 上安裝 pycrypto 模塊時可能會遇到問題:
src/_fastmath.c:36:11: fatal error: 'gmp.h' file not found
# include <gmp.h>
^~~~~~~
330 warnings and 1 error generated.
error: command 'clang' failed with exit status 1
複製代碼
要解決此問題,可使用 homebrew 安裝 gmp 庫,並使用如下命令行運行pip install:
brew install gmp
CFLAGS='-mmacosx-version-min=10.7 -stdlib=libc++' pip install --no-use-wheel pycrypto --no-cache-dir --global-option=build_ext --global-option="-I/usr/local/Cellar/gmp/6.1.2/include/" --global-option="-L/usr/local/lib"
複製代碼
import scrypt
/ Reason: image not found
若是遇到以下錯誤:
import scrypt
File "/project_dir/venv/lib/python3.6/site-packages/scrypt.py", line 11, in
_scrypt = cdll.LoadLibrary(imp.find_module('_scrypt')[1])
File "/project_dir/venv/lib/python3.6/ctypes/init.py", line 429, in LoadLibrary
return self._dlltype(name)
File "/project_dir/venv/lib/python3.6/ctypes/init.py", line 351, in init
self._handle = _dlopen(self._name, mode)
OSError: dlopen(/project_dir/venv/lib/python3.6/site-packages/_scrypt.cpython-36m-darwin.so, 6): Library not loaded: /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib
Referenced from: /project_dir/venv/lib/python3.6/site-packages/_scrypt.cpython-36m-darwin.so
Reason: image not found
複製代碼
能夠嘗試如下命令:
brew reinstall openssl
複製代碼
在計算機上安裝 neo-python
的最簡單方法下載後使用 pip
從 PyPi 安裝。建議您先建立一個虛擬環境,將此安裝與系統目錄隔離,而後像往常同樣安裝:
# create project dir
mkdir myproject
cd myproject
# create virtual environment and activate
python3.6 -m venv venv # this can also be python3 -m venv venv depending on your environment
source venv/bin/activate
(venv) pip install neo-python
複製代碼
從 github.com/CityOfZion/… clone 存儲庫並導航到項目目錄。建立一個 Python 3 虛擬環境並激活:
git clone https://github.com/CityOfZion/neo-python.git
cd neo-python
# if you want to use the development branch, switch now
git checkout development
# create virtual environment using Python 3.7 and activate or skip to the next step for Python 3.6
python3.7 -m venv venv
source venv/bin/activate
# create virtual environment using Python 3.6 and activate
python3.6 -m venv venv
source venv/bin/activate
# install the package in an editable form
(venv) pip install -e .
複製代碼
若是要使用 git pull
更新 neo-python ,還須要使用 pip install -r requirements.txt
更新依賴。
第一次使用 neo-python 時須要同步區塊鏈。這將花費較長時間。此項目包含的 bootstrap.py
能夠自動下載一個鏈目錄。
要同步測試網,運行 np-bootstrap
。
要同步主網,運行 np-bootstrap -m
並等待同步完成 (3.3 GB 文件)。
如下安裝說明針對帶有 MSYS2 環境和 Visual Studio 2017 的 Windows 7 x64 系統,也適用於大多數 Windows 發行版。你也能夠選擇使用 Ubuntu 安裝一個 Linux 子系統( 更多信息參見 這裏)。
從 Microsoft Store 安裝的 Ubuntu 是 Ubuntu 16.04。你須要從這裏下載 Ubuntu 18.04:www.microsoft.com/en-us/p/ubu…
在 Windows 系統中安裝 leveldb 最簡單的辦法是使用 VC++ 打包工具。若是你使用的是 windows x64 系統,還須要先設置環境變量:set VCPKG_DEFAULT_TRIPLET=x64-windows
。
git clone https://github.com/Microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install
.\vcpkg install leveldb
複製代碼
安裝 Anaconda package manager,並激活 python 虛擬環境。
conda create -n neo python=3.6.4
activate neo
複製代碼
(可選)激活 Visual Studio 構建環境,以下所示:
"e:\Program Files\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
複製代碼
確認編譯器能夠訪問 .lib 和 leveldb 頭文件,而後將它們複製到 MSVC 構建工具目錄下:
從 vcpkg\installed\x64-windows\include\
複製到 e:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include
從 vcpkg\installed\x64-windows\lib\libleveldb.lib
複製到 e:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\lib\x64\leveldb.lib
而後克隆存儲庫並進入所需版本,安裝 cython,從 C++ 文件構建 python 擴展,最後安裝 plyvel,以下所示:
git clone https://github.com/wbolster/plyvel
cd plyvel
git checkout e3887a5fae5d7b8414eac4c185c1e3b0cebbdba8
pip install cython
cython --cplus --fast-fail --annotate plyvel/_plyvel.pyx
python setup.py build_ext --inplace --force
python setup.py install
複製代碼
git clone https://github.com/coleifer/peewee
cd peewee
git checkout 761f9144a0e17381147a81658019cffe14c118ca
python setup.py install
複製代碼
git clone https://github.com/hajimes/mmh3
cd mmh3
git checkout a73b373858dedfdb6d362f5ca985ae1bb6bc2161
python setup.py install
複製代碼
某些依賴項沒法正確地從 pip 安裝,但能夠從 Anaconda 安裝。
conda install twisted==17.9.0
conda install pycrypto==2.6.1
複製代碼
導航到 neo-python 目錄並安裝其它依賴項,使用如下命令:
pip install -r requirements.txt
複製代碼
檢查安裝: python prompt.py
如下列出了在安裝過程當中可能遇到的問題和解決方案。
確保編譯器能夠訪問 .lib 與 leveldb 頭文件。
找到庫 shlwapi.lib,它可能在你的文件系統中。 將其合併到 leveldb.lib:lib.exe /OUT:newleveldb.lib leveldb.lib ShLwApi.Lib
並替換原始文件。
導航到你的 python 發行版包目錄,例如: e:\Programs\Anaconda3\envs\neo\Lib\site-packages
。
在 Crypto\Random\OSRNG\nt.py 中將 import winrandom
修改成 from . import winrandom
。
安裝模塊: pip install pypiwin32
SeedList 是一個 URL 列表,是 NEO-Python 在啓動時嘗試鏈接的節點。在 NEO-Python 目錄下 (/neo/data
) 的 protcol.*.json
文件中能夠找到 SeedList。有三個經常使用 protocol.*.json
文件:
protocol.mainnet.json
protocol.testnet.json
protocol.privnet.json
複製代碼
本文指的是 protocol.mainnet.json
,但這些信息是通用的。
json
{
"ProtocolConfiguration": {
"Magic": ...,
"AddressVersion": ...,
"SecondsPerBlock": ...,
"StandbyValidators": [
...
],
"SeedList": [
"seed1.neo.org:10333",
"seed2.neo.org:10333",
"seed3.neo.org:10333",
"seed4.neo.org:10333",
"seed5.neo.org:10333"
],
"RPCList":[
...
],
"SystemFee": {
...
}
}
}複製代碼
在上面的文件中,NEO-Python 配置爲經過PORT:10333
鏈接 seed1.neo.org
, seed2.neo.org
等節點 。
假如以上列表中的每一個節點故障,NEO-Python 會嘗試鏈接相鄰節點。可是這種方法存在不少未知因素,例如相鄰節點出問題了,可能致使等待時間至關漫長。
經過使用咱們肯定的活躍節點更新 SeedList,能夠避免上述潛在問題中提到的漫長等待風險。
若是是在 Ubuntu 上運行 neo-python ,你應該使用了 venv。你須要修改 venv 目錄裏 lib/python3.6/site-packages/neo/data
路徑下的 protocol.mainnet.json 文件。若是該路徑不存在,說明你還沒有在當前 venv 中使用該文件,那麼你能夠到 neo/data 路徑下的 neo-python 文件夾中修改此文件。或者你也能夠刪除 venv 文件夾,修改父文件,新建一個 venv 文件夾(python -m venv venv
)並激活 venv,而後使用 pip install e .
從新安裝。
要尋找活躍節點,使用 NEO 網絡狀態監測網。要查看更詳細的信息,查看該監測網 Github 上的 存儲庫。
如上圖所示,列表中顯示了可用節點。最新節點顯示在最上方。 圖中
yes
的節點爲活躍節點。
咱們會根據如下端口的標準協議進行選擇,好比咱們會選擇上圖中的節點 1 而不選節點3,由於節點 1符合標準而節點 3 不符合。
Main Net | Test Net | |
---|---|---|
JSON-RPC via HTTPS | 10331 | 20331 |
JSON-RPC via HTTP | 10332 | 20332 |
P2P via TCP | 10333 | 20333 |
P2P via WebSocket | 10334 | 20334 |
如下是選出的活躍節點地址:
seed3.aphelion-neo.com
seed4.aphelion-neo.com
node2.ams2.bridgeprotocol.io
pyrpc1.nodeneo.ch
node2.nyc3.bridgeprotocol.io
複製代碼
爲了告知 NEO-Python 新的節點列表,須要將前面幾個地址粘貼到 protocol.mainnet.json
,以下所示:
json
{
"ProtocolConfiguration": {
"Magic": ...,
"AddressVersion": ...,
"SecondsPerBlock": ...,
"StandbyValidators": [
...
],
"SeedList": [
"seed1.neo.org:10333",
"seed2.neo.org:10333",
"seed3.neo.org:10333",
"seed4.neo.org:10333",
"seed5.neo.org:10333",
"seed4.aphelion-neo.com:10333",
"node2.sgp1.bridgeprotocol.io:10333",
"seed2.aphelion-neo.com:10333",
"seed3.aphelion-neo.com:10333",
"node2.ams2.bridgeprotocol.io:10333",
"pyrpc1.narrative.network:10333",
"node2.nyc3.bridgeprotocol.io:10333",
"pyrpc4.narrative.network:10333",
"pyrpc2.narrative.network:10333",
"pyrpc3.narrative.network:10333",
"seed1.aphelion-neo.com:10333",
"seed1.switcheo.network:10333",
"seed2.switcheo.network:10333",
"seed5.cityofzion.io:10333",
"seed3.cityofzion.io:10333",
"seed3.switcheo.network:10333",
"seed1.o3node.org:10333",
"seed3.travala.com:10333",
"seed4.cityofzion.io:10333",
"seed2.cityofzion.io:10333",
"seed2.o3node.org:10333",
"seed3.o3node.org:10333",
"node1.sgp1.bridgeprotocol.io:10333",
"seed2.travala.com:10333",
"seed4.switcheo.network:10333",
"seed1.spotcoin.com:10333",
"node1.nyc3.bridgeprotocol.io:10333"
],
"RPCList":[
...
],
"SystemFee": {
...
}
}
}
複製代碼
請注意,上例中的每一個地址後加上了 :10333
以便告知 NEO-Python 使用 P2P 協議鏈接。
如今就能夠像往常同樣啓動 neo-python 了。
建議你在啓動任意 API 服務器以前先更新節點列表以保證最大鏈接數。有關更多API服務器信息,請查看 這裏。
使用 neo-python 主要有兩種方式:運行 np-prompt
和運行自定義代碼的節點。
在測試網運行 np-prompt
:
$ np-prompt
複製代碼
顯示 help 的全部可用參數:
$ np-prompt -h
usage: np-prompt [-h] [-m | -p [host] | --coznet | -c CONFIG]
[-t {dark,light}] [-v] [--datadir DATADIR] [--version]
optional arguments:
-h, --help show this help message and exit
-m, --mainnet Use MainNet instead of the default TestNet
-p [host], --privnet [host]
Use a private net instead of the default TestNet,
optionally using a custom host (default: 127.0.0.1)
--coznet Use the CoZ network instead of the default TestNet
-c CONFIG, --config CONFIG
Use a specific config file
-t {dark,light}, --set-default-theme {dark,light}
Set the default theme to be loaded from the config
file. Default: 'dark'
-v, --verbose Show smart-contract events by default
--datadir DATADIR Absolute path to use for database directories
--version show program's version number and exit 複製代碼
查看 /examples
目錄下的示例:github.com/CityOfZion/…
另外可參考 「Settings and Logging」 and 「Interacting with Smart Contracts」.
在主網啓動 JSON 和 REST API 服務器:
$ np-api-server --mainnet --port-rpc 10332 --port-rest 80
複製代碼
示例通知和 help 下的全部可用參數:
$ np-api-server --testnet --port-rpc 8080 --port-rest 8088
[I 180315 09:27:09 NotificationDB:44] Created Notification DB At /Users/thomassaunders/.neopython/Chains/Test_Notif
[I 180315 09:27:09 threading:864] [TestNet] Block 5644 / 53999
[I 180315 09:27:09 np-api-server:11] Starting json-rpc api server on http://0.0.0.0:8080
[I 180315 09:27:09 _observer:131] Site starting on 8080
[I 180315 09:27:09 _observer:131] Starting factory <twisted.web.server.Site object at 0x110619828>
[I 180315 09:27:09 np-api-server:11] Starting REST api server on http://0.0.0.0:8088
# view help
$ np-api-server -h
usage: np-api-server [-h]
(--mainnet | --testnet | --privnet | --coznet | --config CONFIG)
[--port-rpc PORT_RPC] [--port-rest PORT_REST]
[--logfile LOGFILE] [--syslog] [--syslog-local [0-7]]
[--disable-stderr] [--datadir DATADIR]
[--maxpeers MAXPEERS] [--wallet WALLET] [--host HOST]
optional arguments:
-h, --help show this help message and exit
--datadir DATADIR Absolute path to use for database directories
--maxpeers MAXPEERS Max peers to use for P2P Joining
--wallet WALLET Open wallet. Will allow you to use methods that
require an open wallet
--host HOST Hostname ( for example 127.0.0.1)
Network options:
--mainnet Use MainNet
--testnet Use TestNet
--privnet Use PrivNet
--coznet Use CozNet
--config CONFIG Use a specific config file
Mode(s):
--port-rpc PORT_RPC port to use for the json-rpc api (eg. 10332)
--port-rest PORT_REST port to use for the rest api (eg. 80)
Logging options:
--logfile LOGFILE Logfile
--syslog Log to syslog instead of to log file ('user' is the
default facility)
--syslog-local [0-7] Log to a local syslog facility instead of 'user'.
Value must be between 0 and 7 (e.g. 0 for 'local0').
--disable-stderr Disable stderr logger
複製代碼
要使外部程序能訪問你的 API 服務器,須要打開防火牆端口。下表顯示的端口能夠設置爲所有打開或按需打開。
Main Net | Test Net | |
---|---|---|
JSON-RPC via HTTPS | 10331 | 20331 |
JSON-RPC via HTTP | 10332 | 20332 |
若是在 Windows WSL (Ubuntu) 上運行 neo-python, 除了打開路由器上的相應端口,還須要參考 這裏 爲你的 Windows 防火牆添加一個入站策略。
Prompt 是用於運行和與 NEO 區塊鏈交互的默認界面。
以下所示:
$ np-prompt
NEO cli. Type 'help' to get started
neo>
複製代碼
下表列出了全部可用的錢包命令。
命令 | 描述 |
---|---|
create wallet <wallet_path> |
建立錢包文件 |
open wallet <wallet_path> |
打開錢包文件 |
wallet |
檢查錢包 |
wallet <verbose> < rebuild> <rebuild block_height> |
重建錢包索引 |
wallet migrated |
遷移你的錢包 |
export wif <address> |
導出私鑰 |
export nep2 <address> |
將地址導出爲NEP2加密私鑰 |
import wif <WIF> |
導入私鑰 |
import nep2 <address> |
將地址導入爲NEP2加密私鑰 |
import watch_addr <address> |
導入 watch only 地址 |
import contract_addr <script_hash> <pubkey> |
導入智能合約地址 |
send <asset_ID> <address> <amount> [from_address] |
將資產發送到指定的地址 |
wallet delete_addr <address> |
刪除地址 |
neo> create wallet path/to/walletfile
[Password 1]> **********
[Password 2]> **********
Wallet {
"addresses": [
"AayaivCAcYnM8q79JCrfpRGXrCEHJRN5bV"
],
"claims": {
"available": 0.0,
"unavailable": 0.0
},
"tokens": [],
"height": 0,
"synced_balances": [],
"path": "Wallets/blahblah.db3",
"public_keys": [
{
"Address": "AayaivCAcYnM8q79JCrfpRGXrCEHJRN5bV",
"Public Key": "027973267230b7cba0724589653e667ddea7aa8479c01a82bf8dd398cec93508ef"
}
],
"percent_synced": 0
}
neo>
複製代碼
neo> open wallet path/to/walletfile
[Password]> ***********
Opened wallet at path/to/walletfile
neo>
複製代碼
neo> wallet
Wallet {
"addresses": [
"AayaivCAcYnM8q79JCrfpRGXrCEHJRN5bV"
],
"claims": {
"available": 0.0,
"unavailable": 0.0
},
"tokens": [],
"height": 75500,
"synced_balances": [],
"path": "Wallets/blahblah.db3",
"public_keys": [
{
"Address": "AayaivCAcYnM8q79JCrfpRGXrCEHJRN5bV",
"Public Key": "027973267230b7cba0724589653e667ddea7aa8479c01a82bf8dd398cec93508ef"
}
],
"percent_synced": 9
}
複製代碼
若是您的錢包出現異常,或者您已將新地址導入錢包,則可能須要重建錢包索引,從區塊頭同步錢包。也能夠指定一個區塊號開始從新同步,以下所示:
neo> wallet rebuild 700000
restarting at 700000
neo>
複製代碼
若是錢包數據模型發生更改,則可能須要遷移錢包,以下所示:
neo> wallet migrated
migrated wallet
neo>
複製代碼
若是你打開錢包時收到以下信息,則必須從新加密以防止以前的錢包漏洞。
Could not open wallet: This wallet is currently vulnerable. Please execute the "reencrypt_wallet.py" script on this wallet before continuing
複製代碼
要修復此問題,先使用命令 exit
退出 neo prompt,而後運行從新加密腳本:
python reencrypt_wallet.py path/to/mywallet.db3
複製代碼
你須要輸入密碼並使用新名稱path/to/new_mywallet.db3
保存從新加密的錢包。
您可能須要導入一個WIF私鑰來添加地址到您的錢包,以下所示:
neo> import wif KxP97gujib35PBEnTq78e5NmYVbeaosU4AdguDzZ4tyf6a7W32UM
Imported key KxP97gujib35PBEnTq78e5NmYVbeaosU4AdguDzZ4tyf6a7W32UM
Pubkey: 303263383231666338336465373331313039633435653034346136353863386631313337623730303461396232323237613335653262353566613061313630323731
neo>
複製代碼
您可能須要從錢包導出 WIF 私鑰用於另外一個程序。指定要導出的 WIF
地址,以下所示:
neo> export wif AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK
[Wallet Password]> ***********
WIF key export: KxP97gujib35PBEnTq78e5NmYVbeaosU4AdguDzZ4tyf6a7W32UM
neo>
複製代碼
您能夠將地址導出爲 NEP2 加密私鑰,以下所示:
neo> export nep2 AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt
[Wallet Password]> ***********
[Key Password 1]> ******************
[Key Password 2]> ******************
NEP2 key export: 6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL
neo>
複製代碼
您能夠將地址導入爲 NEP2 加密私鑰,以下所示:
neo> import nep2 6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL
[Key Password]> ******************
Imported nep2 key: 6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL
Pubkey: 303236323431653765323662333862623731353462386164343934353862393766623163343739373434336463393231633563613537373466353131613262626663
複製代碼
watch only 是一種您沒有公鑰但想觀察的地址。watch only 地址能夠像普通地址同樣刪除。
neo> import watch_addr AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt
neo>
複製代碼
您可能想要使用已部署的智能合約中的資金。根據合約編程,若是其容許您像使用本身的資金同樣使用合約中的資金,則您能夠經過指定合約的script_hash,以及您但願與合約關聯的錢包中地址的公鑰來導入合約地址。合約地址能夠像錢包中的普通地址同樣刪除。
# import contract_addr {script_hash} {pubkey}
neo> import contract_addr 3c62006802d895974069a1d96398a04b4703f0f8 027973267230b7cba0724589653e667ddea7aa8479c01a82bf8dd398cec93508ef
Added contract addres AeU8kTJxynwkT3q9ao8aDFuaRJBkU3AfFG to wallet
neo>
複製代碼
neo> wallet delete_addr AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt
Deleted address AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt
neo>
複製代碼
使用如下命令能夠從你的錢包發送資產。使用此命令,發送的資產來自於你的某個地址或者多個地址。 change_address
是你錢包的中的某個地址。
# syntax send {asset_name} {address to} {amount} ( optional: --from-addr={from_addr})
neo> send gas AeU8kTJxynwkT3q9ao8aDFuaRJBkU3AfFG 11
[Password]> ***********
Relayed Tx: 468e294b11a9f65cc5e2c372124877472eebf121befb77ceed23a84862a606d3
neo>
複製代碼
也能夠指定一個特定的地址來發送資產,如從合約地址發送資產。
# syntax send {asset_name} {address to} {amount} ( optional: --from-addr={from_addr})
neo> send gas AeU8kTJxynwkT3q9ao8aDFuaRJBkU3AfFG 11 --from-addr=AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK
[Password]> ***********
Relayed Tx: a43dfb30af63bd0e5a510b05f02b3d40932af26d4564e040e3812ce78e76ce71
neo>
複製代碼
您可使用錢包觀察 NEP5
代幣並與之交互,爲此,您須要首先註冊錢包以觀察代幣,以下所示:
neo> import token f8d448b227991cf07cb96a6f9c0322437f1599b9
added token {
"name": "NEP5 Standard",
"script_hash": "f8d448b227991cf07cb96a6f9c0322437f1599b9",
"decimals": 8,
"symbol": "NEP5",
"contract address": "AYhE3Svuqdfh1RtzvE8hUhNR7HSpaSDFQg"
}
neo> wallet
Wallet {
# truncated ...
"percent_synced": 100,
"addresses": [
"AayaivCAcYnM8q79JCrfpRGXrCEHJRN5bV",
{
"balances": {
"c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b": "4051.0",
"602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7": "897.48372409"
},
"script_hash": "AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK",
"votes": [],
"version": 0,
"is_watch_only": false,
"tokens": [
"[f8d448b227991cf07cb96a6f9c0322437f1599b9] NEP5 : 4519175.65580000"
],
"frozen": false
},
{
}
}
複製代碼
查看在 prompt 中與智能合約交互的完整說明: Smart Contracts within the Prompt
本節介紹如何經過 NEO 官方申請表 獲取測試網資產。
獲取測試網資產須要兩步:
你須要準備好如下信息:
wallet
獲取所需信息。neo> wallet
Wallet {
...
"public_keys": [
{
"Address": "ANFLgwKG8Eni9gJmKfM7yFXEaWwoGkSUid",
"Public Key": "037b8992e8384212f82e05c8836816c0f14dff9528397138731638b17d6357021e" <--- take this
}
],
...
}
複製代碼
而後使用以下命令建立多方簽名地址:
neo> import multisig_addr
please specify multisig contract like such: 'import multisig {pubkey in wallet} {minimum # of signatures required} {signing pubkey 1} {signing pubkey 2}...'
neo> import multisig_addr 037b8992e8384212f82e05c8836816c0f14dff9528397138731638b17d6357021e 1 037b8992e8384212f82e05c8836816c0f14dff9528397138731638b17d6357021e 02883118351f8f47107c83ab634dc7e4
ffe29d274e7d3dcf70159c8935ff769beb
[I 180310 16:49:19 UserWallet:191] contract does not exist yet
Added multi-sig contract address ALXEKioZntX73QawcnfcHUDvTVm8qXjAxf to wallet
複製代碼
再次檢查你的錢包,應該能查看到餘額(特別是查看 synced_balances )。若是沒有看到新增餘額,請運行wallet rebuild
並等待它徹底同步後再次嘗試。
neo> wallet
Wallet {
"path": "test",
"addresses": [
{
"address": "ANFLgwKG8Eni9gJmKfM7yFXEaWwoGkSUid",
"script_hash": "47028f2a3d33466f29fba10e65c90fd8f3d01e1f",
"tokens": null
},
{
"version": 0,
"script_hash": "ALXEKioZntX73QawcnfcHUDvTVm8qXjAxf",
"frozen": false,
"votes": [],
"balances": {
"0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b": "50.0",
"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7": "50.0"
},
"is_watch_only": false
}
],
...
"synced_balances": [
"[NEO]: 50.0 ",
"[NEOGas]: 50.0 "
],
"public_keys": [
{
"Address": "ANFLgwKG8Eni9gJmKfM7yFXEaWwoGkSUid",
"Public Key": "037b8992e8384212f82e05c8836816c0f14dff9528397138731638b17d6357021e"
},
{
"Address": "ALXEKioZntX73QawcnfcHUDvTVm8qXjAxf",
"Public Key": "037b8992e8384212f82e05c8836816c0f14dff9528397138731638b17d6357021e"
}
],
...
}
複製代碼
如今就能夠安裝如下操做將資產轉移到你本身的地址:
neo> send NEO ANFLgwKG8Eni9gJmKfM7yFXEaWwoGkSUid 5 --from-addr=ALXEKioZntX73QawcnfcHUDvTVm8qXjAxf
[Password]> **********
[I 180310 17:02:42 Transaction:611] Verifying transaction: b'c32b0e3d9adbef6720abfad5106dcd2dacb17b31d4f9d32cbcf8ed6e7f566ef3'
Relayed Tx: c32b0e3d9adbef6720abfad5106dcd2dacb17b31d4f9d32cbcf8ed6e7f566ef3
複製代碼
注意參數 --from-addr
指定的是提取資產的多方簽名合約地址。
neo-python提供一個設置模塊,能夠用來配置如下事情:
日誌:
要更改設置,導入設置示例:
from neo.Settings import settings
複製代碼
您可使用如下設置方法配置網絡:
settings.setup_mainnet()
settings.setup_testnet()
settings.setup_privnet()
settings.setup(config_file)
複製代碼
neo-python
默認使用測試網。
默認狀況下, neo-python
將鏈數據保存在 ~/.neopython/Chains
。若是想指定 Chains
目錄放置的路徑,能夠將 --datadir
標誌傳遞給如下任意命令:np-prompt
, np-api-server
, 或 np-bootstrap
。也可使用 settings
模塊手動設置:
settings.set_data_dir('your/path')
複製代碼
neo-python 使用如下默認方式:
要禁用全部智能合約事件的記錄,參照如下示例:
settings.set_log_smart_contract_events(False)
複製代碼
要更改日誌級別,如也顯示DEBUG日誌或只顯示錯誤日誌,參照如下示例:
import logging
# Show everything, including debug logs:
settings.set_loglevel(logging.DEBUG)
# Only show errors:
settings.set_loglevel(logging.ERROR)
複製代碼
要在 prompt
中更改 log 級別,使用如下命令:
neo> config sc-events on
neo> config sc-events off
複製代碼
要啓動日誌文件的記錄功能,參照如下示例:
# Just a single logfile, with no limits or rotation:
settings.set_logfile(your_logfile_path)
# To enable rotation with a maximum of 10MB per file and 3 rotations:
settings.set_logfile(your_logfile_path, 1e7, 3)
複製代碼
neo-python 使用 logzero 進行記錄。要在現有的 neo 日誌記錄配置中使用 logger,只需從logzero 導入 logger,以下所示:
from logzero import logger
# These log messages are sent to the console
logger.debug("hello")
logger.info("info")
logger.warn("warn")
logger.error("error")
# This is how you'd log an exception
try:
raise Exception("this is a demo exception")
except Exception as e:
logger.exception(e)複製代碼
本文將詳細介紹 neo.Core.TX.Transaction
模塊。
描述:
交易基本類
用法:
從 neo.Core.Transaction 導入交易
class neo.Core.TX.Transaction.ContractTransaction(*args, **kwargs)
[source]
class neo.Core.TX.Transaction.Transaction(inputs=[], outputs=[], attributes=[], scripts=[])
[source]
Deserialize(reader)
[source]
反序列化完整的對象。
參數:reader (
) –
static DeserializeFrom(reader)
[source]
反序列化完整的對象。
參數: reader (
) –
返回值:
返回類型:Transaction
static DeserializeFromBufer (buffer, offset=0)
[source]
從指定的緩衝區反序列化對象實例。
參數:
buffer (
) – (可選)用於建立數據流的數據。
offset – 不使用
返回值:
返回類型:Transaction
DeserializeUnsigned(reader)
[source]
反序列化對象。
參數:reader (
) –
拋出: Exception
– 若是交易類型錯誤。
DeserializeUnsignedWithoutType
(
) [source]
不讀取交易類型數據的反序列化對象。
參數:reader (
) –
GetHashData
() [source]
獲取用於散列的數據。
返回值:
返回類型:bytes
GetMessage
() [source]
獲取用於散列的數據。
返回值:
返回類型:bytes
GetScriptHashesForVerifying
() [source]
獲取用於驗證交易的腳本散列。
拋出:Exception
– 若是交易中沒有有效資產。
返回值:UInt160 類型腳本散列。
返回類型:list
GetTransactionResults
() [source]
獲取交易的執行結果。
返回值:若是交易沒有引用 list: TransactionResult 對象。
返回類型:無
Hash
獲取交易的散列值。
返回值:
返回類型:UInt256
NetworkFee
() [source]
獲取網絡手續費
返回值:
返回類型:Fixed8
References
獲取全部引用
返回值:Key (UInt256): input PrevHash Value (TransactionOutput): object.
返回類型:dict
ResetHashData
() [source]
復位本地保存的散列數據
ResetReferences
() [source]
復位本地保存的引用
Scripts
獲取腳本
返回值:
返回類型:list
Serialize
(
) [source]
序列化對象
參數:writer (
) –
SerializeUnsigned
(
) [source]
序列化對象
參數:writer (
) –
Size
() [source]
獲取對象的總大小(以字節爲單位)。
返回值:大小
返回類型:int
SystemFee
() [source]
獲取系統手續費。
返回值:目前爲 0。
返回類型:Fixed8
ToArray
() [source]
獲取 self 的字節數據。
返回值:
返回類型:byte
ToJson
() [source]
將對象成員轉換爲能夠解析爲JSON的字典編碼。
返回值:
返回類型:dict
Verify
(
) [source]
驗證交易。
參數:mempool –
返回值:驗證經過返回 True,不然返回 False。
返回類型:bool
getAllInputs
() [source]
獲取輸入
返回值:
返回類型:list
withdraw_hold
交易的 docstring
class neo.Core.TX.Transaction.TransactionInput(prevHash=None, prevIndex=None)
[source]
TransactionInput 的 docstring
Deserialize
(
) [source]
反序列化全對象
參數:reader (
) –
Serialize
(
) [source]
序列化對象
參數:writer (
) –
ToJson
() [source]
將對象成員轉換爲能夠解析爲JSON的字典編碼。
返回值:
返回類型:dict
ToString
() [source]
獲取對象的字符串表示形式。
返回:PrevHash:PrevIndexReturn type:str
class neo.Core.TX.Transaction.TransactionOutput (AssetId=None, Value=None, script_hash=None)
[source]
Address
獲取交易的公共地址。
返回值:表明地址的 base58 編碼字符串。
返回類型:str
AddressBytes
獲取交易的公共地址。
返回值:base58 編碼的字符串。
返回類型:bytes
AssetId
docstring for TransactionOutput
Deserialize
(
) [source]
反序列化完整對象
參數:reader (
) –
Serialize
(
) [source]
序列化對象
參數:writer (
) –
ToJson
(
) [source]
將對象成員轉換爲能夠解析爲JSON的字典編碼。 :param index: 交易輸出的索引 :type index: int
返回值:
返回類型:dict
neo-python 的一個常見用例是與智能合約進行交互。典型的智能合約事件包括 Runtime.Notify
, Runtime.Log
, 執行成功或失敗,以及 Storage.GET/PUT/DELETE
。
如下列出了當前 NEO-Python 能夠處理的智能合約事件類型:
RUNTIME_NOTIFY = "SmartContract.Runtime.Notify"
RUNTIME_LOG = "SmartContract.Runtime.Log"
EXECUTION = "SmartContract.Execution.*"
EXECUTION_INVOKE = "SmartContract.Execution.Invoke"
EXECUTION_SUCCESS = "SmartContract.Execution.Success"
EXECUTION_FAIL = "SmartContract.Execution.Fail"
VERIFICATION = "SmartContract.Verification.*"
VERIFICATION_SUCCESS = "SmartContract.Verification.Success"
VERIFICATION_FAIL = "SmartContract.Verification.Fail"
STORAGE = "SmartContract.Storage.*"
STORAGE_GET = "SmartContract.Storage.Get"
STORAGE_PUT = "SmartContract.Storage.Put"
STORAGE_DELETE = "SmartContract.Storage.Delete"
CONTRACT = "SmartContract.Contract.*"
CONTRACT_CREATED = "SmartContract.Contract.Create"
CONTRACT_MIGRATED = "SmartContract.Contract.Migrate"
CONTRACT_DESTROY = "SmartContract.Contract.Destroy"
複製代碼
當這些事件發生在接收區塊時,由neo.EventHub
調度一個 SmartContractEvent
實例。
事件處理程序老是收到參數 neo.EventHub.SmartContractEvent 的一個實例,其包含有關當前事件的全部信息。SmartContractEvent 具備如下屬性:
屬性 | 數據類型 | 描述 |
---|---|---|
event_type |
str | neo.EventHub.SmartContractEvent 中的一個事件類型 |
contract_hash |
UInt160 | 合約散列值 |
tx_hash |
UInt256 | 交易散列值 |
block_number |
int | 收到此事件的區塊號 |
event_payload |
object[] | 對象列表,取決於智能合約發出的數據類型(例如,使用Runtime.Notify)。 |
execution_success |
bool | 方法調用是否成功 |
test_mode |
bool | 這個事件是否由本地TestInvoke調度,而不是從區塊連接收 |
開發人員可使用neo.contrib.smartcontract.SmartContract
輕鬆訂閱這些事件。如下是一個使用散列6537b4bd100e514119e3a7ab49d520d20ef2c2a4
監聽 Runtime.Notify
智能合約事件的示例:
from neo.contrib.smartcontract import SmartContract
smart_contract = SmartContract("6537b4bd100e514119e3a7ab49d520d20ef2c2a4")
@smart_contract.on_notify
def sc_notify(event):
print("SmartContract Runtime.Notify event:", event)
# Make sure that the event payload list has at least one element.
if not len(event.event_payload):
return
# The event payload list has at least one element. As developer of the smart contract
# you should know what data-type is in the bytes, and how to decode it. In this example,
# it's just a string, so we decode it with utf-8:
print("- payload part 1:", event.event_payload[0].decode("utf-8"))
複製代碼
目前可用的裝飾器以下:
裝飾器 | 智能合約事件 |
---|---|
@on_any |
全部事件 |
@on_notify |
Runtime.Notify |
@on_log |
Runtime.Log |
@on_storage |
存儲 PUT, GET 和 DELETE |
@on_execution |
方法調用,成功或失敗 |
如下示例顯示如何監聽全部事件並區分代碼中的事件類型:
from neo.contrib.smartcontract import SmartContract
from neo.EventHub import SmartContractEvent
smart_contract = SmartContract("6537b4bd100e514119e3a7ab49d520d20ef2c2a4")
@smart_contract.on_all
def handle_sc_event(event):
print("SmartContract Runtime.Notify event:", event)
# Check if it is a Runtime.Notify event
if event.event_type == SmartContractEvent.RUNTIME_NOTIFY:
# Exit if an empty payload list
if not len(event.event_payload):
return
# Decode the first payload item and print it
print("- payload part 1:", event.event_payload[0].decode("utf-8"))
複製代碼
neo-python
最使人欣喜的功能之一是可以在 NEO 平臺上快速構建、測試、導入以及調用智能合約。本節將提供在 Prompt 裏操做智能合約的基本指南。
首先,你須要在 prompt 裏建立一個智能合約。該方法使用 neo-boa 編譯器編譯智能合約並將其保存爲 .avm 格式。
在 prompt 裏建立或導入智能合約時,最好使用相對路徑 (相對於 neo-python 安裝目錄),儘管絕對路徑可能也有效。
如下是一個示例: sample1.py
def Main():
print("Hello World")
return True
neo> build docs/source/example/sample1.py
Saved output to docs/source/example/sample1.avm
複製代碼
以上命令只是簡單地編譯文件,以後你就能夠在 Prompt 或者 NEO-GUI 中導入已編譯的 .avm 文件。
建立並測試命令更加經常使用,它能夠在編譯文件後執行和檢測結果,只是其語法要複雜些。
查看 ContractParameterType 列表:ContractParameterTypes
該命令語法爲:
build path/to/file.py test {input_params} {return_type} {needs_storage} {needs_dynamic_invoke} param1 param2 etc..
where {input_params}
and {return_type}
{input_params}
:輸入一個或一系列 ContractParameterType
,例如 0710
表示智能合約接收一個字符串和列表。{return_type}
:輸入一個 ContractParameterType
, 例如 02
表示智能合約返回一個整數。{needs_storage}
:輸入布爾值 True
或 False
指示智能合約是否使用 Storage.Get/Put/Delete
互操做 API。{needs_dynamic_invoke}
:輸入布爾值True
或 False
,用於指示智能合約是否調用另外一個運行時才知道地址的合約,一般爲 False
。params1 params2 etc...
:輸入你用來測試的參數。所以要建立並測試 sample1.py
,命令格式爲 build docs/source/example/sample1.py test '' 01 False False
,其中 ''
表示不接收參數,01
表示返回一個布爾值。在 Prompt 中輸入以下:
neo> build docs/source/example/sample1.py test '' 01 False false
Saved output to docs/source/example/sample1.avm
please open a wallet to test built contract
neo>
複製代碼
如今咱們能夠打開錢包來測試以前建立的合約了。注意,打開錢包後,你可使用向上箭頭鍵選擇以前輸入過的命令。
neo> open wallet Wallets/awesome
[password]> ***********
Opened wallet at Wallets/awesome
neo> build docs/source/example/sample1.py test '' 01 False false
Saved output to docs/source/example/sample1.avm
[I 180302 22:22:58 Invoke:482] Used 0.016 Gas
-----------------------------------------------------------
Calling docs/source/example/sample1.py with arguments []
Test deploy invoke successful
Used total of 11 operations
Result [{'type': 'Boolean', 'value': True}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
到此咱們就完成了第一個智能合約的建立和測試。若是想要查看該智能合約做爲整數時的結果,能夠更改 return_type
,你會獲得以下所示的輸出:
neo> build docs/source/example/sample1.py test '' 02 False False
Saved output to docs/source/example/sample1.avm
[I 180302 22:25:09 Invoke:482] Used 0.016 Gas
-----------------------------------------------------------
Calling docs/source/example/sample1.py with arguments []
Test deploy invoke successful
Used total of 11 operations
Result [{'type': 'Integer', 'value': 1}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
在上例中你會發現,儘管合約中包含了 print
命令,卻並無打印輸出任何字符。要解決這個問題,讓咱們打開智能合約事件並再次運行一遍。
neo>
neo> config sc-events on
Smart contract event logging is now enabled
neo> build docs/source/example/sample1.py test '' 01 False False
Saved output to docs/source/example/sample1.avm
[I 180302 22:56:19 EventHub:71] [test_mode][SmartContract.Contract.Create] [09a129673c61917593cb4b57dce066688f539d15] ['{\n "version": 0,\n "code": {\n "hash": "0x09a129673c61917593cb4b57dce066688f539d15",\n "script": "54c56b0b48656c6c6f20576f726c64680f4e656f2e52756e74696d652e4c6f67516c7566",\n "parameters": "",\n "returntype": 1\n },\n "name": "test",\n "code_version": "test",\n "author": "test",\n "email": "test",\n "description": "test",\n "properties": {\n "storage": false,\n "dynamic_invoke": false\n }\n}']
[I 180302 22:56:19 EventHub:71] [test_mode][SmartContract.Runtime.Log] [09a129673c61917593cb4b57dce066688f539d15] [b'Hello World']
[I 180302 22:56:19 EventHub:71] [test_mode][SmartContract.Execution.Success] [09a129673c61917593cb4b57dce066688f539d15] [1]
[I 180302 22:56:20 Invoke:482] Used 0.016 Gas
-----------------------------------------------------------
Calling docs/source/example/sample1.py with arguments []
Test deploy invoke successful
Used total of 11 operations
Result [{'type': 'Boolean', 'value': True}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
當咱們在 prompt 裏使用 config sc-events on
命令打開 SmartContractEvent 日誌功能後,再次運行相同的命令會發現此次輸出結果中多出了三行。
Hello World
的事件下面讓咱們嘗試一個複雜點的合約,sample2.py:
def Main(operation, a, b):
if operation == 'add':
return a + b
elif operation == 'sub':
return a - b
elif operation == 'mul':
return a * b
elif operation == 'div':
return a / b
else:
return -1
複製代碼
建立並指定幾個參數運行該合約:
neo> build docs/source/example/sample2.py test 070202 02 False False
Saved output to docs/source/example/sample2.avm
[E 180302 22:30:01 ExecutionEngine:825] COULD NOT EXECUTE OP: Invalid list operation b'z' ROLL
[E 180302 22:30:01 ExecutionEngine:826] Invalid list operation
Traceback (most recent call last):
File "/Users/thomassaunders/Workshop/neo-python/neo/VM/ExecutionEngine.py", line 823, in StepInto
self.ExecuteOp(op, self.CurrentContext)
File "/Users/thomassaunders/Workshop/neo-python/neo/VM/ExecutionEngine.py", line 276, in ExecuteOp
estack.PushT(estack.Remove(n))
File "/Users/thomassaunders/Workshop/neo-python/neo/VM/RandomAccessStack.py", line 57, in Remove
raise Exception("Invalid list operation")
Exception: Invalid list operation
[I 180302 22:30:01 InteropService:93] Trying to get big integer Array: ['None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None', 'None']
複製代碼
出現以上結果的緣由是,咱們測試的合約要求提供更多的參數。若是你在建立並測試合約時遇到類似的錯誤信息,頗有多是相同的緣由。讓咱們輸入一些參數再嘗試一次:
neo> build docs/source/example/sample2.py test 070202 02 False False add 1 2
Saved output to docs/source/example/sample2.avm
[I 180302 22:32:06 Invoke:482] Used 0.033 Gas
-----------------------------------------------------------
Calling docs/source/example/sample2.py with arguments ['add', '1', '2']
Test deploy invoke successful
Used total of 39 operations
Result [{'type': 'Integer', 'value': 3}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
neo> build docs/source/example/sample2.py test 070202 02 False False mul -1 20000
Saved output to docs/source/example/sample2.avm
[I 180302 22:33:36 Invoke:482] Used 0.041 Gas
-----------------------------------------------------------
Calling docs/source/example/sample2.py with arguments ['mul', '-1', '20000']
Test deploy invoke successful
Used total of 53 operations
Result [{'type': 'Integer', 'value': -20000}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
此次好多了。接下來讓咱們作些更有用的嘗試,咱們將作一個簡單的地址餘額跟蹤器。
from boa.interop.Neo.Storage import Get,Put,Delete,GetContext
def Main(operation, addr, value):
if not is_valid_addr(addr):
return False
ctx = GetContext()
if operation == 'add':
balance = Get(ctx, addr)
new_balance = balance + value
Put(ctx, addr, new_balance)
return new_balance
elif operation == 'remove':
balance = Get(ctx, addr)
Put(ctx, addr, balance - value)
return balance - value
elif operation == 'balance':
return Get(ctx, addr)
return False
def is_valid_addr(addr):
if len(addr) == 20:
return True
return False
複製代碼
咱們將使用 add
進行一個測試,給錢包裏的一個地址添加一些值。你會注意到,當你在錢包裏輸入任意地址時會自動完成輸入,這可能會產生誤導。當經過 prompt
將地址發送到 SC 時,它會自動轉換爲 ByteArray 以便使用。 所以方法簽名看起來像 070502 或 String,ByteArray,Integer。
咱們使用 True
來表示使用智能合約的 Storage
API。
neo> build docs/source/example/sample3.py test 070502 02 True False add AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy 3
Saved output to docs/source/example/sample3.avm
[I 180302 23:04:33 Invoke:482] Used 1.174 Gas
-----------------------------------------------------------
Calling docs/source/example/sample3.py with arguments ['add', 'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy', '3']
Test deploy invoke successful
Used total of 106 operations
Result [{'type': 'Integer', 'value': 3}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
再次調用,將看到咱們的測試調用保留了存儲庫中的值。
neo> build docs/source/example/sample3.py test 070502 02 True False add AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy 3
Saved output to docs/source/example/sample3.avm
[I 180302 23:04:33 Invoke:482] Used 1.174 Gas
-----------------------------------------------------------
Calling docs/source/example/sample3.py with arguments ['add', 'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy', '3']
Test deploy invoke successful
Used total of 106 operations
Result [{'type': 'Integer', 'value': 6}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
如今除去一些值:
neo> build docs/source/example/sample3.py test 070502 02 True False remove AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy 2
Saved output to docs/source/example/sample3.avm
[I 180302 23:09:21 Invoke:482] Used 1.176 Gas
-----------------------------------------------------------
Calling docs/source/example/sample3.py with arguments ['remove', 'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy', '2']
Test deploy invoke successful
Used total of 109 operations
Result [{'type': 'Integer', 'value': 4}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
你也能夠爲地址傳入一個 ByteArray 對象,並測試是否 is_valid_addr
在任何事情發生前返回 False,這會被解析爲 0:
neo> build docs/source/example/sample3.py test 070502 02 True False add bytearray(b'\x00\x01\x02\x03') 4
Saved output to docs/source/example/sample3.avm
[I 180302 23:12:43 Invoke:482] Used 0.041 Gas
-----------------------------------------------------------
Calling docs/source/example/sample3.py with arguments ['add', "bytearray(b'\\x00\\x01\\x02\\x03')", '4']
Test deploy invoke successful
Used total of 52 operations
Result [{'type': 'Integer', 'value': 0}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
請注意,以可讀格式 (
) 發送地址與發送地址的腳本哈希是同樣的。咱們將經過獲取餘額進行嘗試。因爲智能合約指望第三個參數,我在最後添加了一個額外的 0 做爲最後一個參數:
neo> build docs/source/example/sample3.py test 070502 02 True False balance bytearray(b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96') 0
Saved output to docs/source/example/sample3.avm
[I 180302 23:16:23 Invoke:482] Used 0.162 Gas
-----------------------------------------------------------
Calling docs/source/example/sample3.py with arguments ['balance', "bytearray(b'\\x03\\x19\\xe0)\\xb9%\\x85w\\x90\\xe4\\x17\\x85\\xbe\\x9c\\xce\\xc6\\xca\\xb1\\x98\\x96')", '0']
Test deploy invoke successful
Used total of 87 operations
Result [{'type': 'Integer', 'value': 4}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
導入智能合約有點相似 build .. test
命令,但你不須要發送任何參數。命令格式爲:
import contract path/to/sample2.avm {input_params} {return_type} {needs_storage} {needs_dynamic_invoke}
運行該命令後,若是一切正常系統會提示你添加合約相關的元數據。完成後你就能夠選擇在網絡中實際部署將該合約。請注意部署合約將花費 GAS。
neo>
neo> import contract docs/source/example/sample2.avm 070202 02 False False
Please fill out the following contract details:
[Contract Name] > Sample Calculator
[Contract Version] > .01
[Contract Author] > Thomas Saunders
[Contract Email] > tom@cityofzion.io
[Contract Description] > A test calculator contract
Creating smart contract....
Name: A test calculator contract
Version: .01
Author: tom@cityofzion.io
Email: tom@cityofzion.io
Description: A test calculator contract
Needs Storage: False
Needs Dynamic Invoke: False
{
"hash": "0x86d58778c8d29e03182f38369f0d97782d303cc0",
"script": "5ec56b6a00527ac46a51527ac46a52527ac46a00c3036164649c640d006a51c36a52c3936c7566616a00c3037375629c640d006a51c36a52c3946c7566616a00c3036d756c9c640d006a51c36a52c3956c7566616a00c3036469769c640d006a51c36a52c3966c7566614f6c7566006c7566",
"parameters": "070202",
"returntype": "02"
}
Used 100.0 Gas
-------------------------------------------------------------------------------------------------------------------------------------
Test deploy invoke successful
Total operations executed: 11
Results:
[<neo.Core.State.ContractState.ContractState object at 0x11435d2e8>]
Deploy Invoke TX GAS cost: 90.0
Deploy Invoke TX Fee: 0.0
-------------------------------------------------------------------------------------------------------------------------------------
Enter your password to continue and deploy this contract
[password]>
複製代碼
從這裏開始,若是你肯定要花費 GAS 來部署合約,輸入密碼:
Enter your password to continue and deploy this contract
[password]> ***********
[I 180302 23:46:23 Transaction:611] Verifying transaction: b'f8ad261d28bf4bc5544e47f9bc3fff85f85ee674f14162dac81dd56bf73cf0a3'
Relayed Tx: f8ad261d28bf4bc5544e47f9bc3fff85f85ee674f14162dac81dd56bf73cf0a3
neo>
複製代碼
如今你已將合約部署到網絡。 若是一切順利,將很快部署。 要肯定什麼時候部署完成,在區塊鏈中搜索 txid 或合約哈希。
neo> tx f8ad261d28bf4bc5544e47f9bc3fff85f85ee674f14162dac81dd56bf73cf0a3
{
"txid": "0xf8ad261d28bf4bc5544e47f9bc3fff85f85ee674f14162dac81dd56bf73cf0a3",
"type": "InvocationTransaction",
"version": 1,
"attributes": [],
[ MORE Output Omitted ]
neo> contract 0x86d58778c8d29e03182f38369f0d97782d303cc0
{
"version": 0,
"code": {
"hash": "0x86d58778c8d29e03182f38369f0d97782d303cc0",
"script": "5ec56b6a00527ac46a51527ac46a52527ac46a00c3036164649c640d006a51c36a52c3936c7566616a00c3037375629c640d006a51c36a52c3946c7566616a00c3036d756c9c640d006a51c36a52c3956c7566616a00c3036469769c640d006a51c36a52c3966c7566614f6c7566006c7566",
"parameters": "070202",
"returntype": 2
},
"name": "A test calculator contract",
"code_version": ".01",
"author": "tom@cityofzion.io",
"email": "tom@cityofzion.io",
"description": "A test calculator contract",
"properties": {
"storage": false,
"dynamic_invoke": false
}
}
neo>
複製代碼
如今你已經在網絡上部署了合同,可使用真正的 InvocationTransactions 與它進行交互。
一旦部署了合約,你就沒法再像使用 build .. test
命令那樣進行交互,更改和構建,但最好是使用 testinvoke
來肯定鏈上的工做。
如今咱們已經部署了
,只要知道它的腳本哈希,就可使用 testinvoke
命令與它進行交互。命令格式是 testinvoke {contract_hash} param1 param2 ..
neo> testinvoke 0x86d58778c8d29e03182f38369f0d97782d303cc0 add 1 2
Used 0.033 Gas
-------------------------------------------------------------------------------------------------------------------------------------
Test invoke successful
Total operations: 39
Results ['Integer: 3 ']
Invoke TX GAS cost: 0.0
Invoke TX fee: 0.0001
-------------------------------------------------------------------------------------------------------------------------------------
Enter your password to continue and invoke on the network
[password]>
複製代碼
這個調用只在本地完成,只有在你輸入密碼後才能運行。若是你不但願在網絡中調用,只需輸入錯誤密碼便可取消。這裏咱們取消調用,而後設置 config sc-events on
以確切地查看測試調用時發生的狀況,而後將其發送到網絡:
Enter your password to continue and invoke on the network
[password]> **
Incorrect password
neo>
neo> config sc-events on
Smart contract event logging is now enabled
neo>
neo> testinvoke 0x86d58778c8d29e03182f38369f0d97782d303cc0 add 1 2
[I 180303 07:38:58 EventHub:71] [test_mode][SmartContract.Execution.Success] [86d58778c8d29e03182f38369f0d97782d303cc0] [3]
Used 0.033 Gas
-------------------------------------------------------------------------------------------------------------------------------------
Test invoke successful
Total operations: 39
Results ['Integer: 3 ']
Invoke TX GAS cost: 0.0
Invoke TX fee: 0.0001
-------------------------------------------------------------------------------------------------------------------------------------
Enter your password to continue and invoke on the network
[password]> ***********
[I 180303 07:39:04 Transaction:611] Verifying transaction: b'e0f4251a83f7081fb6fd94ce884d12b0bb597c1c1b3f1a89f07db68e114f4fa2'
[I 180303 07:39:04 EventHub:89] [SmartContract.Verification.Success][433121] [4c896601a99d58e22c32dcadd24974ca24c10587] [tx e0f4251a83f7081fb6fd94ce884d12b0bb597c1c1b3f1a89f07db68e114f4fa2] [True]
Relayed Tx: e0f4251a83f7081fb6fd94ce884d12b0bb597c1c1b3f1a89f07db68e114f4fa2
neo>
neo> [I 180303 07:39:31 EventHub:89] [SmartContract.Execution.Success][433122] [86d58778c8d29e03182f38369f0d97782d303cc0] [tx e0f4251a83f7081fb6fd94ce884d12b0bb597c1c1b3f1a89f07db68e114f4fa2] [3]
neo>
複製代碼
在這裏請注意如下幾點:
sc-events on
測試調用時,將看到
test_mode
完成測試。test_mode
中,你將再次看到SmartContract.Execution.Success 事件。如今,你已經完成了合約的構建、測試和測試調用,你可能會問,這個驗證步驟是什麼,如何與之程序化的交互?讓咱們從以前一個跟蹤餘額的例子開始,限制僅有一個全部者地址能夠對其執行操做。如下是智能合約代碼:
from boa.interop.Neo.Runtime import GetTrigger,CheckWitness
from boa.interop.Neo.Storage import Get,Put,Delete,GetContext
from boa.interop.Neo.TriggerType import Application, Verification
OWNER = b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96'
def Main(operation, addr, value):
print("Running Sample v4")
trigger = GetTrigger()
# This determines that the SC is runnning in Verification mode
# This determines whether the TX will be relayed to the rest of the network
# The `Verification` portion of SC is *read-only*, so calls to `Storage.Put` will fail.
# You can, however, use `Storage.Get`
if trigger == Verification():
print("Running Verification!")
# This routine is: if the invoker ( or the Address that signed the contract ) is not OWNER,
# Then we return False, and the TX will not be relayed to the network
# Otherwise, we know the owner address signed the TX and return True
is_owner = CheckWitness(OWNER)
if is_owner:
print("Is Owner!")
return True
print("Not Owner")
return False
elif trigger == Application():
print("Running Application!")
if not is_valid_addr(addr):
print("Not Valid Address")
return False
ctx = GetContext()
if operation == 'add':
balance = Get(ctx, addr)
new_balance = balance + value
Put(ctx, addr, new_balance)
return new_balance
elif operation == 'remove':
balance = Get(ctx, addr)
Put(ctx, addr, balance - value)
return balance - value
elif operation == 'balance':
return Get(ctx, addr)
return False
return False
def is_valid_addr(addr):
if len(addr) == 20:
return True
return False
複製代碼
OWNER
就是咱們以前用過的ByteArray, 是咱們使用的錢包裏的地址。上例將使用boa.interop.Neo.Runtime.CheckWitness
方法來驗證簽名 InvocationTransaction 的錢包是否與 OWNER
的同樣。首先,構建合約並測試其是否正常執行。咱們將打開 sc-events
以便準確地看到執行過程。
neo>
neo> build docs/source/neo/example/sample4.py test 070202 02 True False add AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy 7
Saved output to docs/source/neo/example/sample4.avm
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Contract.Create] [562d6c29209dc96432c6868621fe489cedd05222] ['{\n "version": 0,\n "code": {\n "hash": "0x562d6c29209dc96432c6868621fe489cedd05222",\n "script": "0122c56b6a00527ac46a51527ac46a52527ac4140319e029b925857790e41785be9ccec6cab198966a53527ac41152756e6e696e672053616d706c65207634680f4e656f2e52756e74696d652e4c6f6768164e656f2e52756e74696d652e47657454726967676572616a54527ac46a54c301009c6492001552756e6e696e6720566572696669636174696f6e21680f4e656f2e52756e74696d652e4c6f676a53c368184e656f2e52756e74696d652e436865636b5769746e657373616a55527ac46a55c3642200094973204f776e657221680f4e656f2e52756e74696d652e4c6f67516c756661094e6f74204f776e6572680f4e656f2e52756e74696d652e4c6f67006c7566616a54c301109c6454011452756e6e696e67204170706c69636174696f6e21680f4e656f2e52756e74696d652e4c6f676a51c3652d01632a00114e6f742056616c69642041646472657373680f4e656f2e52756e74696d652e4c6f67006c75666168164e656f2e53746f726167652e476574436f6e74657874616a56527ac46a00c3036164649c6450006a56c36a51c37c680f4e656f2e53746f726167652e476574616a57527ac46a57c36a52c3936a58527ac46a56c36a51c36a58c35272680f4e656f2e53746f726167652e507574616a58c36c7566616a00c30672656d6f76659c644c006a56c36a51c37c680f4e656f2e53746f726167652e476574616a57527ac46a56c36a51c36a57c36a52c3945272680f4e656f2e53746f726167652e507574616a57c36a52c3946c7566616a00c30762616c616e63659c641f006a56c36a51c37c680f4e656f2e53746f726167652e476574616c756661006c756656c56b6a00527ac46a00c3c001149c640700516c756661006c7566",\n "parameters": "070202",\n "returntype": 2\n },\n "name": "test",\n "code_version": "test",\n "author": "test",\n "email": "test",\n "description": "test",\n "properties": {\n "storage": true,\n "dynamic_invoke": false\n }\n}']
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Runtime.Log] [562d6c29209dc96432c6868621fe489cedd05222] [b'Running Sample v4']
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Runtime.Log] [562d6c29209dc96432c6868621fe489cedd05222] [b'Running Application!']
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Storage.Get] [562d6c29209dc96432c6868621fe489cedd05222] ['AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy -> 0']
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Storage.Put] [562d6c29209dc96432c6868621fe489cedd05222] ['AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy -> 7']
[I 180303 08:25:12 EventHub:71] [test_mode][SmartContract.Execution.Success] [562d6c29209dc96432c6868621fe489cedd05222] [7]
[I 180303 08:25:12 Invoke:482] Used 1.191 Gas
-----------------------------------------------------------
Calling docs/source/neo/example/sample4.py with arguments ['add', 'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy', '7']
Test deploy invoke successful
Used total of 136 operations
Result [{'type': 'Integer', 'value': 7}]
Invoke TX gas cost: 0.0001
-------------------------------------------------------------
neo>
複製代碼
到這裏執行過程跟以前差很少。咱們添加了一些新的 print 語句,經過這些語句能看到智能合約的 Verification
部分從未執行。另外,合約中的 SmartContract.Storage.\*
事件對調試很是有用。目前,爲了與智能合約的Verification
階段交互,你須要部署並使用 testinvoke
。假設你已經構建並導入合約,將獲得以下結果:
neo> contract 2e80ee491a0a54c9bbb0f791672050f9ab367767
{
"version": 0,
"code": {
"hash": "0x2e80ee491a0a54c9bbb0f791672050f9ab367767",
"script": "0123c56b6a00527ac46a51527ac46a52527ac4140319e029b925857790e41785be9ccec6cab198966a53527ac41152756e6e696e672053616d706c65207634680f4e656f2e52756e74696d652e4c6f6768164e656f2e52756e74696d652e47657454726967676572616a54527ac46a54c3680f4e656f2e52756e74696d652e4c6f676a54c301009c6492001552756e6e696e6720566572696669636174696f6e21680f4e656f2e52756e74696d652e4c6f676a53c368184e656f2e52756e74696d652e436865636b5769746e657373616a55527ac46a55c3642200094973204f776e657221680f4e656f2e52756e74696d652e4c6f67516c756661094e6f74204f776e6572680f4e656f2e52756e74696d652e4c6f67006c7566616a54c301109c6454011452756e6e696e67204170706c69636174696f6e21680f4e656f2e52756e74696d652e4c6f676a51c3652d01632a00114e6f742056616c69642041646472657373680f4e656f2e52756e74696d652e4c6f67006c75666168164e656f2e53746f726167652e476574436f6e74657874616a56527ac46a00c3036164649c6450006a56c36a51c37c680f4e656f2e53746f726167652e476574616a57527ac46a57c36a52c3936a58527ac46a56c36a51c36a58c35272680f4e656f2e53746f726167652e507574616a58c36c7566616a00c30672656d6f76659c644c006a56c36a51c37c680f4e656f2e53746f726167652e476574616a57527ac46a56c36a51c36a57c36a52c3945272680f4e656f2e53746f726167652e507574616a57c36a52c3946c7566616a00c30762616c616e63659c641f006a56c36a51c37c680f4e656f2e53746f726167652e476574616c756661006c756656c56b6a00527ac46a00c3c001149c640700516c756661006c7566",
"parameters": "070202",
"returntype": 2
},
"name": "test",
"code_version": "test",
"author": "test",
"email": "test",
"description": "test",
"properties": {
"storage": true,
"dynamic_invoke": false
}
}
neo>
複製代碼
再次測試調用一遍。
neo> testinvoke 0x2e80ee491a0a54c9bbb0f791672050f9ab367767 add AMUUgxnLhGxNSATinNp8gKmndqM1BxDZHR 42
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Runtime.Log] [2e80ee491a0a54c9bbb0f791672050f9ab367767] [b'Running Sample v4']
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Runtime.Log] [2e80ee491a0a54c9bbb0f791672050f9ab367767] [b'\x10']
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Runtime.Log] [2e80ee491a0a54c9bbb0f791672050f9ab367767] [b'Running Application!']
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Storage.Get] [2e80ee491a0a54c9bbb0f791672050f9ab367767] ['AMUUgxnLhGxNSATinNp8gKmndqM1BxDZHR -> 0']
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Storage.Put] [2e80ee491a0a54c9bbb0f791672050f9ab367767] ['AMUUgxnLhGxNSATinNp8gKmndqM1BxDZHR -> 42']
[I 180303 09:08:14 EventHub:71] [test_mode][SmartContract.Execution.Success] [2e80ee491a0a54c9bbb0f791672050f9ab367767] [42]
Used 1.194 Gas
-------------------------------------------------------------------------------------------------------------------------------------
Test invoke successful
Total operations: 140
Results ['Integer: 42 ']
Invoke TX GAS cost: 0.0
Invoke TX fee: 0.0001
-------------------------------------------------------------------------------------------------------------------------------------
Enter your password to continue and invoke on the network
[password]>
複製代碼
這裏仍是沒有看到任何驗證事件。一旦咱們輸入密碼將其轉發到網絡,將看到以下結果:
[password]> ***********
[I 180303 08:36:52 Transaction:611] Verifying transaction: b'0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40'
[I 180303 08:35:38 EventHub:71] [test_mode][SmartContract.Runtime.Log] [562d6c29209dc96432c6868621fe489cedd05222] [b'Running Sample v4']
[I 180303 08:35:38 EventHub:71] [test_mode][SmartContract.Runtime.Log] [562d6c29209dc96432c6868621fe489cedd05222] [b'Running Verification!']
[I 180303 08:35:38 EventHub:71] [test_mode][SmartContract.Runtime.Log] [562d6c29209dc96432c6868621fe489cedd05222] [b'Is Owner!']
[I 180303 08:36:52 EventHub:89] [SmartContract.Verification.Success][433331] [f64d628af19f53a6b8226a44c93182eff6fcb222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] [True]
Relayed Tx: 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40
neo>
neo>
neo>
neo> [I 180303 08:37:29 EventHub:89] [SmartContract.Runtime.Log][433333] [562d6c29209dc96432c6868621fe489cedd05222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] [b'Running Sample v4']
[I 180303 08:37:29 EventHub:89] [SmartContract.Runtime.Log][433333] [562d6c29209dc96432c6868621fe489cedd05222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] [b'Running Application!']
[I 180303 08:37:29 EventHub:89] [SmartContract.Storage.Get][433333] [562d6c29209dc96432c6868621fe489cedd05222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] ['AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy -> 0']
[I 180303 08:37:29 EventHub:89] [SmartContract.Storage.Put][433333] [562d6c29209dc96432c6868621fe489cedd05222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] ['AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy -> 17']
[I 180303 08:37:29 EventHub:89] [SmartContract.Execution.Success][433333] [562d6c29209dc96432c6868621fe489cedd05222] [tx 0fd755e847a5ce54f9894c0c0bbf9303730ac28d8aeacdaddb2f912a2a3fcd40] [17]
複製代碼
和預期的同樣。如今咱們將打開不一樣的錢包並嘗試調用相同的東西。
在使用 NEO-python 或 NEO 區塊鏈時,你須要熟悉一些數據類型,這能夠幫助你識別在系統的各部分以不一樣格式出現的這些數據類型,以及正確使用它們。本章將簡要描述每種數據類型及其通常用法。
請注意,這些數據類型是在 neocore
項目中實現的,但在 neo-python 中用的不少。
NEO 中的地址其實是一對公鑰/私鑰。當建立一個錢包時,會根據錢包密碼建立一個32位的私鑰,這個私鑰只能你本身知道和保存。此私鑰與公鑰配對,用於標識網絡上的地址。只有簽名交易時才須要用到私鑰。
若是在 prompt
中打開一個錢包,運行 wallet
命令,在輸出的信息中能夠查看到錢包的公鑰,例如:
"public_keys": [
{
"Address": "AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy",
"Public Key": "036d4de3e05057df18b82718d635795cb67d9c19001e998d76c77b86081be5f160"
}
],
複製代碼
上例中 Public Key
以壓縮格式表示 ECDSA 曲線上的 x 和 y 座標,特別是 *SECP256R1 曲線。咱們經過一系列步驟推導出 Address
:
建立一個以 21
開頭 ac
結尾的公鑰 UInt160
或 ScriptHash
:
>>> from neocore.Cryptography.Crypto import Crypto
>>> pubkey_hex = '036d4de3e05057df18b82718d635795cb67d9c19001e998d76c77b86081be5f160'
>>> pubkey_hex_for_addr = '21' + pubkey_hex + 'ac'
>>> pubkey_hex_for_addr
'21036d4de3e05057df18b82718d635795cb67d9c19001e998d76c77b86081be5f160ac'
>>> script_hash = Crypto.ToScriptHash(pubkey_hex_for_addr, unhex=True)
>>> script_hash
<neocore.UInt160.UInt160 object at 0x10d33e908>
>>> script_hash.Data
bytearray(b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96')
複製代碼
接着,從如下腳本散列建立一個地址:
>>> addr = Crypto.ToAddress(script_hash)
>>> addr
'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy'
>>>
複製代碼
若是對 KeyPair
、 UInt160
、或 Crypto
包的實現細節感興趣,能夠查看 neocore repository。
UInt256
表示 32位 的散列。它一般是一個 Transaction
對象或 Block
的散列。 它通常顯示爲 64 字符的字符串或帶有 0x 十六進制說明符的 66 個字符的字符串。如下是一個與 UInt256
交互的例子。
>>>
>>> from neocore.UInt256 import UInt256
>>>
>>> hash = "0x99e2be05956027b884cbf11cddbf9d2e5a8fb97ab18d5cde44d5ae2d4c980d18"
>>>
>>> uint = UInt256.ParseString(hash)
>>> uint
<neocore.UInt256.UInt256 object at 0x10cb9b240>
>>> uint.ToString()
'99e2be05956027b884cbf11cddbf9d2e5a8fb97ab18d5cde44d5ae2d4c980d18'
>>> uint.To0xString()
'0x99e2be05956027b884cbf11cddbf9d2e5a8fb97ab18d5cde44d5ae2d4c980d18'
>>> uint.Data
bytearray(b"\x18\r\x98L-\xae\xd5D\xde\\\x8d\xb1z\xb9\x8fZ.\x9d\xbf\xdd\x1c\xf1\xcb\x84\xb8\'`\x95\x05\xbe\xe2\x99")
>>>
>>> uint.ToBytes()
b'99e2be05956027b884cbf11cddbf9d2e5a8fb97ab18d5cde44d5ae2d4c980d18'
>>>
>>> data = uint.Data
>>> data
bytearray(b"\x18\r\x98L-\xae\xd5D\xde\\\x8d\xb1z\xb9\x8fZ.\x9d\xbf\xdd\x1c\xf1\xcb\x84\xb8\'`\x95\x05\xbe\xe2\x99")
>>>
>>> copy = UInt256(data=data)
>>>
>>> copy.To0xString()
'0x99e2be05956027b884cbf11cddbf9d2e5a8fb97ab18d5cde44d5ae2d4c980d18'
>>>
複製代碼
須要注意的是,咱們一般看到的是字符串,或者 UInt256 的 0x 字符串版本。
UInt160
表示 20 位的散列,也可稱爲一個 ScriptHash
。它用於顯示 NEO 中的 Address
對象是普通地址仍是合約地址。如下是一個與 UInt160
交互的例子。
>>>
>>> data = bytearray(b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96')
>>>
>>> from neocore.UInt160 import UInt160
>>>
>>> new_sh = UInt160(data=data)
>>> new_sh
<neocore.UInt160.UInt160 object at 0x10d3460b8>
>>> new_sh.Data
bytearray(b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96')
>>>
>>> new_sh.To0xString()
'0x9698b1cac6ce9cbe8517e490778525b929e01903'
>>>
>>> sh_again = UInt160.ParseString( new_sh.To0xString() )
>>> sh_again.Data
bytearray(b'\x03\x19\xe0)\xb9%\x85w\x90\xe4\x17\x85\xbe\x9c\xce\xc6\xca\xb1\x98\x96')
>>>
>>> Crypto.ToAddress( sh_again)
'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy'
>>>
複製代碼
Fixed8
用於表示整數格式的 8 位小數。如下是一個使用 Fixed8
的基本示例。
>>> from neocore.Fixed8 import Fixed8
>>>
>>> three = Fixed8.FromDecimal(3)
>>> three.value
300000000
>>> three.ToInt()
3
>>> three.ToString()
'3.0'
>>>
>>>
>>> point5 = Fixed8(50000000)
>>> point5.ToString()
'0.5'
>>>
>>> point5 + three
<neocore.Fixed8.Fixed8 object at 0x10cd48ba8>
>>> threepoint5 = point5 + three
>>> threepoint5.value
350000000
>>>
>>> threepoint5.ToString()
'3.5'
>>>
>>>
>>> threepoint5 * 2
Traceback (most recent call last):
File "<input>", line 1, in <module>
threepoint5 * 2
File "/Users/thomassaunders/Workshop/neo-python/venv/lib/python3.6/site-packages/neocore/Fixed8.py", line 85, in __mul__
return Fixed8(self.value * other.value)
AttributeError: 'int' object has no attribute 'value'
>>>
>>>
複製代碼
如下是一些總結:
Fixed8.FromDecimal
方法。Fixed8
,你能夠對 Fixed8 對象進行數學運算。Fixed8
和另外一種類型的數字之間進行數學運算會引起錯誤。value
屬性來訪問 Fixed8
對象的完整值。BigInteger
用於存儲和對任意大小的整數進行運算,包括負數和正數。這對將數字序列化爲字節和返回很是有用。如下是 BigInteger
的一些示例用法。
>>> from neocore.BigInteger import BigInteger
>>>
>>> bi = BigInteger(10000)
>>>
>>> bi.ToByteArray()
b"\x10'"
>>>
>>> bi2 = BigInteger.FromBytes( bi.ToByteArray() )
>>> bi2
10000
>>>
>>> bi3 = BigInteger(-3)
>>>
>>> bi4 = bi2 * bi3
>>> bi4
-30000
>>>
>>> bi4 += 100000
>>> bi4
70000
>>> bi4.ToByteArray()
b'p\x11\x01'
>>>
複製代碼
BigInteger
實現中須要注意的一點是它與 Fixed8
不一樣,所以你能夠在 BigInteger
和普通整數之間進行數學運算。
如下是建立和調用智能合約中用到的 ContractParameterTypes。
描述:
neo.Wallets 中的合約參數
用法:
從 neo.SmartContract.ContractParameterType 導入 ContractParameterType
class neo.SmartContract.ContractParameterType.ContractParameterType
Contract Parameter Types are used to denote different types of objects used in the VM
Signature
00
Boolean
01
Integer
02
Hash160
03
Hash256
04
ByteArray
05
PublicKey
06
String
07
Array
10
InteropInterface
F0
Void
FF
neo.SmartContract.ContractParameterType.``ToName (param_type)
根據其值 param_type 獲取 ContractParameterType 的名稱。
您可使用此命令開始測試:
make test
複製代碼
使用此命令運行樣式檢查:
make lint
複製代碼
使用此命令運行 neo-python 測試
python -m unittest discover neo
複製代碼
使用此命令運行 neo-boa 項目的測試:
python -m unittest discover boa_test
複製代碼
若是要添加測試或更改功能,能夠只運行一個測試:
python -m unittest neo/test_settings.py複製代碼
如下指南與全部依賴於 BlockChainFixtureTestCase
或 WalletFixtureTestCase
的unit-tests
相關。這種測試依賴於 neo-python-privnet-unittest
映像生成的裝置。該映像位於這裏。
BlockChainFixtureTestCase
的測試是使用 BC 錢包(neo-test-bc.wallet
, neo-test2-bc.wallet
)裏的地址之間的交易生成的。有時在少數測試中也使用 neo-test-coz.wallet
裏的默認地址。COZ 錢包很特別,它是原始的 COZ 私網錢包,擁有 100000000 NEO。直接依賴 WalletFixtureTestCase
的測試是使用 W 錢包 (neo-test1-w.wallet
, neo-test2-w.wallet
, neo-test3-w.wallet
) 裏的地址之間的交易生成的。
下圖能夠更好的說明測試 BC 和 W:
向私網測試裝置新增測試時請遵循如下方針,以便最小化單元測試間的依賴:
neo-test-coz.wallet
,由於該錢包是其它測試錢包的 NEO 和 GAS的來源,會常常被更改。若是測試中使用了neo-test-coz.wallet
,你將隨時須要進行更新。上述最後三條要求更新測試裝置,操做以下:
拉取最新 neo-python-privnet-unittest image:
docker pull cityofzion/neo-python-privnet-unittest:v0.0.xx
複製代碼
運行 image:
docker run --rm -d --name neo-privnet-unittest -p 20333-20336:20333-20336/tcp -p 30333-30336:30333-30336/tcp dautt/neo-privnet-unittest:v0.0.xx``
複製代碼
清除當前 unittest
鏈:
rm -rf ~/.neopython/Chains/unittest
rm -rf ~/.neopython/Chains/unittest_notif
複製代碼
激活你的虛擬環境:
source venv/bin/activate
複製代碼
啓動 NEO 節點:
python prompt.py -u
複製代碼
使用如下錢包生成交易:
neo-test-coz.wallet (pwd = coz)
neo-test1-bc.wallet (pwd = 1234567890)
neo-test2-bc.wallet (pwd = 1234567890)
neo-test1-w.wallet (pwd = 1234567890)
neo-test2-w.wallet (pwd = 1234567890)
neo-test3-w.wallet (pwd = 1234567890)
複製代碼
(要添加直接依賴 BlockchainFixtureTestCase
的新測試,請使用 -bc.wallet
類型的錢包。要添加直接依賴 WalletFixtureTestCase
的新測試,請使用 -w.wallet
類型的錢包)
若是你須要建立一個新智能合約,考慮使用這裏現有的合約:
fixtures/UnitTest-SM.zip
複製代碼
(若是以上 zip 包中沒有新合約的源代碼,請添加。)
若是你已經在 neo-python-privnet-unittest
映像上部署了一個新合約,請在指定合約名稱時使用 test 爲前綴,這樣可使用如下命令查找出全部部署在映像上的合約:
contract search test
複製代碼
當你對新的單元測試滿意後,保存測試,而後重啓 docker 映像並從新部署你的測試。而後經過增長版本號 (xx+1) 建立一個新的映像:
docker commit neo-privnet-unittest dautt/neo-privnet-unittest:v0.0.xx+1
複製代碼
這樣作的緣由是咱們須要使映像儘量小。你的映像文件可能在不經意間積累了幾天或幾周的新塊,例如,在分階段執行新測試時,這會沒必要要地增長映像的大小。咱們的測試裝置在構建系統中被重置和提取20屢次,因此任何尺寸的增長都會增長延遲 20倍或更多。
經過增長數字後綴建立測試裝置 (x+1):
notif_fixtures_vx+1.tar.gz
fixtures_vx+1.tar.gz
複製代碼
在以下文件的靜態類變量中更新裝置名稱:
neo.Utils.BlockchainFixtureTestCase.py
neo.api.REST.test_rest_api.py
複製代碼
建立一個新的PR,連接到新的映像和新建的測試裝置。