.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,连接到新的映像和新建的测试装置。