数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文介绍如何安装EOS节点软件并接入EOS主网,主要包括以下内容: 如何安装EOS节点软件 如何配置EOS节点软件接入主网 如何启动EOS节点软件与主网数据同步 如何检查主网数据同步进度 如何正确地关闭EOS节点 在出现 database dirty flag set 错误时如何处理? 如果希望高效学习EOS区块链应用开发,推荐汇智网的在线互动教程 《EOS智能合约与DApp开发入门》 。
一、安装EOS节点软件
本文以ubuntu16.04为例介绍EOS节点软件的安装方法,其他操作系统 可参考 官网文档 。
1、下载
首先到官方github下载最新版的eosio软件安装包: ~$ wget https://github.com/eosio/eos/releases/download/v1.6.2/eosio_1.6.2-1-ubuntu-16.04_amd64.deb
2、安装
下载完成安装本地软件包: ~$ sudo apt install ./eosio_1.6.2-1-ubuntu-16.04_amd64.deb
3、验证
安装完成后验证软件版本: ~$ nodeos --version v1.6.2
二、配置EOS节点软件
首先创建一个新的目录作为工作环境,起个容易看懂的名字,例如: ~$ mkdir eos-main
1、下载主网创世文件
EOS节点要接入主网,需要在初次启动nodeos时指定主网的创世文件genesis.json, 可以从CryptoLions的github上下载这个文件: ~/eos-main$ wget https://github.com/CryptoLions/EOS-MainNet/blob/master/genesis.json
2、下载主网配置文件
CryptoLions同样也提供了主网的配置文件config.ini,同样下载到本地: ~/eos-main$ wget https://github.com/CryptoLions/EOS-MainNet/blob/master/config.ini
3、下载最新可用节点清单
从privex.io下载最新的可用EOS节点清单,保存到peers.txt文件中 ~/eos-main$ wget https://eosnodes.privex.io/?config=1 -O peers.txt
4、更新主网配置文件中的节点列表
在配置文件config.ini中,找到所有的 p2p-peer-address 配置项,例如: p2p-peer-address = bp.cryptolions.io:9876 ... p2p-peer-address = mainnet.eoseco.com:10010
然后用peers.txt中的内容替换。
三、首次启动
第一次启动nodeos时,需要指定创世文件,并且清理之前的区块: ~/eos-main$ nodeos --config-dir . --data-dir . --genesis-json genesis.json --delete-all-blocks
启动之后,可以另开终端查看同步进度: ~$ cleos get info
观察输出结果中的 chain_id 如下所示为 aca376... ,就表明已经接入主网: { "server_version": "c8f26078", "chain_id": "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906", "head_block_num": 3712, "last_irreversible_block_num": 3711, "last_irreversible_block_id": "00000e7f1b9d5b50256654921f5ca8a91aa3168f0c0a3e8ea3bbea1ba5c00fe2", "head_block_id": "00000e80a8c5b9e7acc9c063113668b7eae9025aa38a8c8ac3606df6256086e3", "head_block_time": "2018-06-09T12:29:10.500", "head_block_producer": "eosio", "virtual_block_cpu_limit": 2675279111, "virtual_block_net_limit": 42941084, "block_cpu_limit": 100000000, "block_net_limit": 1048576 }
可以将上面信息中的 head_block_num 与 eospark 上的最新区块号对比, 即可得知同步进度。当两者一致后,表示节点与EOS主网达成同步。
四、EOS节点的停止与重新启动
有时可能因为种种原因需要重新启动nodeos,切记不要强制杀掉nodeos,让它 有喘息清理的机会。应当用如下的命令通知nodeos退出: ~$ pkill nodeos
这样关闭的nodeos不会有历史垃圾,因此再次启动时会很顺利: ~/eos-main$ nodeos --config-dir . --data-dir . 注意,在第二次以及以后的启动中,一定__不要__再用__--delete-all-blocks__参数,否则 你会一遍遍的从零开始!
如果必须强制杀掉nodeos,比如使用 pkill -9 或者直接运行中重新启动机器, 那么再次启动nodeos时会失败并收到这个提示: ... database dirty flag set (likely due to unclean shutdown): replay required
这时我们要么删掉全部区块(使用 --delete-all-blocks 参数)重新来过,要么重放交易,比如 硬重放: ~/eos-main$ nodeos nodeos --config-dir . --data-dir . --hard-replay-blockchain
重放问题就是,它也会花掉很长的时间....,虽然比删掉全部区块要好一点。
所以,在关闭nodeos的时候,记得一定温柔一点。
原文连接: EOS节点安装与主网数据同步指南 — 汇智网
区块链
2019-02-22 22:40:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Nethereum基本上是目前唯一可用的.NET平台下的web3.js移植包。在这个教程中,我们将首先编写并部署一个简单的智能合约,然后创建一个简单的.NET应用,并使用Nethereum来访问以太坊上的智能合约。Nethereum是通过以太坊节点旳标准RPC接口访问智能合约,因此使用Nethereum可以对接所有的以太坊节点实现,例如geth或parity。 如果你希望快速掌握Netherem的开发,可以访问汇智网的互动教程 C#以太坊开发详解 ,技术问题可以直接咨询课程助教。
智能合约开发与部署
首先安装开发用以太坊节点软件Ganache: ~$ npm install -g ganache-cli
然后安装以太坊开发框架Truffle: ~$ npm install -g truffle
现在创建一个项目目录,进入该目录,并执行 truffle init 进行初始化: ~$ mkdir demo && cd hubwiz ~/hubwiz$ truffle init
truffle会创建一些新的文件夹:contract、test、migration等。在contract文件夹中,创建一个新的合约文件Vote.sol: ~/hubwiz/contracts$ touch Vote.sol
按如下内容编辑Vote.sol,这个合约只是简单地跟踪两个候选人的得票数,它使用交易发起账户作为投票人,并且每个账户只能投一票: pragma solidity ^0.4.16; contract Vote { uint public candidate1; uint public candidate2; mapping (address => bool) public voted; function castVote(uint candidate) public { require(!voted[msg.sender] && (candidate == 1 || candidate == 2)); if(candidate == 1){ candidate1++; }else{ candidate2++; } voted[msg.sender] = true; } }
接下来在migration文件夹创建一个新的js文件2_vote.js,内容如下: var vote = artifacts.require("Vote"); module.exports = function(deployer) { // deployment steps deployer.deploy(vote); };
然后打开项目文件夹下的truffle.js,用以下内容替换: module.exports = { networks: { ganache: { host: "127.0.0.1", port: 7545, network_id: "*" // Match any network id } } };
现在打开一个终端,启动ganache: ~$ ganache-cli
然后打开另一个终端,用truffle部署合约: ~/hubwiz$ truffle deploy --reset --network ganache
你会看到终端输出类似下面的合约地址,拷贝下来,后面还要用到: Vote: 0xe4e47451aad6c89a6d9e4ad104a7b77ffe1d3b36
.Net应用开发与智能合约访问
创建一个新的控制台项目,添加对如下开发包的依赖: Nethereum.Web3 Nethereum.Contracts
然后按如下内容修改program.cs: using System; using System.Numerics; using System.Threading.Tasks; using Nethereum.Contracts; using Nethereum.Hex.HexTypes; using Nethereum.Web3; namespace console { class Program { static void Main(string[] args) { //The URL endpoint for the blockchain network. string url = "HTTP://localhost:7545"; //The contract address:合约部署的地址 string address = "0x345cA3e014Aaf5dcA488057592ee47305D9B3e10"; //The ABI for the contract. string ABI = @"[{'constant':true,'inputs':[],'name':'candidate1','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':false,'inputs':[{'name':'candidate','type':'uint256'}],'name':'castVote','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function'},{'constant':true,'inputs':[],'name':'candidate2','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':true,'inputs':[{'name':'','type':'address'}],'name':'voted','outputs':[{'name':'','type':'bool'}],'payable':false,'stateMutability':'view','type':'function'}]"; //Creates the connecto to the network and gets an instance of the contract. Web3 web3 = new Web3(url); Contract voteContract = web3.Eth.GetContract(ABI, address); //Reads the vote count for Candidate 1 and Candidate 2 Task candidate1Function = voteContract.GetFunction("candidate1").CallAsync(); candidate1Function.Wait(); int candidate1 = (int)candidate1Function.Result; Task candidate2Function = voteContract.GetFunction("candidate2").CallAsync(); candidate2Function.Wait(); int candidate2 = (int)candidate2Function.Result; Console.WriteLine("Candidate 1 votes: {0}", candidate1); Console.WriteLine("Candidate 2 votes: {0}", candidate2); //Prompts for the account address. Console.Write("Enter the address of your account: "); string accountAddress = Console.ReadLine(); //Prompts for the users vote. int vote = 0; Console.Write("Press 1 to vote for candidate 1, Press 2 to vote for candidate 2: "); Int32.TryParse(Convert.ToChar(Console.Read()).ToString(), out vote); Console.WriteLine("You pressed {0}", vote); //Executes the vote on the contract. try{ HexBigInteger gas = new HexBigInteger(new BigInteger(400000)); HexBigInteger value = new HexBigInteger(new BigInteger(0)); Task castVoteFunction = voteContract.GetFunction("castVote").SendTransactionAsync(accountAddress, gas, value, vote); castVoteFunction.Wait(); Console.WriteLine("Vote Cast!"); }catch(Exception e){ Console.WriteLine("Error: {0}", e.Message); } } } }
别忘了用你自己部署的合约地址修改上面代码中的合约地址。现在运行应用,就可以投票了!
用Nethereum很容易就可以为.Net应用添加访问以太坊智能合约的能力,由于Nethereum基于.NET平台,因此它可以用于.NET Core应用、.NET Standard应用、Xamarin以及各种windows应用中。
原文链接: Nethereum:.NET应用和以太坊智能合约的桥梁 - 汇智网
区块链
2019-01-06 13:55:01
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
在开发链上部署测试链码helloworld 利用 hyperledger/fabric-samples 进行部署 克隆 hyperledger/fabric-samples git clone https://github.com/hyperledger/fabric-samples.git 将链码文件夹 helloworld 复制到 fabric-samples/chaincode 下 到 fabric-samples 下 cd chaincode-docker-devmode 在 chaincode-docker-devmode 下打开三个终端 终端1-启动网络 docker-compose -f docker-compose-simple.yaml up 终端2-构建并启动链码 进入容器 docker exec -it chaincode bash 到链码目录编译代码 cd helloworld go build 运行链码 CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./helloworld 日志 2018-08-25 03:58:31.237 UTC [shim] SetupChaincodeLogging -> INFO 001 Chaincode log level not provided; defaulting to: INFO 2018-08-25 03:58:31.237 UTC [shim] SetupChaincodeLogging -> INFO 002 Chaincode (build level: ) starting up ... 终端3-使用链码 进入容器 docker exec -it cli bash 节点安装链码 peer chaincode install -p chaincodedev/chaincode/helloworld -n mycc -v 0 节点实例化链码 peer chaincode instantiate -n mycc -v 0 -c '{"Args":["hi","jonluo"]}' -C myc 验证 peer chaincode query -n mycc -c '{"Args":["get","hi"]}' -C myc peer chaincode invoke -n mycc -c '{"Args":["set", "hello", "world"]}' -C myc peer chaincode query -n mycc -c '{"Args":["get","hello"]}' -C myc 完成
区块链
2019-01-09 09:48:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> 本文作者为万向区块链CTO罗荣阁。
目录
1. CentOS 环境准备
1.1. 使用rpm 安装devtoolset-7
1.2. 使用rpm 安装dos2unix
1.3. 准备Platon代码
1.4. 确保build脚本正常
1.5. 准备mpclib
1.6. 编译Platon
1.7. 重新编译前的清理工作
2. 初始化和运行Platon
2.1. Platon节点初始化
2.1.1. 生成 account 和 key pair
2.1.2. 配置初始化文件
2.1.3. 初始化Platon
2.2. 启动 Platon 节点
2.3. platon help 信息
2.4. 重新初始化Platon节点
3. CentOS升级gcc原始步骤
3.1. 安装CentOS-release-scl
3.2. 使用yum 安装devtoolset-7
3.3. 编译获得静态库libstdc++.so.6

Platon在CentOS上编译部署
PlatON官网上主要支持在 Ubuntu 和 Windows 环境中编译部署,但是也会有在CentOS上编译部署的需要。本文主要介绍了在CentOS上的环境准备、编译生成可执行文件和运行节点程序的过程。PlatON 官方代码库更新速度较快,有可能官方代码做出了一些设置变化,如果有步骤不能正确执行,可以参考 PlatON 官网具体信息。

1. CentOS 环境准备
Ubuntu在社区中很流行,但CentOS在企业级市场中占有较大优势。目前,CentOS在AWS、阿里云、UCloud 云服务商中能够使用的最高官方版本是CentOS 7.5。
本文就在CentOS 7.5下编译部署PlatON。

1.1. 使用rpm 安装devtoolset-7
因为Platon的WASM库和MPC库依赖,开发和编译环境需要支持C++14。GCC 6.1版本以上是默认支持C++14。 https://www.gnu.org/software/gcc/projects/cxx-status.html#cxx14
CentOS 7.5的默认GCC版本为4.8.5,开发和编译Platon需要升级GCC。Redhat官方的升级方法是通过devtoolset。 2018年1月,devtoolset 6 发布。 2018年5月,CentOS 7.5 发布。 2018年9月,devtoolset 7 发布。
https://access.redhat.com/solutions/19458
http://mirror.centos.org/centos/7/sclo/x86_64/rh/devtoolset-7/
https://www.softwarecollections.org/en/scls/rhscl/devtoolset-7/
考虑以上的发布时间顺序、相互具体版本要求,选择在CentOS 7.5中安装devtoolset 7。
将以下33个rpm拷贝到一个目录中,再执行: $ sudo rpm -ivh boost-date-time-1.53.0-27.el7.x86_64.rpm efivar-libs-31-4.el7.x86_64.rpm kernel-debug-devel-3.10.0-862.el7.x86_64.rpm libgfortran4-7.2.1-1.1.1.el7.x86_64.rpm libquadmath-4.8.5-28.el7.x86_64.rpm mokutil-12-1.el7.centos.x86_64.rpm scl-utils-20130529-18.el7_4.x86_64.rpm devtoolset-7-7.1-4.el7.x86_64.rpm devtoolset-7-binutils-2.28-11.el7.x86_64.rpm devtoolset-7-dwz-0.12-1.1.el7.x86_64.rpm devtoolset-7-dyninst-9.3.2-3.el7.x86_64.rpm devtoolset-7-elfutils-0.170-5.el7.x86_64.rpm devtoolset-7-elfutils-libelf-0.170-5.el7.x86_64.rpm devtoolset-7-elfutils-libs-0.170-5.el7.x86_64.rpm devtoolset-7-gcc-7.3.1-5.13.el7.x86_64.rpm devtoolset-7-gcc-c++-7.3.1-5.13.el7.x86_64.rpm devtoolset-7-gcc-gfortran-7.3.1-5.13.el7.x86_64.rpm devtoolset-7-gdb-8.0.1-36.el7.x86_64.rpm devtoolset-7-libquadmath-devel-7.3.1-5.13.el7.x86_64.rpm devtoolset-7-libstdc++-devel-7.3.1-5.13.el7.x86_64.rpm devtoolset-7-ltrace-0.7.91-2.el7.x86_64.rpm devtoolset-7-make-4.2.1-3.el7.x86_64.rpm devtoolset-7-memstomp-0.1.5-5.1.el7.x86_64.rpm devtoolset-7-oprofile-1.2.0-2.el7.1.x86_64.rpm devtoolset-7-perftools-7.1-4.el7.x86_64.rpm devtoolset-7-runtime-7.1-4.el7.x86_64.rpm devtoolset-7-strace-4.17-7.el7.x86_64.rpm devtoolset-7-systemtap-3.1-4s.el7.x86_64.rpm devtoolset-7-systemtap-client-3.1-4s.el7.x86_64.rpm devtoolset-7-systemtap-devel-3.1-4s.el7.x86_64.rpm devtoolset-7-systemtap-runtime-3.1-4s.el7.x86_64.rpm devtoolset-7-toolchain-7.1-4.el7.x86_64.rpm devtoolset-7-valgrind-3.13.0-11.el7.x86_64.rpm

1.2. 使用rpm 安装dos2unix $ sudo rpm -ivh dos2unix-6.0.3-7.el7.x86_64.rpm

1.3. 准备Platon代码
Platon git仓库代码 $ go get github.com/PlatONnetwork/PlatON-Go
更新代码 $ go get -u github.com/PlatONnetwork/PlatON-Go

1.4. 确保build脚本正常 $ cd build $ dos2unix *.sh $ chmod 755 *.sh

1.5. 准备mpclib
下载地址 https://download.platon.network/mpclib.tar.gz $ tar xf mpclib.tar.gz $ mv mpclib $GOPATH/src/github.com/PlatONnetwork/PlatON-Go/

1.6. 编译Platon
每次进bash需要手动切换GCC版本到 7.3.1 $ scl enable devtoolset-7 bash
或者直接设置在环境配置中,这样每次打开bash默认是GCC 7.3.1 $ vi ~/.bashrc source scl_source enable devtoolset-7
添加mpclib中的依赖包 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GOPATH/src/github.com/PlatONnetwork/PlatON-Go/mpclib $ echo $LD_LIBRARY_PATH /opt/rh/devtoolset-7/root/usr/lib64:/opt/rh/devtoolset-7/root/usr/lib:/opt/rh/devtoolset-7/root/usr/lib64/dyninst:/opt/rh/devtoolset-7/root/usr/lib/dyninst:/opt/rh/devtoolset-7/root/usr/lib64:/opt/rh/devtoolset-7/root/usr/lib:/home/wxuser/work/golang/src/github.com/PlatONnetwork/PlatON-Go/mpclib $ cd PlatON-Go/ 带mpc编译 $ make platon-with-mpc > ~/temp/make_platon.txt $ make all-with-mpc > ~/temp/make_all.txt
编译后生成的可执行程序在 build/bin/ 中。
将生成的可执行程序拷贝到节点启动目录 $ cd build $ cp -R bin/ ~/platon-node

1.7. 重新编译前的清理工作 $ make clean $ rm -rf build/_workspace/*

2. 初始化和运行Platon
2.1. Platon节点初始化
2.1.1. 生成 account 和 key pair $ ./platon --datadir ./data account new INFO [01-09|17:25:14.269] Maximum peer count ETH=50 LES=0 total=50 Your new account is locked with a password. Please give a password. Do not forget this password. Passphrase: Repeat passphrase: Address: {60208c048e7eb8e38b0fac40406b819ce95aa7af}
本次操作密码设成了“0”。 $ ll data/keystore/ -rw------- 1 wxuser wxuser 491 Jan 9 17:25 UTC--2019-01-09T09-25-28.487164507Z--60208c048e7eb8e38b0fac40406b819ce95aa7af $ ./ethkey genkeypair Address : 0xC71433b47f1b0053f935AEf64758153B24cE7445 PrivateKey: b428720a89d003a1b393c642e6e32713dd6a6f82fe4098b9e3a90eb38e23b6bb PublicKey : 68bb049008c7226de3188b6376127354507e1b1e553a2a8b988bb99b33c4d995e426596fc70ce12f7744100bc69c5f0bce748bc298bf8f0d0de1f5929850b5f4
将节点私钥存储在 ./data/platon/nodekey中,私钥来自上一步PrivateKey。 $ mkdir -p ./data/platon $ echo "b428720a89d003a1b393c642e6e32713dd6a6f82fe4098b9e3a90eb38e23b6bb" > ./data/platon/nodekey $ cat ./data/platon/nodekey b428720a89d003a1b393c642e6e32713dd6a6f82fe4098b9e3a90eb38e23b6bb

2.1.2. 配置初始化文件
将initialNodes改为节点公钥,alloc为账户地址分配金额。 $ vi genesis.json { "config": { "chainId": 300, "homesteadBlock": 1, "eip150Block": 2, "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip155Block": 3, "eip158Block": 3, "byzantiumBlock": 4, "cbft": { "initialNodes": ["enode://68bb049008c7226de3188b6376127354507e1b1e553a2a8b988bb99b33c4d995e426596fc70ce12f7744100bc69c5f0bce748bc298bf8f0d0de1f5929850b5f4@127.0.0.1:16789"] } }, "nonce": "0x0", "timestamp": "0x5c074288", "extraData": "0x00000000000000000000000000000000000000000000000000000000000000007a9ff113afc63a33d11de571a679f914983a085d1e08972dcb449a02319c1661b931b1962bce02dfc6583885512702952b57bba0e307d4ad66668c5fc48a45dfeed85a7e41f0bdee047063066eae02910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x47b77760", "difficulty": "0x40000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x60208c048e7eb8e38b0fac40406b819ce95aa7af", "alloc": { "0x60208c048e7eb8e38b0fac40406b819ce95aa7af": { "balance": "999000000000000000000" } }, "number": "0x0", "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }

2.1.3. 初始化Platon $ ./platon --datadir ./data init genesis.json INFO [01-09|17:31:58.832] Maximum peer count ETH=50 LES=0 total=50 INFO [01-09|17:31:58.833] Allocated cache and file handles database=/home/wxuser/manual-Platon/build/bin/data/platon/chaindata cache=16 handles=16 INFO [01-09|17:31:58.839] Writing custom genesis block INFO [01-09|17:31:58.840] Persisted trie from memory database nodes=1 size=150.00B time=34.546µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [01-09|17:31:58.840] Successfully wrote genesis state database=chaindata hash=4fe06b…382a26 INFO [01-09|17:31:58.840] Allocated cache and file handles database=/home/wxuser/manual-Platon/build/bin/data/platon/lightchaindata cache=16 handles=16 INFO [01-09|17:31:58.848] Writing custom genesis block INFO [01-09|17:31:58.848] Persisted trie from memory database nodes=1 size=150.00B time=238.177µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [01-09|17:31:58.848] Successfully wrote genesis state database=lightchaindata hash=4fe06b…382a26

2.2. 启动 Platon 节点 $ ./platon --identity "node1" --rpc --rpcaddr 0.0.0.0 --datadir ./data --rpcapi "db,eth,net,web3,admin,personal,miner" --networkid 300 --mine --verbosity 3 --miner.etherbase 0x60208c048e7eb8e38b0fac40406b819ce95aa7af INFO [01-09|17:42:01.165] Maximum peer count ETH=50 LES=0 total=50 INFO [01-09|17:42:01.166] Starting peer-to-peer node instance=Geth/node1/v1.8.16-stable-7ee6fe39/linux-amd64/go1.11.4 INFO [01-09|17:42:01.166] Allocated cache and file handles database=/home/wxuser/manual-Platon/build/bin/data/platon/chaindata cache=768 handles=512 INFO [01-09|17:42:01.183] Initialised chain configuration config="{ChainID: 300 Homestead: 1 DAO: DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: 4 Constantinople: Engine: &{0 0 0 0 0 [{127.0.0.1 16789 16789 68bb049008c7226de3188b6376127354507e1b1e553a2a8b988bb99b33c4d995e426596fc70ce12f7744100bc69c5f0bce748bc298bf8f0d0de1f5929850b5f4 [149 178 250 27 246 47 49 86 100 108 50 3 199 20 51 180 127 27 0 83 249 53 174 246 71 88 21 59 36 206 116 69] {0 0 }}] 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }}" INFO [01-09|17:42:01.183] Initialising Ethereum protocol versions="[63 62]" network=300 INFO [01-09|17:42:01.184] Loaded most recent local header number=0 hash=4fe06b…382a26 age=1mo5d6h INFO [01-09|17:42:01.184] Loaded most recent local full block number=0 hash=4fe06b…382a26 age=1mo5d6h INFO [01-09|17:42:01.184] Loaded most recent local fast block number=0 hash=4fe06b…382a26 age=1mo5d6h INFO [01-09|17:42:01.184] Read the StateDB instance from the cache map sealHash=bbbae7…30dbfb INFO [01-09|17:42:01.184] Loaded local transaction journal transactions=0 dropped=0 INFO [01-09|17:42:01.185] Regenerated local transaction journal transactions=0 accounts=0 INFO [01-09|17:42:01.185] Loaded local mpc transaction journal mpc transactions=0 dropped=0 INFO [01-09|17:42:01.185] Init mpc processor success osType=linux icepath= httpEndpoint=http://127.0.0.1:6789 INFO [01-09|17:42:01.185] commitDuration commitDuration=950.000 INFO [01-09|17:42:01.185] Set the block time at the end of the last round of consensus startTimeOfEpoch=1543979656 INFO [01-09|17:42:01.185] Starting P2P networking INFO [01-09|17:42:03.298] UDP listener up self=enode://aa18a88c1463c1f1026c6cb0b781027d898d19ed9c11b10ad7a3a9ee2d0c09ab607d9b24bc4580bd816c0194215461cd88bf65955e0d87cf69e0157d464c582b@[::]:16789 INFO [01-09|17:42:03.299] Transaction pool price threshold updated price=1000000000 INFO [01-09|17:42:03.300] IPC endpoint opened url=/home/wxuser/manual-Platon/build/bin/data/platon.ipc INFO [01-09|17:42:03.300] RLPx listener up self=enode://aa18a88c1463c1f1026c6cb0b781027d898d19ed9c11b10ad7a3a9ee2d0c09ab607d9b24bc4580bd816c0194215461cd88bf65955e0d87cf69e0157d464c582b@[::]:16789 INFO [01-09|17:42:03.300] HTTP endpoint opened url=http://0.0.0.0:6789 cors= vhosts=localhost INFO [01-09|17:42:03.300] Transaction pool price threshold updated price=1000000000

2.3. platon help 信息 $ ./platon --help

2.4. 重新初始化Platon节点
确保Platon进程已经被杀死,再删除data目录。 $ cd build/bin $ rm -rf data/platon
然后可以再重新初始化。

3. CentOS升级gcc原始步骤
CentOS 7.5升级GCC的原始步骤。

3.1. 安装CentOS-release-scl $ sudo yum install centos-release-scl ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: centos-release-scl noarch 2-2.el7.centos extras 12 k Installing for dependencies: centos-release-scl-rh noarch 2-2.el7.centos extras 12 k Transaction Summary ================================================================================ Install 1 Package (+1 Dependent package) Total download size: 24 k Installed size: 39 k

3.2. 使用yum 安装devtoolset-7 $ sudo yum install devtoolset-7 ============================================================================== Package Arch Version Repository Size ============================================================================== Installing: devtoolset-7 x86_64 7.1-4.el7 centos-sclo-rh 6.2 k Installing for dependencies: boost-date-time x86_64 1.53.0-27.el7 CentOS-7_Local 52 k devtoolset-7-binutils x86_64 2.28-11.el7 centos-sclo-rh 5.3 M devtoolset-7-dwz x86_64 0.12-1.1.el7 centos-sclo-rh 99 k devtoolset-7-dyninst x86_64 9.3.2-3.el7 centos-sclo-rh 3.6 M devtoolset-7-elfutils x86_64 0.170-5.el7 centos-sclo-rh 390 k devtoolset-7-elfutils-libelf x86_64 0.170-5.el7 centos-sclo-rh 194 k devtoolset-7-elfutils-libs x86_64 0.170-5.el7 centos-sclo-rh 280 k devtoolset-7-gcc x86_64 7.3.1-5.13.el7 centos-sclo-rh 29 M devtoolset-7-gcc-c++ x86_64 7.3.1-5.13.el7 centos-sclo-rh 11 M devtoolset-7-gcc-gfortran x86_64 7.3.1-5.13.el7 centos-sclo-rh 11 M devtoolset-7-gdb x86_64 8.0.1-36.el7 centos-sclo-rh 3.2 M devtoolset-7-libquadmath-devel x86_64 7.3.1-5.13.el7 centos-sclo-rh 154 k devtoolset-7-libstdc++-devel x86_64 7.3.1-5.13.el7 centos-sclo-rh 2.6 M devtoolset-7-ltrace x86_64 0.7.91-2.el7 centos-sclo-rh 148 k devtoolset-7-make x86_64 1:4.2.1-3.el7 centos-sclo-rh 485 k devtoolset-7-memstomp x86_64 0.1.5-5.1.el7 centos-sclo-rh 442 k devtoolset-7-oprofile x86_64 1.2.0-2.el7.1 centos-sclo-rh 1.8 M devtoolset-7-perftools x86_64 7.1-4.el7 centos-sclo-rh 3.6 k devtoolset-7-runtime x86_64 7.1-4.el7 centos-sclo-rh 20 k devtoolset-7-strace x86_64 4.17-7.el7 centos-sclo-rh 558 k devtoolset-7-systemtap x86_64 3.1-4s.el7 centos-sclo-rh 141 k devtoolset-7-systemtap-client x86_64 3.1-4s.el7 centos-sclo-rh 2.1 M devtoolset-7-systemtap-devel x86_64 3.1-4s.el7 centos-sclo-rh 2.1 M devtoolset-7-systemtap-runtime x86_64 3.1-4s.el7 centos-sclo-rh 405 k devtoolset-7-toolchain x86_64 7.1-4.el7 centos-sclo-rh 3.8 k devtoolset-7-valgrind x86_64 1:3.13.0-11.el7 centos-sclo-rh 7.6 M efivar-libs x86_64 31-4.el7 CentOS-7_Local 68 k kernel-debug-devel x86_64 3.10.0-862.el7 CentOS-7_Local 16 M libgfortran4 x86_64 7.2.1-1.1.1.el7 CentOS-7_Local 676 k libquadmath x86_64 4.8.5-28.el7 CentOS-7_Local 188 k mokutil x86_64 12-1.el7.centos CentOS-7_Local 41 k scl-utils x86_64 20130529-18.el7_4 CentOS-7_Local 24 k Transaction Summary ============================================================================== Install 1 Package (+32 Dependent packages) Total download size: 100 M Installed size: 289 M

3.3. 编译获得静态库libstdc++.so.6
通过devtoolset 7升级GCC,并不会得到静态库: libstdc++.so.6.0.24。可以在“另一个”CentOS 7.5环境中,编译gcc 7.3.0得到这个文件。
http://www.netgull.com/gcc/releases/gcc-7.3.0/gcc-7.3.0.tar.gz
ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2 ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.16.1.tar.bz2 $ tar xvf gcc-7.3.0.tar.gz $ cd gcc-7.3.0 $ ./contrib/download_prerequisites
说明:如果脚本无法成功通过ftp下载文件,就手动下载以上4个压缩包,放到 gcc-7.3.0/中,再执行这个脚本,解压缩并建立link。 $ mkdir build $ cd build $ ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
说明: --enable-checking=release //增加一些检查,也可以–disable-checking生成的编译器在编译过程中不做检查; --enable-languages=c,c++ //让gcc支持的编程语言 ; --disable-multilib //取消多目标库编译(取消32位库编译)。 $ make
libstdc++.so.6.0.24 在 build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.24 中。如果需要,可以把它拷贝到另外一个Linux的 /opt/rh/devtoolset-7/root/lib64/ 中。(目前不需要) $ sudo mv libstdc++.so.6.0.24 /opt/rh/devtoolset-7/root/lib64/ $ cd /opt/rh/devtoolset-7/root/lib64/ $ sudo chown root.root libstdc++.so.6.0.24 $ sudo chmod 755 libstdc++.so.6.0.24 $ sudo ln -s libstdc++.so.6.0.24 libstdc++.so.6

作者简介:
上海万向区块链股份公司CTO,产品和研发团队负责人,ISO TC307 区块链国际标准本体论项目负责人。拥有15 年的IT 技术规划及管理方面的从业经历,曾在中国证监会直属的证券期货交易所负责技术系统规划工作,长期与纳斯达克交易所、纽约证券交易所、泛欧交易所等国际领先交易所集团共同开展技术项目,与欧美技术架构师进行过深入合作交流,具有深厚的金融技术背景和全球化视野,撰写的论文还曾获评证监会优秀论文。在区块链前沿技术及其在金融行业应用方面具有很强的研究能力。
区块链
2019-01-23 15:08:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
为了帮助大家了解NEO平台上技术社区的开发进展,NEONewsToday将每月发布一份值得关注的更新报告。这些报告将包括对NEO核心项目的贡献以及对社区创建项目的改进。
这个报告不是包括所有项目进展的详细清单。NEONewsToday将从尽可能多的社区贡献者中收集信息,但并不能完全包含所有社区项目内容。
任何对NEO基础设施或开发工具做出重大贡献的NEO开发者(无论是开发社区的成员还是其他人),都可以通过wakeup@neonewstoday.com与NEONews Today 联系,并提供相关信息以供将来报告使用。
NEO协议贡献
Neo-cli(NR)
自10月24日以来,NeoResearch成员Igor和Vitor Coelho一直致力于一项旨在优化NEO共识机制的重大更新。该提案中还看到了CoZ和NGD成员的贡献和评论。 https://github.com/neo-project/neo/pull/426
此项更新的第一部分由PR #426涵盖,重点介绍如何添加“提交”阶段的共识,以防止“分叉”问题(移植到与Akka模型兼容的地方),以及更新策略和其他性能优化。再生策略的目的是允许丢失/失败的共识节点自动重新与网络连接,无需重新启动。 https://github.com/neo-project/neo/pull/422
初步的修改已经完成,目前正在接受NeoResearch、NGD和CoZ的测试。在不久的将来,新的具有这些改进的Neo-cli版本将被应用到测试网络共识节点中。
社区项目
Neon Wallet (CoZ)
11月发布了Neon Wallet v2,对原有的Neon Wallet进行了全面的设计改进。本月进行了大量更改,包括实现了新功能,如NEP-9 QR生成、节点选择以及简单可转换的转移和Token销售优先费用。 https://neonewstoday.com/general/city-of-zion-releases-neon-wallet-v2-featuring-complete-design-overhaul/
第一周是修复新特性和其他各种日常bug的修复 https://github.com/CityOfZion/neon-wallet/pull/1645 ,例如将接收转移的最大数量从10个增加到25个 https://github.com/CityOfZion/neon-wallet/pull/1655 。Neon Wallet是去中心化的,已经不存在对其他项目的依赖 https://github.com/CityOfZion/neon-wallet/pull/1648 。其中一个例子就是Neoscan的自动节点选择,它被直接内置在Neon钱包中的自动节点选择算法所取代。 https://github.com/CityOfZion/neon-wallet/pull/1663
第一周,钱包的下载量就超过了15k。目前的短期目标包括处理小Bug、对测试的改进以及考虑替代定价数据API。该团队还开始计划对本地网络或手动节点地址输入、多团体钱包和改进的用户体验/用户界面的GAS索赔的支持。
在最后一周,有20多个问题得到了解决,测试覆盖率和节点选择算法也得到了进一步的改进 https://github.com/CityOfZion/neon-wallet/pull/1727 。这将继续作为之后的核心关注点,因为该团队为第一次重大更新(即v2.0.1)打下了坚实的基础。
neo-local (CoZ)
11月的大部分开发都花在了改进和更新命令行界面(CLI)上 https://github.com/CityOfZion/neo-local/pull/102 。 最初的改进之一是添加了destroy命令,允许根据需要停止和删除服务容器。 新的本地版本0.11.1于11月6日星期二发布。 https://github.com/CityOfZion/neo-local/releases/tag/0.11.1
从12日星期一开始的第二周,PrivateNet容器 https://github.com/CityOfZion/neo-local/pull/104 、新python https://github.com/CityOfZion/neo-local/pull/109 和通知服务器服务 https://github.com/CityOfZion/neo-local/pull/108 被添加到CLI。通过改进CLI,可以简化对CLI的理解,并建立用于开发的NEO私有链。
从19日星期一开始的下一周,CLI中添加了neo-scan-sync https://github.com/CityOfZion/neo-local/pull/118 和neo-scan-api容器 https://github.com/CityOfZion/neo-local/pull/119 ,同时还添加了其他改进,如引导链的能力 https://github.com/CityOfZion/neo-local/pull/115 。CLI启动了特性工作,目的是使其具有上下文智能;这意味着它知道哪些服务相互依赖,以便以正确的顺序启动它们 https://github.com/CityOfZion/neo-local/pull/117 。
11月的最后一周,CLI功能得到了改进,这些功能在项目的早期阶段得到了快速开发 https://github.com/CityOfZion/neo-local/pull/124 。这些更改包括增加配置的灵活性,以及支持在任何操作系统上加载配置。改进还提供了进度条和其他信息,以帮助用户知道下载需要多长时间。 https://github.com/CityOfZion/neo-local/pull/125
近期欧洲黑客马拉松(鹿特丹,柏林和苏黎世)也使用了NEO本地项目 https://github.com/CityOfZion/neo-local 。该团队报告称,已经收到了很多关于如何在未来改进项目的有用反馈。
neo-python (CoZ)
虽然neo-python节点在正常网络活动期间通常没有问题,但增加的使用/滥用行为可能导致neo-python节点卡住,需要重新启动。 neo-python团队已经投入时间分析此行为并更新网络代码以提高这些节点的整体弹性。
bootstrapping进程也得到了改进,在这之前需要用户更新protocol.xxx.json文件中的bootstrap链接。该文件现在将自动查找最新版本 https://github.com/CityOfZion/neo-python/pull/705 ,因此用户无需进行手动修改。主网和测试网引导程序文件已更新,分别阻止高度3002xxx和2022xxx。
更新后的实现能够通过在neo-python设置中指定路径来交换组件类 https://github.com/CityOfZion/neo-python/pull/719 。虽然目前只支持RPC和REST服务器,但团队打算将其扩展为包括CLI命令,网络和数据库。最终,该团队希望允许用户创建可以通过pip包管理器安装的自我维护插件,然后通过更改protocol.xxx.json来激活。
在向JSON-RPC服务器添加GET和OPTIONS请求功能之后,neo-python项目正在接入与neo-cli的功能奇偶校验 https://github.com/CityOfZion/neo-python/pull/712 。在更新之后,使用neo-python的RPC节点将通过GET请求进行查询。
neo-tools (CoZ)
Neo-tools是一个更近期的项目,由City of Zion 的开发者Fetter带头发起 https://github.com/CityOfZion/neo-tools 。 现采用CLI的形式,旨在将所有NEO API、示例和项目原语集中到一个位置,以便开发人员可以在简单的类Unix环境中轻松访问它们。
Fetter从包含基本参考API实现和服务的初始构建开始。其中包括Neoscan,neon-js,Binance,Coinmarketcap和CoinPaprika的CLI。 根据这些内容,Fetter优先考虑被动地添加开发者社区需求最多或者其他成员所需的工具。
在短期内,neo-tools的更新将侧重于一致性和代码模块化,但可以期待Fetter意图包纳所有NEO服务,包括RPC和REST API,钱包服务和区块链元数据分析/转换实用程序。
NeoCompiler Eco (NR)
NeoCompiler Eco是一个智能合约开发平台 https://neocompiler.io/#/ ,由NeoResearch团队创建 https://neonewstoday.com/general/introducing-vitor-and-igor-coelho-of-neoresearch/ ,该平台允许他们使用基于Linux的系统编译NEO合同。 NeoCompiler Eco可通过Web浏览器或移动设备访问,可帮助开发人员构建,测试甚至部署使用C#,Java,Python和Go编写的智能合约。编译器在共享的私有测试网络上运行,每12小时重置一次,允许任何人在部署到主网之前测试他们的合约。
NeoResearch目前专注于实施共识绘制工具 https://github.com/NeoResearch/consensus-draw ,该工具旨在跟踪共识数据并以人类易于理解的格式呈现。该工具的实施还可以帮助调试NEO共识的所有潜在问题。
Smart Account Composer (NR)
Smart Account Composer/Smacco是另一个NeoResearch项目 https://neoresearch.io/smacco/#/ ,允许创建具有附加功能的NEO地址。Smacco不是生成具有基本发送/接收功能的典型公钥/私钥对,而是允许用户使用特定规则创建验证合同。
这些基于逻辑的条件可以以多种方式使用,例如用于创建需要多个私钥解锁的钱包,或者锁定时间戳后面的特定动作。它还可用于允许特定私钥使用某些操作,例如发送特定令牌,而无需完全控制帐户。
与NeoCompiler Eco一样,用户可操作性是Smacco的重中之重。为了便于理解这些规则描述的逻辑流程,使用该工具创建的任何智能帐户都伴随着自动生成的逻辑图。无论技术熟练程度如何,这些图表都易于被任何人理解。
原文: https://neonewstoday.com/development/november-community-development-summary/
区块链
2018-12-19 14:21:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文集汇总了EOS区块链常见错误代码及其含义,完整错误代码集请查看 EOS错误代码集 - 汇智网
EOS错误代码列表如下,
错误代码错误信息中文含义
3000000blockchain exception区块链异常
3010000chain type exception链类型异常
3010001Invalid name无效的名称
3010002Invalid public key无效的公钥
3010003Invalid private key无效的私钥
3010004Invalid authority无效的授权
3010005Invalid action无效的动作
3010006Invalid transaction无效的交易
3010007Invalid ABI无效的ABI
3010008Invalid block ID无效的区块ID
3010009Invalid transaction ID无效的交易ID
3010010Invalid packed transaction无效的打包交易
3010011Invalid asset无效的资产
3010012Invalid chain ID无效的链ID
3010013Invalid fixed key无效的固定密钥
3010014Invalid symbol无效的代币符号
3015000ABI exceptionABI异常
3015001No ABI found没有找到ABI
3015002Invalid Ricardian Clause无效的李嘉图语句
3015003Invalid Ricardian Action无效的李嘉图动作
3015004The type defined in the ABI is invalidABI中定义的类型无效
3015005Duplicate type definition in the ABIABI中存在重复定义的类型
3015006Duplicate struct definition in the ABIABI中存在重复定义的结构
3015007Duplicate action definition in the ABIABI中存在重复定义的动作
3015008Duplicate table definition in the ABIABI中存在重复定义的数据表
3015009Duplicate error message definition in the ABIABI中存在重复定义的错误信息
3015010ABI serialization time has exceeded the deadlineABI序列化时间超过截止值
3015011ABI recursive definition has exceeded the max recursion depthABI中的递归定义超过最大允许深度
3015012Circular definition is detected in the ABIABI中检测到循环定义
3015013Unpack data exception解包数据发生异常
3015014Pack data exception打包数据发生异常
3015015Duplicate variant definition in the ABIABI中存在重复定义的变量
3015016ABI has an unsupported version不支持的ABI版本
3020000Fork database exception分叉数据库异常
3020001Block can not be found找不到区块
3030000Block exception区块异常
3030001Unlinkable block无法链接的区块
3030002Transaction outputs in block do not match transaction outputs from applying block指定区块与待应用区块中的交易输出不匹配
3030003Block does not guarantee concurrent execution without conflicts区块不能保证无冲突并发执行
3030004Shard locks in block are incorrect or mal-formed区块的分片锁不正确或格式错误
3030005Block exhausted allowed resources区块已耗尽许可的资源
3030006Block is too old to push区块太陈旧,无法提交
3030007Block is from the future区块时间过早
3030008Block is not signed with expected key区块签名与密钥不一致
3030009Block is not signed by expected producer区块签名与出块人不一致
3040000Transaction exception交易异常
3040001Error decompressing transaction解压交易失败
3040002Transaction should have at least one normal action交易至少应当包含一个常规动作
3040003Transaction should have at least one required authority交易至少应当包含一个授权
3040004Context-free action should have no required authority上下文无关动作不应当包含授权
3040005Expired Transaction超时的交易
3040006Transaction Expiration Too Far交易超时过久
3040007Invalid Reference Block无效的参考块
3040008Duplicate transaction重复的交易
3040009Duplicate deferred transaction重复的延迟交易
3040010Context free action is not allowed inside generated transaction在生成的交易中不允许出现上下文无关动作
3040011The transaction can not be found交易找不到
3040012Pushing too many transactions at once同时提交过多的交易
3040013Transaction is too big交易过大
3040014Unknown transaction compression未知的交易压缩方式
3050000Action validate exception动作验证异常
3050001Account name already exists账号名已经存在
3050002Invalid Action Arguments无效的动作参数
3050003eosio_assert_message assertion failure消息条件验证失败
3050004eosio_assert_code assertion failure代码条件验证失败
3050005Action can not be found找不到动作
3050006Mismatch between action data and its struct动作数据和结构定义不匹配
3050007Attempt to use unaccessible API试图访问不许可的API
3050008Abort Called中止被调用
3050009Inline Action exceeds maximum size limit内联动作超过允许的最大尺寸
3060000Database exception数据库异常
3060001Permission Query Exception许可查询异常
3060002Account Query Exception账号查询异常
3060003Contract Table Query Exception合约数据表查询异常
3060004Contract Query Exception合约查询异常
3060100Guard Exception保护性异常
3060101Database usage is at unsafe levels数据库利用处于不安全等级
3060102Reversible block log usage is at unsafe levels可逆块日志利用处于不安全等级
3070000WASM ExceptionWASM异常
3070001Error in WASM page memoryWASM内存页错误
3070002Runtime Error Processing WASM处理WASM时发生运行时错误
3070003Serialization Error Processing WASM处理WASM时发生序列化错误
3070004memcpy with overlapping memory内存拷贝时发生地址重叠
3070005binaryen exceptionbinaryen异常
3080000Resource exhausted exception资源耗尽异常
3080001Account using more than allotted RAM usage账号使用的内存超限
3080002Transaction exceeded the current network usage limit imposed on the transaction交易网络占用超限
3080003Transaction network usage is too much for the remaining allowable usage of the current block交易网络占用过高
3080004Transaction exceeded the current CPU usage limit imposed on the transaction交易CPU占用超限
3080005Transaction CPU usage is too much for the remaining allowable usage of the current block交易CPU占用过高
3080006Transaction took too long交易用时过长
3080007Transaction exceeded the current greylisted account network usage limit交易超过当前灰名单账号的网络用量上限
3080008Transaction exceeded the current greylisted account CPU usage limit交易超过当前灰名单账号的CPU用量上限
3081001Transaction reached the deadline set due to leeway on account CPU limits由于账号CPU限制,交易已经达到截止区
3090000Authorization exception授权异常
3090001Duplicate signature included包含重复的签名
3090002Irrelevant signature included包含不相关的签名
3090003Provided keys, permissions, and delays do not satisfy declared authorizations提供的密钥、许可和延时不能满足声称的授权
3090004Missing required authority授权丢失
3090005Irrelevant authority included包含不相关的授权
3090006Insufficient delay延时不足
3090007Invalid Permission许可无效
3090008The action is not allowed to be linked with minimum permission不允许该动作链接到最小许可
3090009The parent permission is invalid父级许可无效
3100000Miscellaneous exception其他异常
3100001Internal state is no longer consistent内部状态不一致
3100002Unknown block未知区块
3100003Unknown transaction未知交易
3100004Corrupted reversible block database was fixed被破坏的可逆区块数据库已修复
3100005Extracted genesis state from blocks.log从区块日志中提取的创世状态
3100006Subjective exception thrown during block production出块时抛出异常
3100007Multiple voter info detected检测到多个投票人信息
3100008Feature is currently unsupported当前不支持的特性
3100009Node management operation successfully executed结果管理操作执行成功
3110000Plugin exception插件异常
3110001Missing Chain API PluginChain API插件丢失
3110002Missing Wallet API PluginWallet API插件丢失
3110003Missing History API PluginHistory API插件丢失
3110004Missing Net API PluginNet API插件丢失
3110005Missing Chain PluginChain插件丢失
3110006Incorrect plugin configuration插件配置不正确
3120000Wallet exception钱包异常
3120001Wallet already exists钱包已经存在
3120002Nonexistent wallet钱包不存在
3120003Locked wallet已锁定的钱包
3120004Missing public key公钥丢失
3120005Invalid wallet password无效的钱包密码
3120006No available wallet没有有效的钱包
3120007Already unlocked已经解锁
3120008Key already exists密钥已经存在
3120009Nonexistent key不存在的密钥
3120010Unsupported key type不支持的密钥类型
3120011Wallet lock timeout is invalid钱包锁定超时无效
3120012Secure Enclave Exception安全专区异常
3130000Actor or contract whitelist/blacklist exception执行人或合约白名单/黑名单异常
3130001Authorizing actor of transaction is not on the whitelist交易的授权执行人不在白名单中
3130002Authorizing actor of transaction is on the blacklist交易的授权执行人在黑名单中
3130003Contract to execute is not on the whitelist要执行的合约不在白名单中
3130004Contract to execute is on the blacklist要执行的合约在黑名单中
3130005Action to execute is on the blacklist要执行的动作在黑名单中
3130006Public key in authority is on the blacklist授权中的公钥在黑名单中
3140000Exceptions that are allowed to bubble out of emit calls in controller控制器异常
3140001Block does not match checkpoint区块与检查点不匹配
3160000Contract exception合约异常
3160001The payer of the table data is invalid表数据支付账号无效
3160002Table access violation数据表访问违规
3160003Invalid table iterator无效的数据表迭代器
3160004Table can not be found inside the cache缓存中找不到指定的数据表
3160005The table operation is not allowed不允许数据表操作
3160006Invalid contract vm type无效的合约虚拟机类型
3160007Invalid contract vm version无效的合约虚拟机版本
3160008Contract is already running this version of code合约已经在运行这个版本的代码
3160009No wast file found,没有找到wast文件
3160010No abi file found没有找到abi文件
3170000Producer exception出块人异常
3170001Producer private key is not available出块人私钥无效
3170002Pending block state is missing待定区块状态丢失
3170003Producer is double confirming known range出块人双重确认
3170004Producer schedule exception出块人调度计划异常
3170006The producer is not part of current schedule出块人不属于当前安排计划
3170007The configured snapshot directory does not exist配置的快照目录不存在
3170008The requested snapshot already exists请求的快照已经存在
3180000Reversible Blocks exception可逆区块异常
3180001Invalid reversible blocks directory无效的可逆区块目录
3180002Backup directory for reversible blocks already existg可逆块的备份目录已存在
3180003Gap in the reversible blocks database不连续的可逆区块数据库
3190000Block log exception区块日志异常
3190001unsupported version of block log不支持的区块日志版本
3190002fail to append block to the block log向区块日志添加区块时失败
3190003block log can not be found找不到区块日志
3190004block log backup dir already exists区块日志备份目录已存在
3200000http exceptionhttp异常
3200001invalid http client root certificate无效的http客户端证书
3200002invalid http response无效的http请求
3200003service resolved to multiple ports服务对应多个端口
3200004fail to resolve host解析主机名失败
3200005http request failhttp请求失败
3200006invalid http request无效的http请求
3210000Resource limit exception资源限制异常
3220000Mongo DB exceptionMongoDB异常
3220001Fail to insert new data to Mongo DBMongoDB插入数据失败
3220002Fail to update existing data in Mongo DBMongoDB更新数据失败
3230000Contract API exception合约API异常
3230001Crypto API Exception密码学API异常
3230002Database API Exception数据库API异常
3230003Arithmetic Exception算术异常
3240000Snapshot exception快照异常
3240001Snapshot Validation Exception快照验证异常

原文链接: EOS错误代码集 - 汇智网
区块链
2018-12-17 23:36:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
文章目录 摘要 动机 原理 详述 CALL_I CALL_E CALL_ED CALL_ET CALL_EDT 向后兼容性 实现
摘要
本NEP提议NeoVM计算栈堆栈隔离,以确保动态调用的安全性,并为将来的新功能提供支持。
动机
现在已经实现了NEP-4(动态调用),但由于NeoVM计算栈未被隔离,动态调用的合约可能会在运行时中打断调用者的堆栈,从而导致合约未按预期执行。
另一方面,某些功能(例如异常处理)也需要实现堆栈隔离。
原理
我们需要一组新的指令,以便每次调用都创建一个单独的计算栈,并自动将函数的参数复制到新堆栈。函数运行完毕后,返回值将自动复制到调用者的堆栈中。这样,调用的合约对栈的修改,不会影响调用者的行为。
详述
我们添加了五条用于启动堆栈隔离调用的新指令:
CALL_I,CALL_E,CALL_ED,CALL_ET,CALL_EDT。
CALL_I
指令CALL_I与老指令CALL很类似。不同之处在于CALL_I需要在其之后跟随一个操作数来表示参数的数量和返回的要拷贝的值。
CALL_E
指令CALL_E与老指令APPCALL很类似在用于静态调用时。不同之处在于CALL_E需要在其之后跟随一个操作数来表示参数的数量和返回的要拷贝的值。
CALL_ED
指令CALL_ED与老指令APPCALL很类似在用于动态调用时。不同之处在于CALL_ED需要在其之后跟随一个操作数来表示参数的数量和返回的要拷贝的值。
CALL_ET
指令CALL_ET与指令CALL_E很类似。不同之处在于CALL_ET会开启一个尾调用。
CALL_EDT
指令CALL_EDT与指令CALL_ED很类似。不同之处在于CALL_EDT会开启一个尾调用。
向后兼容性
所有旧合约都可以在原始指令集中正确执行,但是不建议新合约继续使用旧指令。当新合约需要动态调用时,应避免使用旧指令。
实现
https://github.com/neo-project/neo-vm/pull/39
原文链接: https://github.com/neo-project/proposals/blob/master/nep-8.mediawiki
区块链
2018-12-17 18:38:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
媒体对比特币的关注让我开始了解比特币的真正运作方式,直至流经网络的字节数。普通人使用隐藏真实情况的软件,但我想亲自了解比特币协议。我的目标是直接使用比特币系统:手动创建比特币交易,将其作为十六进制数据提供给系统,并查看它是如何处理的。事实证明这比我预期的要困难得多,但我在这个过程中学到了很多东西,希望你会发现它很有趣.
本篇博文首先简要介绍比特币,然后跳转到低级细节:创建比特币地址,进行交易,签署交易,将交易提供给对等网络,并观察结果。
比特币的快速概述
在深入研究细节之前,我将首先快速概述比特币的工作原理。比特币是一种相对较新的数字货币,可以通过互联网传输。你可以用Coinbase或MtGox等网站上的美元或其他传统资金购买比特币,将比特币发送给其他人,在某些地方用它们买东西,然后将比特币兑换成美元。为了略微简化,比特币由分布式数据库中的条目组成,该数据库跟踪比特币的所有权。与银行不同,比特币与用户或账户无关。相反,比特币由比特币地址拥有,例如 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa 。
比特币交易
交易是消费比特币的机制。在交易中,某些比特币的所有者将所有权转移到新地址。比特币的一个关键创新是如何通过挖掘在分布式数据库中记录交易。交易被分组为块,大约每10分钟发送一个新的交易块,成为交易日志的一部分,称为区块链,表示交易已经(或多或少)正式进行。比特币挖掘是将交易放入块中的过程,以确保每个人都具有一致的交易日志视图。为了挖掘区块,矿工们必须找到一种极其罕见的解决方案来解决(否则无意义的)加密问题。找到此解决方案会生成一个已开采的块,该块将成为官方区块链的一部分。
挖掘也是比特币进入系统的新机制。当块成功挖掘时,块中会生成新的比特币并支付给矿工。这个采矿奖金很大——目前每块25比特币(约19,000美元)。此外,矿工获得与区块中的交易相关的任何费用。因此,采矿与许多试图开采矿块的人竞争非常激烈。采矿的难度和竞争力是比特币安全的关键部分,因为它确保没有人可以用坏块淹没系统。
点对点网络
没有集中的比特币服务器。相反,比特币在点对点网络上运行。如果你运行比特币客户端,你将成为该网络的一部分。网络上的节点彼此交换其他对等体的交易,块和地址。首次连接到网络时,客户端会从某个随机节点或节点下载区块链。反过来,你的客户端可能会向其他节点提供数据。当你创建比特币交易时,你将其发送给某个对等方,该对等方将其发送给其他对等方,依此类推,直到它到达整个网络。矿工获取你的交易,生成包含你的交易的挖掘区块,并将此挖掘的区块发送给对等方。最终,你的客户端将收到该块,你的客户端将显示该交易已处理完毕。
加密
比特币使用数字签名来确保只有比特币的所有者可以使用它们。 比特币地址的所有者具有与该地址相关联的私钥。 为了花费比特币,他们用这个私钥签署交易,证明他们是所有者。 (这有点像签署物理检查以使其有效。)公钥与每个比特币地址相关联,任何人都可以使用它来验证数字签名。 块和交易由其内容的256位加密哈希标识。 此哈希值用于比特币协议中的多个位置。 此外,查找特殊哈希是挖掘块的难题。
深入原始比特币协议
本文的其余部分将逐步讨论我如何使用原始比特币协议。首先,我生成了比特币地址和密钥接下来,我做了一笔交易,将少量的比特币转移到这个地址。签署此交易给我带来了很多时间和困难。最后,我将这笔交易送入比特币点对点网络并等待它开采。本文的其余部分将详细介绍这些步骤。事实证明,实际使用比特币协议比我预期的更难。正如你将看到的,该协议有点混乱:它使用大尾数字,小尾数数字,固定长度数字,可变长度数字,自定义编码,DER编码和各种加密算法,看似随意。因此,将数据转换为正确的格式会有很多烦人的操作。
直接使用协议的第二个复杂因素是加密,这是非常不可原谅的。如果你得到一个字节错误,则会拒绝该交易,而不知道问题出在何处。
我遇到的最后一个困难是签署交易的过程比必要的困难得多,需要纠正很多细节。特别是,签名的交易版本与实际使用的版本非常不同。
比特币地址和密钥
我的第一步是创建一个比特币地址。通常,你使用比特币客户端软件来创建地址和相关密钥。但是,我写了一些Python代码来创建地址,准确显示幕后发生的事情。比特币使用各种键和地址,因此下图可能有助于解释它们。首先创建一个随机的256位私钥。需要私钥来签署交易,从而转移(支出)比特币。因此,私钥必须保密,否则你的比特币可能被盗。
Elliptic Curve DSA算法从私钥生成512位公钥。(椭圆曲线加密将在后面讨论。)此公钥用于验证交易上的签名。不方便的是,比特币协议为公钥添加了前缀04。在签署交易之前不会公开公钥,这与大多数公钥公开的系统不同。
下一步是生成与其他人共享的比特币地址。由于512位公钥不方便大,因此使用SHA-256和RIPEMD哈希算法将其分解为160位。然后使用比特币的自定义Base58Check编码以ASCII编码密钥。结果地址,例如 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa ,是人们为了接收比特币而发布的地址。请注意,你无法从该地址确定公钥或私钥。如果你丢失了私钥(例如丢弃了硬盘),你的比特币将永远丢失。
最后,电子钱包交换格式密钥(WIF)用于向客户端钱包软件添加私钥。这只是将私钥的Base58Check编码转换为ASCII,这很容易被反转以获得256位私钥。(我很好奇是否有人会使用上面的私钥来窃取我的80美分的比特币,当然有人这样做了。)
总而言之,有三种类型的密钥:私钥,公钥和公钥的hash,它们使用Base58Check编码在ASCII外部表示。私钥是重要的密钥,因为它需要访问比特币,而其他密钥可以从中生成。公钥哈希是你看到的比特币地址。
我使用以下代码片段生成WIF格式的私钥和地址。私钥只是一个随机的256位数字。ECDSA加密库从私钥生成公钥。比特币地址由SHA-256哈希,RIPEMD-160哈希,然后是带校验和的Base58编码生成。最后,私钥在Base58Check中编码,以生成用于将私钥输入比特币客户端软件的WIF编码。注意:这个Python随机函数不是强加密;如果你真的这样做,请使用更好的功能。 def privateKeyToWif(key_hex): return utils.base58CheckEncode(0x80, key_hex.decode('hex')) def privateKeyToPublicKey(s): sk = ecdsa.SigningKey.from_string(s.decode('hex'), curve=ecdsa.SECP256k1) vk = sk.verifying_key return ('\04' + sk.verifying_key.to_string()).encode('hex') def pubKeyToAddr(s): ripemd160 = hashlib.new('ripemd160') ripemd160.update(hashlib.sha256(s.decode('hex')).digest()) return utils.base58CheckEncode(0, ripemd160.digest()) def keyToAddr(s): return pubKeyToAddr(privateKeyToPublicKey(s)) # Warning: this random function is not cryptographically strong and is just for example private_key = ''.join(['%x' % random.randrange(16) for x in range(0, 64)]) print keyUtils.privateKeyToWif(private_key) print keyUtils.keyToAddr(private_key)
在交易中
交易是比特币系统的基本操作。你可能希望交易只是将一些比特币从一个地址移动到另一个地址,但它比这更复杂。比特币交易在一个或多个输入和输出之间移动比特币。 每个输入都是提供比特币的交易和地址。每个输出都是接收比特币的地址,以及到达该地址的比特币数量。
上图显示了一个示例交易“C”。在此交易中,0.005BTC取自交易A中的地址,而0.003BTC取自交易B中的地址。请注意,箭头是对先前输出的引用,因此向后转到比特币流。)对于输出,0.003BTC指向第一个地址,0.004BTC指向第二个地址。剩余的0.001BTC作为费用给到该区块的矿工。请注意,交易A的其他输出中的0.015 BTC不会用于此交易。
使用的每个输入必须完全花在交易中。如果一个地址在一个交易中收到了100个比特币而你只想花1个比特币,那么交易必须花费所有100个。解决方案是使用第二个输出进行更改,这会将99个剩余比特币返回给你。
交易还可以包括费用。如果在将输入相加并减去输出后仍有任何比特币剩余,则余额是支付给矿工的费用。该费用并非严格要求,但免费交易对矿工来说不是优先考虑的事项,可能几天不会处理,也可能完全丢弃。交易的典型费用是0.0002比特币(约20美分),因此费用很低但不是微不足道的。
手动创建交易
对于我的实验,我使用了一个带有一个输入和一个输出的简单交易,如下所示。我开始使用Coinbase的比特币并将0.00101234比特币放入地址 1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5 ,这是交易 81b4c832... 我的目标是创建一个交易,将这些比特币转移到我上面创建的地址, 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa ,减去0.0001比特币的费用。因此,目标地址将接收0.00091234比特币。
遵循规范,可以非常容易地组装无符号交易,如下所示。有一个输入,它使用来自交易 81b4c832... 输出0(第一个输出) 81b4c832... 请注意,此交易哈希在交易中不方便地反转。输出量为0.00091234比特币(91234为十六进制的0x016462),以小尾数格式存储在值字段中。加密部分——— criptSig 和 scriptPubKey 更复杂,稍后将对其进行讨论。
这是我用来生成这个无符号交易的代码。这只是将数据打包成二进制的问题。签署交易是困难的部分,你将在下面看到。 # Makes a transaction from the inputs # outputs is a list of [redemptionSatoshis, outputScript] def makeRawTransaction(outputTransactionHash, sourceIndex, scriptSig, outputs): def makeOutput(data): redemptionSatoshis, outputScript = data return (struct.pack("比特币交易如何签署
下图给出了如何签署和链接交易的简化视图。考虑中间交易,将比特币从地址B转移到地址C.交易的内容(包括先前交易的哈希)被哈希并用B的私钥签名。此外,B的公钥包含在交易中。
通过执行几个步骤,任何人都可以验证交易是否被B授权。首先,B的公钥必须与前一个交易中的B地址相对应,证明公钥是有效的。(如前所述,地址可以很容易地从公钥中导出。)接下来,可以使用交易中B的公钥来验证B的交易签名。这些步骤确保交易有效并由B授权。比特币的一个意外部分是B的公钥在交易中使用之前不会公开。
使用这个系统,比特币通过一系列交易从一个地址传递到另一个地址。可以验证链中的每个步骤以确保有效地使用比特币。请注意,交易通常可以有多个输入和输出,因此链分支到树中。
比特币脚本语言
你可能希望仅通过在交易中包含签名来签署比特币交易,但该过程要复杂得多。事实上,每个交易中都有一个小程序可以执行以确定交易是否有效。该程序是用Script编写的,这是一种基于堆栈的比特币脚本语言。复杂的赎回条件可以用这种语言表达。例如,托管系统可能需要三个特定用户中的两个必须签署交易才能使用它。或者可以设置各种类型的合约。
Script语言非常复杂,有大约80种不同的操作码。它包括算术运算,按位运算,字符串运算,条件运算和堆栈操作。该语言还包括必要的加密操作(SHA-256,RIPEMD等)作为基元。为了确保脚本终止,该语言不包含任何循环操作。(因此,它不是Turing-complete。)但实际上,只支持几种类型的交易。
为了使比特币交易有效,兑换脚本的两个部分必须成功运行。旧交易中的脚本称为 scriptPubKey ,新交易中的脚本称为 scriptSig 。要验证交易,执行 scriptSig ,然后执行 scriptPubKey 。如果脚本成功完成,则交易有效并且可以使用比特币。否则,交易无效。关键在于旧交易中的 scriptPubKey 定义了使用比特币的条件。新交易中的 scriptSig 必须提供满足条件的数据。
在标准交易中, scriptSig 将签名(从私钥生成)推送到堆栈,然后是公钥。接下来,执行 scriptPubKey (来自源交易)以验证公钥,然后验证签名。
如脚本中所述, scriptSig 是: PUSHDATA signature data and SIGHASH_ALL PUSHDATA public key data
scriptPubKey 是: OP_DUP OP_HASH160 PUSHDATA Bitcoin address (public key hash) OP_EQUALVERIFY OP_CHECKSIG
执行此代码时, PUSHDATA 首先将签名推送到堆栈。下一个 PUSHDATA 将公钥推送到堆栈。接下来, OP_DUP 复制堆栈上的公钥。 OP_HASH160 计算公钥的160位哈希值。 PUSHDATA 推送所需的比特币地址。然后 OP_EQUALVERIFY 验证前两个堆栈值是否相等。来自新交易的公钥哈希与旧地址中的地址匹配。这证明公钥是有效的。接下来, OP_CHECKSIG 检查交易的签名是否与堆栈上的公钥和签名匹配。这证明签名是有效的。
签署交易
我发现签署交易是手动使用比特币最困难的部分,其过程非常困难且容易出错。基本思想是使用ECDSA椭圆曲线算法和私钥生成交易的数字签名,但细节很棘手。签名过程已通过19个步骤(更多信息)进行了描述。单击下面的缩略图以获取该过程的详细图表。
最大的复杂因素是签名出现在交易中间,这就提出了在签名之前如何签署交易的问题。为避免此问题,在计算签名之前,将 scriptPubKey 脚本从源交易复制到支出交易(即正在签名的交易)中。然后将签名转换为脚本语言中的代码,创建嵌入在交易中的 scriptSig 脚本。似乎在签名期间使用先前交易的 scriptPubKey 是出于历史原因而不是任何逻辑原因。对于具有多个输入的交易,签名甚至更复杂,因为每个输入都需要单独的签名,但我不会详细介绍。
绊倒我的一步是哈希类型。在签名之前,交易具有临时附加的哈希类型常量。对于常规交易,这是 SIGHASH_ALL(0x00000001) 。签名后,此哈希类型将从交易结束时删除并附加到 scriptSig 。
关于比特币协议的另一个令人讨厌的事情是签名和公钥都是512位椭圆曲线值,但它们以完全不同的方式表示:签名用DER编码编码,但公钥表示为普通字节。此外,两个值都有一个额外的字节,但位置不一致:签名后放置 SIGHASH_ALL ,类型04放在公钥之前。
由于ECDSA算法使用随机数,因此调试签名变得更加困难。因此,每次计算时签名都不同,因此无法与已知良好的签名进行比较。
更新(2014年2月):每次签名更改的一个重要副作用是,如果重新签名交易,交易的哈希值将会更改。这称为交易可维护性。还有一些方法可以让第三方以微不足道的方式修改交易,从而改变哈希,而不是交易的意义。尽管多年来人们已经知道,但是可塑性最近在MtGox(新闻稿)中引起了很大的问题(2014年2月)。
由于这些复杂情况,我花了很长时间才能使签名工作。但最终,我从签名代码中获得了所有错误,并成功签署了一项交易。这是我使用的代码片段。 def makeSignedTransaction(privateKey, outputTransactionHash, sourceIndex, scriptPubKey, outputs): myTxn_forSig = (makeRawTransaction(outputTransactionHash, sourceIndex, scriptPubKey, outputs) + "01000000") # hash code s256 = hashlib.sha256(hashlib.sha256(myTxn_forSig.decode('hex')).digest()).digest() sk = ecdsa.SigningKey.from_string(privateKey.decode('hex'), curve=ecdsa.SECP256k1) sig = sk.sign_digest(s256, sigencode=ecdsa.util.sigencode_der) + '\01' # 01 is hashtype pubKey = keyUtils.privateKeyToPublicKey(privateKey) scriptSig = utils.varstr(sig).encode('hex') + utils.varstr(pubKey.decode('hex')).encode('hex') signed_txn = makeRawTransaction(outputTransactionHash, sourceIndex, scriptSig, outputs) verifyTxnSignature(signed_txn) return signed_txn
最终的 scriptSig 包含签名以及源地址的公钥( 1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5 )。这证明我可以使用这些比特币,使交易有效。
最终的scriptPubKey包含必须成功使用比特币的脚本。请注意,在使用比特币时,此脚本将在以后的某个任意时间执行。它包含以十六进制表示的目标地址( 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa ),而不是Base58Check。结果是只有该地址的私钥的所有者可以使用比特币,因此该地址实际上是所有者。
最后的交易
一旦完成所有必要的方法,就可以组装最终的交易。 privateKey = keyUtils.wifToPrivateKey("5HusYj2b2x4nroApgfvaSfKYZhRbKFH41bVyPooymbC6KfgSXdD") #1MMMM signed_txn = txnUtils.makeSignedTransaction(privateKey, "81b4c832d70cb56ff957589752eb4125a4cab78a25a8fc52d6a09e5bd4404d48", # output (prev) transaction hash 0, # sourceIndex keyUtils.addrHashToScriptPubKey("1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5"), [[91234, #satoshis keyUtils.addrHashToScriptPubKey("1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa")]] ) txnUtils.verifyTxnSignature(signed_txn) print 'SIGNED TXN', signed_txn
最终交易如下所示。这将上面的scriptSig和scriptPubKey与前面描述的unsigned交易相结合。
切线:理解椭圆曲线
比特币使用椭圆曲线作为签名算法的一部分。在解决费马最后定理的背景下,我之前听说过椭圆曲线,所以我很好奇它们是什么。椭圆曲线的数学很有意思,所以我会绕道而行,快速概述一下。名称椭圆曲线令人困惑:椭圆曲线不是椭圆形,看起来不像椭圆,它们与椭圆几乎没有关系。椭圆曲线是满足相当简单的方程y^2=x^3+ax+b的曲线。比特币使用称为secp256k1的特定椭圆曲线,其简单方程为y^2=x^3+7。
椭圆曲线的一个重要特性是你可以使用一个简单的规则在曲线上定义点的添加:如果你在曲线中绘制一条直线并且它击中三个点A,B和C,则添加由A+定义B+C=0。由于椭圆曲线的特殊性质,以这种方式定义的加法“正常”起作用并形成一个组。如果定义了加法,则可以定义整数乘法:例如4A=A+A+A+A。
使椭圆曲线在加密方面有用的原因是它可以快速进行整数乘法,但除法基本上需要强力。例如,你可以非常快速地计算诸如12345678 A=Q的乘积(通过计算2的幂),但是如果你只知道A和Q求解n A=Q很难。在椭圆曲线加密中,密码12345678将是私钥,曲线上的点Q将是公钥。
在密码学中,坐标不是在曲线上使用实值点,而是以模数为模的整数。椭圆曲线的一个令人惊讶的特性是,无论使用实数还是模运算,数学运算都非常相似。因此,比特币的椭圆曲线看起来不像上面的图片,而是一个随机的256位点混乱(想象一个大的灰色方块点)。
椭圆曲线数字签名算法(ECDSA)采用消息哈希,然后使用消息,私钥和随机数进行一些简单的椭圆曲线算法,以在曲线上生成给出签名的新点。拥有公钥,消息和签名的任何人都可以执行一些简单的椭圆曲线算法来验证签名是否有效。因此,只有具有私钥的人才能签署消息,但是具有公钥的任何人都可以验证该消息。
有关椭圆曲线的更多信息,请参阅参考文献。
将我的交易发送到p2p网络
留下椭圆曲线,此时我创建了一个交易并签名。下一步是将其发送到点对点网络,在那里它将被矿工接收并合并到一个块中。
如何找到同行
使用p2p网络的第一步是找到一个对等体。每当有人运行客户端时,对等体列表每隔几秒就会更改一次。一旦节点连接到对等节点,它们就会在发现新对等体时通过交换addr消息来共享新对等体。因此,新同伴迅速通过该系统传播。
然而,关于如何找到第一个同伴,有一个鸡与蛋的问题。比特币客户通过几种方法解决了这个问题。几个可靠的对等体在DNS中以bitseed.xf2.org的名称注册。通过执行nslookup,客户端获取这些对等端的IP地址,并希望其中一个可以工作。如果这不起作用,则将对等体的种子列表硬编码到客户端中。
当普通用户启动和停止比特币客户端时,同行进入和离开网络,因此客户端有大量的营业额。我使用的客户现在不太可能正常运营,所以如果你想做实验,你需要找到新的同行。 你可能需要尝试一堆才能找到有效的方法。
和同龄人交谈
一旦我获得了工作对等体的地址,下一步就是将我的交易发送到对等网络。使用点对点协议非常简单。我在端口8333上打开了与任意对等方的TCP连接,开始发送消息,并依次接收消息。 比特币点对点协议非常宽容;即使我完全搞砸了请求,同行也会保持沟通。
重要提示:正如一些人所指出的,如果你想进行实验,你应该使用比特币测试网,这可以让你试验“虚假”的比特币,因为如果你搞砸了真正的网络,很容易丢失你的宝贵的比特币。(例如,如果你忘记了交易中的更改地址,那么多余的比特币将作为费用交给矿工。)但我想我会使用真正的比特币网络并冒险使用价值1.00美元的比特币。
该协议由大约24种不同的消息类型组成。每条消息都是一个相当简单的二进制blob,包含一个ASCII命令名和一个适合该命令的二进制有效负载。该协议在比特币维基上有详细记录 。
连接到对等方的第一步是通过交换版本消息来建立连接。首先,我发送一个版本消息,其中包含我的协议版本号,地址和其他一些内容。对等体发回其版本消息。在此之后,节点应该用verack消息确认版本消息。(正如我所提到的,该协议是宽容的 - 即使我跳过了那个行列,一切正常。)
生成版本消息并不是完全无关紧要的,因为它有一堆字段,但它可以用几行Python创建。下面的makeMessage根据幻数,命令名和有效负载构建一个任意的对等消息。getVersionMessage通过将各个字段打包在一起来为版本消息创建有效负载。 magic = 0xd9b4bef9 def makeMessage(magic, command, payload): checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[0:4] return struct.pack('L12sL4s', magic, command, len(payload), checksum) + payload def getVersionMsg(): version = 60002 services = 1 timestamp = int(time.time()) addr_me = utils.netaddr(socket.inet_aton("127.0.0.1"), 8333) addr_you = utils.netaddr(socket.inet_aton("127.0.0.1"), 8333) nonce = random.getrandbits(64) sub_version_num = utils.varstr('') start_height = 0 payload = struct.pack('发送交易:tx
我使用下面的精简Python脚本将交易发送到对等网络。该脚本发送版本消息,接收(并忽略)对等方的版本和维拉消息,然后将该交易作为tx消息发送。十六进制字符串是我之前创建的交易。 def getTxMsg(payload): return makeMessage(magic, 'tx', payload) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("97.88.151.164", 8333)) sock.send(msgUtils.getVersionMsg()) sock.recv(1000) # receive version sock.recv(1000) # receive verack sock.send(msgUtils.getTxMsg("0100000001484d40d45b9ea0d652fca8258ab7caa42541eb52975857f96fb50cd732c8b481000000008a47304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201410414e301b2328f17442c0b8310d787bf3d8a404cfbd0704f135b6ad4b2d3ee751310f981926e53a6e8c39bd7d3fefd576c543cce493cbac06388f2651d1aacbfcdffffffff0162640100000000001976a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac00000000".decode('hex')))
以下屏幕截图显示了如何在Wireshark网络分析程序中发送我的交易。我编写了Python脚本来处理比特币网络流量,但为了简单起见,我将在这里使用Wireshark。“tx”消息类型在ASCII转储中可见,在我的交易开始的下一行(01 00 ...)后面。
为了监视我的交易的进度,我有一个套接字打开给另一个随机对等体。发送我的交易五秒后,另一个对等体发送了一条tx消息,其中包含我刚刚发送的交易的哈希值。因此,我的交易只需几秒钟即可在对等网络或至少部分网络中传递。
胜利:我的交易被开采了
在将我的交易发送到对等网络后,我需要等待它才能获得胜利。十分钟后,我的脚本收到一条带有新块的inv消息(参见下面的Wireshark描述)。检查此块显示它包含我的交易,证明我的交易有效。我还可以通过查看我的比特币钱包和在线查询来验证此交易是否成功。因此,经过大量的努力,我成功地手动创建了一个交易并让它被系统接受。(不用说,我的前几次交易尝试都没有成功,我的错误交易消失在网络中,永远不会被再次看到。)
我的交易是由大型GHash.IO矿池开采的,块为#279068,哈希为 0000000000000001a27b1d6eb8c405410398ece796e742da3b3e35363c2219ee 。(哈希在上面的inv消息中反转:ee19...)请注意,哈希以大量零开始——在quintillion值中找到这样的字面意思是使挖掘变得如此困难的原因。这个特殊的块包含462个交易,其中我的交易只有一个。
为了开采这个区块,矿工们获得了25比特币的奖励,总费用为0.104比特币,分别约为19,000美元和80美元。我支付了0.0001比特币的费用,约占我交易的8美分或10%。挖掘过程非常有趣,但我将把它留给以后的文章。
结论
使用原始的比特币协议比我预期的要困难,但我一路上学到了很多关于比特币的知识,我希望你也做到了。我的代码纯粹是为了演示——如果你真的想通过Python使用比特币,请使用真正的库而不是我的代码。
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程: EOS教程 ,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。 java以太坊开发教程 ,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。 python以太坊 ,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。 php以太坊 ,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。 以太坊入门教程 ,主要介绍智能合约与dapp应用开发,适合入门。 以太坊开发进阶教程 ,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。 C#以太坊 ,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。 java比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。 php比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。 tendermint区块链开发详解 ,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是原文 如何使用原始比特币协议
区块链
2019-01-02 10:16:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
我必须承认,学习eosio一直没有闲庭信步的感觉,我可以看到为什么很多人说它有一个陡峭的学习曲线。随着eosio软件继续经历大量快速发展,文档数量有限,很少有工作实例可供参考。我已经被困了好几次,也希望帮助改善下一个开发人员的体验。在本文中,我将通过将其分解为单独的部分来讨论 eosio.token 合约。
什么是eosio.token合约?
eosio.token合约允许创建许多不同的代币。这使任何人都能够创建和发送代币。每个代币必须由 issuer 帐户发行。由于帐户可以包含多方,因此你可以使用具有所有者和活动权限的普通帐户或自定义配置帐户来创建和管理代币。每个代币都是 asset 类型,如下所示: 1000000000.0000 SYS 1.0000 SYMBOL 0.10 SYS
asset 类型是一个数字(如果我没记错的话可以达到18位小数)和一个可以在1-7个大写字母之间的符号。此合约有三个操作可用于与之交互。它们是:创建,发布和转账。
创建用于定义新代币的特征。这包括代币 asset 符号,最大供应量以及允许发出代币的帐户。创建还会将新代币配置保留在区块链上。这意味着新代币配置的存储必须由某人放置。正如你稍后将看到的,部署此合约的帐户(在我们的案例中为'eosio.token')也将支付代币配置存储。
发布用于增加代币的有效供应。可以持续发出代币,直到达到最大供应量。在代币创建期间定义的 issuer 必须批准此操作才能使其成功。
转账让一个帐户将代币转移到另一个帐户。
部署合约
你应该知道的第一件事是每个eosio智能合约都属于一个eosio帐户。合约基本上是其他帐户可以与之交互的对象。合约包含在区块链上执行代码的操作 actions 。合约可以直接访问区块链上的存储,删除和更新数据。
将一个action推送到合约需要至少一个帐户的授权。根据合约的复杂性,可能需要进一步的帐户和权限。帐户可以由基于权限的配置中设置的单个或多个个人组成。智能合约只能由一个帐户运行,而一个帐户只能拥有一个智能合约。最佳做法是为帐户和合约提供相同(小写)的名称。
在你与eosio.token合约进行交互之前,你需要创建一个具有相同名称的帐户,并将合约部署到该帐户。
首先创建一个帐户 $cleos create account eosio eosio.token
然后编译合约 $cd eos/contract/eosio.token $eosiocpp -o eosio.token.wast eosio.token.cpp
最后将合约部署到帐户上 $cleos set contract eosio.token ../eosio.token
你可以验证合约是否已部署 $cleos get code eosio.token
合约架构
合约分为两个文件 eosio.token.cpp 和 eosio.token.hpp 。 .hpp 文件定义合约类,操作和表,而 .cpp 文件实现操作逻辑。让我们首先看一下将用于实例化合约对象的合约类。(我从 eosio.token.hpp 中删除了一些遗留代码) /** * @file * @copyright defined in eos/LICENSE.txt */ #pragma once #include #include #include namespace eosiosystem { class system_contract; } namespace eosio { using std::string; class token : public contract { public: token( account_name self ):contract(self){} void create( account_name issuer, asset maximum_supply); void issue( account_name to, asset quantity, string memo ); void transfer( account_name from, account_name to, asset quantity, string memo ); private: friend eosiosystem::system_contract; inline asset get_supply( symbol_name sym )const; inline asset get_balance( account_name owner, symbol_name sym )const; struct account { asset balance; uint64_t primary_key()const { return balance.symbol.name(); } }; struct currency_stats { asset supply; asset max_supply; account_name issuer; uint64_t primary_key()const { return supply.symbol.name(); } }; typedef eosio::multi_index accounts; typedef eosio::multi_index stats; void sub_balance( account_name owner, asset value ); void add_balance( account_name owner, asset value, account_name ram_payer ); }; asset token::get_supply( symbol_name sym )const { stats statstable( _self, sym ); const auto& st = statstable.get( sym ); return st.supply; } asset token::get_balance( account_name owner, symbol_name sym )const { accounts accountstable( _self, owner ); const auto& ac = accountstable.get( sym ); return ac.balance; } } /// namespace eosio
构造函数和操作被定义为公共成员函数。构造函数采用帐户名称(将是部署合约的帐户,也就是eosio.token)并将其设置为contract变量。请注意,此类继承自 eosio::contract 。
表和helper函数作为私有成员提供。两个内联函数在底部定义但从未使用过。这给我们留下了重要的函数 sub_balance() 和 add_balance() 。这些将由转移操作调用。

定义的两个表是 accounts 和 stat 。 accounts 表由不同的 account 对象组成,每个 account 对象持有不同代币的余额。 stat 表由持有供应, max_supply 和发行者的 currency_stats 对象(由 struct currency_stats 定义)组成。在继续之前,重要的是要知道该合约将数据保存到两个不同的范围。 accounts 表的范围限定为eosio帐户, stat 表的范围限定为代币符号名称。
根据 eosio::multi_index 定义, code 是具有写权限的帐户的名称, scope 是存储数据的帐户。
范围本质上是一种在合约中划分数据的方法,以便只能在定义的空间内访问。在代币合约中,每个eosio帐户都用作 accounts 表的范围。 accounts 表是一个包含多个 account 对象的多索引容器。每个 account 对象都由其代币符号编制索引,并包含代币余额。使用其范围查询用户的 accounts 表时,将返回用户具有现有余额的所有代币的列表。
这是我如何想象它。
在上图中,有一个名为tom的eosio帐户,他有自己的范围。在他的范围内是一个名为 accounts 的表。在该表中是一个单独的 account 对象,用于他持有的每个代币, SYS 和 EOS 。
还有一个名为 stat 的第二个表。此表将包含现有代币的状态。新标记在其自己的符号名称范围内创建。范围内是一个包含 currency_stats 对象的 stat 表。与包含许多不同 account 对象的 accounts 表不同, stat 表仅包含给定标记符号的单个 currency_stats 对象。
操作
操作在 .cpp 文件中实现。要创建新代币,必须发送创建操作。 Create 有两个参数:发行者,以及新代币的最大供应量。 issuer 是唯一允许增加新代币供应的人。 issuer 不能超过最高供应量发行。
第一行代码只需要合约帐户本身的授权。这可以在推动操作时使用命令行标志 -p eosio.token 给出。
接下来的几行提取传入的 maximum_supply 资产的符号并执行一些错误处理。如果任何 eosio_assert 失败,那么所有代码​​都将被回滚,并且交易不会被推送到区块链。
一个 stat 表使用符号名称(标记符号)作为其范围构造为 statstable 。代码检查代币是否已存在。如果没有,则创建新代币状态并将其保存到区块链中。 emplace 函数中的第一个参数 _self 意味着此合约帐户 eosio.token 将支付投注存储。
请注意,保存 supply 的符号,因为它用作定位表行的键,但供应量尚未发出。
你现在可以执行下一个操作,发布。发布将采用将收到已发行代币的帐户,发出的代币数量和备忘录。发布操作在一个中执行两个操作,因为它将修改创建的代币供应并调用转账操作以发送已发布的代币。同样,前几行提取代币符号并执行错误检查。
以下代码部分将使用符号名称作为范围构造 stat 表。这用作查找先前使用 create action 创建的代币的键。
请注意,从 statstable.find() 返回的 existing currency_stat 是一个指向找到的对象的迭代器。为简洁起见,声明了一个名为 st 的新变量,并将其设置为 existing 迭代器指向的实际对象。这让我们可以使用 . 运算符访问成员变量而不是指针表示法 -> 。
创建代币的 issuer 者需要签署此交易,并执行更多错误处理。
最后,修改现有代币的currency_stats st ,并将已发放的 quantity 添加到 supply 。 issuer 也将此 supply 添加到他们的余额中,以便初始供应可以追溯到他们的帐户。
紧接着,通过 SEND_INLINE_ACTION() 调用 transfer 函数,这会将资金进行转移。论点如下: 1. *this 是行动所属的合约代码。 2. transfer 操作的名称。 3. {st.issuer, N(active)} 操作所需的权限。 4. {st.issuer, to, quantity, memo} 操作本身的参数。
这将我们带到最后的转账操作。转账操作将从 from , to , quantity 和 memo 获取四个输入参数。 from 是谁将发送代币,因此 quantity 将从他们的余额中减去。 to 是谁将收到代币,因此 quantity 将被添加到他们的余额。 quantity 是要发送的代币数量, memo 是一个可以与交易一起发送的字符串。 memo 未在本合约中使用或存储。
该操作首先要求 from accounts帐户权限并对 from 和 to 帐户执行发布处理。该符号从 quantity 提取并用于获取代币的 currency_stats 。
require_recipient() 函数将在操作完成时通知发送方和接收方。
完成更多发布处理,最后调用两个私有函数 sub_balance() 和 add_balance() 以从发送 add_balance() 减去代币余额并增加接收方的代币余额。
这是完整的'eosio.token.cpp'文件。 /** * @file * @copyright defined in eos/LICENSE.txt */ #include "eosio.token.hpp" namespace eosio { void token::create( account_name issuer, asset maximum_supply ) { require_auth( _self ); auto sym = maximum_supply.symbol; eosio_assert( sym.is_valid(), "invalid symbol name" ); eosio_assert( maximum_supply.is_valid(), "invalid supply"); eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); stats statstable( _self, sym.name() ); auto existing = statstable.find( sym.name() ); eosio_assert( existing == statstable.end(), "token with symbol already exists" ); statstable.emplace( _self, [&]( auto& s ) { s.supply.symbol = maximum_supply.symbol; s.max_supply = maximum_supply; s.issuer = issuer; }); } void token::issue( account_name to, asset quantity, string memo ) { auto sym = quantity.symbol; eosio_assert( sym.is_valid(), "invalid symbol name" ); eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); auto sym_name = sym.name(); stats statstable( _self, sym_name ); auto existing = statstable.find( sym_name ); eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); const auto& st = *existing; require_auth( st.issuer ); eosio_assert( quantity.is_valid(), "invalid quantity" ); eosio_assert( quantity.amount > 0, "must issue positive quantity" ); eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); statstable.modify( st, 0, [&]( auto& s ) { s.supply += quantity; }); add_balance( st.issuer, quantity, st.issuer ); if( to != st.issuer ) { SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} ); } } void token::transfer( account_name from, account_name to, asset quantity, string memo ) { eosio_assert( from != to, "cannot transfer to self" ); require_auth( from ); eosio_assert( is_account( to ), "to account does not exist"); auto sym = quantity.symbol.name(); stats statstable( _self, sym ); const auto& st = statstable.get( sym ); require_recipient( from ); require_recipient( to ); eosio_assert( quantity.is_valid(), "invalid quantity" ); eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); sub_balance( from, quantity ); add_balance( to, quantity, from ); } void token::sub_balance( account_name owner, asset value ) { accounts from_acnts( _self, owner ); const auto& from = from_acnts.get( value.symbol.name(), "no balance object found" ); eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); if( from.balance.amount == value.amount ) { from_acnts.erase( from ); } else { from_acnts.modify( from, owner, [&]( auto& a ) { a.balance -= value; }); } } void token::add_balance( account_name owner, asset value, account_name ram_payer ) { accounts to_acnts( _self, owner ); auto to = to_acnts.find( value.symbol.name() ); if( to == to_acnts.end() ) { to_acnts.emplace( ram_payer, [&]( auto& a ){ a.balance = value; }); } else { to_acnts.modify( to, 0, [&]( auto& a ) { a.balance += value; }); } } } /// namespace eosio EOSIO_ABI( eosio::token, (create)(issue)(transfer) )
示例命令: $cleos push action eosio.token create '["usera","21000000.0000 DEMO"]' -p eosio.token usera $cleos push action eosio.token issue '["usera","21000000.0000 DEMO","issuance"]' -p usera $cleos push action eosio.token tranfser '["usera","userb","1000000.0000 DEMO","here you go"]' -p usera
表命令: $cleos get table eosio.token DEMO stat { "rows": [{ "supply": "21000000.0000 DEMO" "max_supply": "2100000000.0000 DEMO" "issuer": "usera" } ], "more": false } $cleos get table eosio.token usera accounts { "rows": [{ "balance": "20000000.0000 DEMO" } ], "more": false } $cleos get table eosio.token userb accounts { "rows": [{ "balance": "10000000.0000 DEMO" } ], "more": false }
注意:本文是在Dawn4.1代码发布时编写的。
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程: EOS教程 ,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。 java以太坊开发教程 ,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。 python以太坊 ,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。 php以太坊 ,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。 以太坊入门教程 ,主要介绍智能合约与dapp应用开发,适合入门。 以太坊开发进阶教程 ,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。 C#以太坊 ,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。 java比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。 php比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。 tendermint区块链开发详解 ,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是原文 理解eosio.token合约
区块链
2019-01-02 10:15:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Hyperledger Fabric是一种联盟区块链,Fabric区块链也支持智能合约,被称为链码(Chaincode)。Fabric链码就是一个标准的(运行在docker容器中的)操作系统进程,通过gRPC协议与Fabric节点通信。因此理论上可以使用任何语言开发Fabric链码。目前官方提供了三种开发语言的Fabric链码开发工具包:Go、Java和Node.js,本文将介绍如何使用node.js开发Fabric链码。 上汇智网,用互动方式学习以太坊、比特币、EOS、tendermint等更多 区块链开发教程 。
Fabric官方提供了两种开发node.js链码的途径:fabric-shim和fabric-contract-api。
使用fabric-shim开发Fabric链码
fabric-shim是较底层的链码开发包,它封装了与节点通信的grpc协议。安装方法如下: ~/fabric-shim-chaincode-demo$ npm install fabric-shim
fabric-shim要求链码开发者定义一个实现两个预定义方法的类。 Init(stub):初始化链码时节点将调用该方法 Invoke(stub):节点将应用对链码的调用转化为对该方法的调用
参数 stub 由节点传入,它提供了访问链上账本的方法,以便读取或更新账本状态。
例如,下面的代码实现了一个最小化的node.js链码,每次调用链码都会更新acc0的状态(例如:可以使用这个状态代表账户余额): const shim = require('fabric-shim'); class EzChaincode { async Init(stub) { return shim.success(Buffer.from('init done!'));//返回success对象 } async Invoke(stub) { let key = 'acc0'; let oldValue = await stub.getState(key); //读取账本中acc0的状态 let newValue = oldValue + 100; await stub.putState(key, Buffer.from(newValue)); //更新acc0的状态 return shim.success(Buffer.from('update done!'));//返回success对象 } };
一旦定义好链码,就可以使用 shim.start() 方法启动链码实例了。例如: const shim = require('fabric-shim'); class EzChainCode {...} shim.start(new EzChaincode());
这就是一个完整的Fabric链码了!将上面代码保存为demo.js,可以直接用node.js启动: ~/fabric-shim-chaincode-demo$ node demo.js
使用fabric-contract-api开发Fabric链码
fabric-shim是一种相对底层的fabric grpc协议封装,它直接把链码接口暴露给开发者,虽然简单直白,但如果要实现相对复杂一点的链码,开发者需要自己在Invoke实现中进行方法路由。
fabric-contract-api则是更高层级的封装,开发者直接继承开发包提供的Contract类,就不用费心合约方法路由的问题了。fabric-contrac-api开发方法如下: ~/fabric-contract-api-demo$ npm install fabric-contract-api
使用fabric-contract-api的链码示例代码如下,除了构造函数之外的每个方法都自动称为链码的方法,可供外部应用调用 : //demo.js const { Contract } = require('fabric-contract-api'); class EzContract extends Contract constructor(){ super('EzContract'); } async update(ctx, newValue) { await ctx.stub.putState('acc0', Buffer.from(newValue)); return Buffer.from('update done!'); } async remove(ctx) { //..... } }; module.exports.contracts = ['EzContract'];
与fabric-shim不同,fabric-contract-api只需要链码导出contracts数组,因此不能直接使用node.js启动链码,而需要使用fabric-chaincode-node程序。例如: ~/fabric-contract-api-demo$ fabric-chaincode-node demo.js
原文链接: Fabric Node.js链码开发 - 汇智网
区块链
2018-12-29 20:05:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
近日,有用户反映,5G套餐价格已经出现松动,收到基础电信运营商的电话,在推销89元每月的5G套餐。恰逢2019年6月6日中国下发5G商用牌照一周年,三大运营商都纷纷降低了5G套餐价格,推出不同力度的折扣价。
工信部统计显示,我国5G基站数量以每周增加1万多个的数量在增长。目前全国已建成的5G基站超过25万个,有130款5G手机获得入网销售许可,5G终端连接数超过3600万。仅4月一个月,5G用户就增加了700多万
除了5G套餐价格开始松动,另一个显著变化是5G终端不断出新品,且价格快速下调。5月底发布的Redmi 10X售价仅1599元起,将5G手机价格拉至新低。
无论是通信成本、设备成本还是信号覆盖,风风火火的建设和发展都意味着,5G马上就要面向市场,走向普遍化、大众化。可以预见,2020年下半年,随着价格成本的不断降低,和便捷度的不断提升,5G即将凭借政策支持和时代推动,成为大众化的通信应用。5G的使用率将呈现脉冲式上涨,覆盖各行各业的日常工作和生活中。
而数据存储仍然是受5G大众化影响最大的领域之一,5G的到来对数据存储行业有什么意义?
5G提速 信息爆炸式增长
5G技术具有“高速度、泛在网、低功耗、低时延”的特点,随着5G的大众化进程不断加快,网络传输速度提高,数据流通加快,可以预见,2020年数据增长将进入空前阶段。据DIC预测,到2025年,人类将拥有750亿台互联网设备,一年将产生175ZB海量数据。如果将这些数据存入光盘,则叠加起来可绕地球222圈。
信息存储需求增加
大数据时代,万物都携带着数据属性,人工智能、物联网、短视频,智慧城市... 无数新应用每时每刻都在产生大量数据。当你早上起床,用手机查阅天气预报;上班路上,开启车载导航... 每一个动作,甚至上班打卡,都会产生大量数据。未来,数据将成为生活的必备工具,我们将生活在一座由数据搭建起来的城市中。激增的海量数据对数据存储的需求必定会增加,给数据存储行业迎来了新的机遇和挑战,如何安全、高速、低成本地存储如此庞大的数据,成为行业难题。
区块链
2020-07-30 11:48:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
数字货币通过运营公司交易的模式为: 以 瑞波币 为例,瑞波币由专业运营公司OpenCoin 运营, Ripple 协议最初是基于支付手段设计的,设计思路是基于熟人关系网和信任链。要使用 Ripple 网络进行汇款或借贷,前提是在网络中收款人与付款人必须是朋友( 互相建立了信任关系) ,或者有共同的朋友( 经过朋友的传递形成信任链) ,否则无法在该用户与其他用户之间建立信任链,转账无法进行
交易成本低
与传统的银行转账、汇款等方式相比,数字货币交易不需要向第三方支付费用,其交易成本更低,特别是相较于向支付服务供应商提供高额手续费的跨境支付 [2] 。
交易速度快
数字货币所采用的 区块链 技术具有 去中心化 的特点,不需要任何类似清算中心的中心化机构来处理数据,交易处理速度更快捷 [2] 。
高度匿名性
除了实物形式的货币能够实现无中介参与的点对点交易外,数字货币相比于其它电子支付方式的优势之一就在于支持远程的点对点支付,它不需要任何可信的第三方作为中介,交易双方可以 在完全陌生的情况下完成交易而无需彼此信任,因此具有更高的 匿名性 ,能够保护交易者的隐私,但同时也给网络犯罪创造了便利,容易被洗钱和其它犯罪活动等所利用
区块链
2020-07-29 11:26:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
什么是0x协议,它的工作机制是怎样的?在这个教程中,我们将介绍0x协议的基本概念,例如其链下订单中继、去中心化交易中继器等,学习如何使用0x智能合约在以太坊公链或私链上实现自己的去中心化交易所(DEX),掌握如何利用0x.js实现0x资产交易委托订单的链下创建与签名、链上验证及执行。如果你是Go工程师,可以使用这个 0x协议Golang开发包 - ZrxTool 。 用自己熟悉的语言学习 以太坊DApp开发 : Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、什么是0x协议
0x是一种开放协议,支持以太坊区块链上点对点的资产交换。其主要特性为: 安全的非托管交易:无需存入或从中心化平台取出,就可以直接实现钱包对钱包的资产交易。 灵活的订单类型:支持立即购买,或允许潜在买家提交出价。 有助于建立可持续的业务:每笔交易可以收取服务费,有助于生态的扩展
0x协议使用模块化方式在以太坊区块链上交易资产,其主要优势在于: 可靠的智能合约:0x协议的智能合约已通过两轮严格的安全审核。 可扩展架构:0x的模块化流水线支持开发者在通过扩展API插入自己的智能合约。 高效设计:0x的具有链上结算功能的链下订单中继是一种节省手续费的P2P方式的委托单交换方法。
0x协议可用于多种用例,例如游戏和收藏品,预测市场,去中心化交易的订单簿,去中心化贷款等。同时,0x使用以太坊区块链的模块化智能合约,可以通过治理进行升级,而不会影响系统的其他组件,也不会引起活跃市场的中断。
利用0x协议所提供的开源基础架构,开发人员能够轻松构建支持ERC-20和ERC-721资产的去中心化交易所。
2、0x协议的智能合约
0x协议的智能合约主要包括以下类别: 资产交换合约:包含0x协议的业务逻辑,提供订单执行、订单取消、交易执行、签名验证、新资产注册等功能 ERC20资产代理合约:代表用户转让ERC20资产。因此,每个用户都需要授权该合约可以操作自己持有的ERC20代币。 ERC721资产代理合约:代表用户转让ERC721资产。因此,每个用户都需要授权该合约可以操作自己持有的ERC721资产
为了部署、使用0x协议的智能合约,我们需要先安装0x.js。0x.js是一个与0x协议进行交互的JavaScript库,利用它就可以轻松地调用0x协议的智能合约来创建、取消或验证订单,或者检查ERC20和ERC721资产持有者的授权额度和余额。
0x协议采用链下订单中继、链上结算的模式,密码学签名的订单可以通过任意通信渠道在区块链之外传播。感兴趣的对手方可以将这些订单中的一个或多个注入到0x的资产交换合约中,在区块链上执行和结算交易。
可以使用0x协议来交换任何ERC20或ERC721资产。上图显示了当Taker向0x资产交换智能合约 提交订单时资产转移的实际处理流程: Taker调用资产交换智能合约的 fillOrder() 方法提交签名订单 资产交换合约将订单传递给相应的ERC20Proxy资产代理合约,实际的资产转移是在代理合约上进行的。 注意:Maker和Taker必须先授权ERC20Proxy合约,然后才能提交订单。 在资产代理合约中调用Maker资产合约的 transferFrom() 方法 如果Maker的ERC20资产合约调用失败,则交易回滚。 如果ERC20代理合约转换为交换合同。 资产交换合约将订单传递到ERC20Proxy合同。 在资产代理合约中调用Taker资产合约的 transferFrom() 方法 接受方ERC20代币合同失败后恢复。 从ERC20代理合约转换为资产交换合约 返回订单执行结果
3、部署0x智能合约
要与智能合约进行交互,我们需要部署0x智能合约,并使用智能合约的地址通过0x.js库与智能合约进行交互。
首先安装0x.js: Use npm install 0x.js — save to install and save 0x.js library
资产交换合约 :利用 源代码 部署交换智能合约,其中交换合约的构造函数不需要任何参数,智能合约的部署者(msg.sender)将是智能合约的所有者。所有者将能够在交换合约中设置assetProxy合约的地址。
ERC20资产代理合约 :利用 源代码 部署ERC20proxy合约,其中代理合约的构造函数不需要任何参数,智能合约的部署者(msg.sender)将是智能合约的所有者。所有者将能够在ERC20Proxy合约中设置资产交换合约的地址。
ERC721资产代理合约 :利用 源代码 部署ERC20proxy合约,其中代理合约的构造函数不需要任何参数,智能合约的部署者(msg.sender)将是智能合约的所有者。所有者将能够在ERC20Proxy合约中设置交换合约的地址。
部署以上合约后,需要在交换合约中设置资产代理合约的地址,在资产代理合约中设置交换合约的地址。
调用资产交换合约的 registerAssetProxy(assetProxyAddress) 方法将存储资产代理合约的地址,在该地址将发生实际交易以交换代币资产。该方法只能由资产交换智能合约的所有者调用。
调用ERC20Proxy合约的 addAuthorizedAddress(exchangeAddress) 方法注册交换合约。调用ERC20Proxy合约的 removeAuthorizedAddress(exchangeAddress) 方法删除交换合约。
使用资产交换合约和资产代理合约的地址通过0x.js库进行交互: let contractConfig = { contractAddresses: { erc20Proxy: proxyAddress.toLowerCase(), erc721Proxy: "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401", exchange: exchangeAddress.toLowerCase() }, networkId: networkId }; const contractWrappers = new ContractWrappers(holderEngine, contractConfig);
现在就可以交互部署在专用或测试网络上的0x协议智能合约。请记住添加RPC子提供程序以与区块链进行交互。
4、使用0x.js访问0x合约
为了与0x.js库进行交互,我们需要导入相关的软件包,如下所示,最终目标是使用0x.js库用Maker帐户创建订单,并且Taker将使用 fillOrder() 方法提交执行交易: const { assetDataUtils,BigNumber,ContractWrappers, generatePseudoRandomSalt,orderHashUtils,signatureUtils } = require('0x.js'); const TX_DEFAULTS = { gas: 400000 }; const { RPCSubprovider, Web3ProviderEngine } = require('0x.js'); let newWallet = new ethers.Wallet(wallet.signingKey.privateKey, prov); const holderWallet = new PrivateKeyWalletSubprovider(wallet.signingKey.privateKey.slice(2));
添加RPC子提供程序: const holderEngine = new Web3ProviderEngine(); holderEngine.addProvider(holderWallet); holderEngine.addProvider(new RPCSubprovider(providerUrl)); holderEngine.start();
在RPC子提供程序中,可以使用自定义URL分别连接以太坊主网、测试网或私有区块链的区块链连接。
获取0x合约地址并实例化合约包装器: const contractWrappers = new ContractWrappers(holderEngine, contractConfig); const web3Wrapper = new Web3Wrapper(providerEngine); const contractAddresses = getContractAddressesForNetworkOrThrow(100);//networkID
现在,Maker将创建订单,而Taker将执行订单以交换Maker的资产: const tokenAAddress = contractAddresses.tokenA; const tokenBAddress = contractAddresses.tokenB; const exchange = contractAddresses.exchange;
所有地址都可以从0x.js库获取到。 const makerAssetData = assetDataUtils.encodeERC20AssetData(tokenAAddress); const takerAssetData = assetDataUtils.encodeERC20AssetData(tokenBAddress); const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS); const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS); const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const ZERO = new BigNumber(0); const DECIMALS = 18;
现在,Maker和Taker应该授权相应的资产代理合约,以分别代表Maker和Taker转让代币资产: //Allow ERC20 Proxy to move tokenA on behalf of makerAccount const makerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( tokenAAddress, maker, ); await web3Wrapper.awaitTransactionSuccessAsync(makerApprovalTxHash); // Allow ERC20 Proxy to move tokenB on behalf of takerAccount const takerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( tokenBAddress, taker, ); await web3Wrapper.awaitTransactionSuccessAsync(takerApprovalTxHash);
在Maker和Taker批准资产代理合约之后,代理合约就可以分别代表Maker和Taker转让代币资产。现在,Maker将创建一个委托订单并在链下签名,而Taker将在链上执行订单。
5、0x订单的创建、签名、验证与执行
创建订单: const order = { exchangeAddress: exchangeAddress, makerAddress: maker,//address of maker takerAddress: taker,//address of taker senderAddress: taker,//address of sender feeRecipientAddress: NULL_ADDRESS,//fee in the form of native currency of platform expirationTimeSeconds: randomExpiration,//expire time of order salt: generatePseudoRandomSalt(),//random no to differentiate order makerAssetAmount,//maker asset amount takerAssetAmount,//taker asset amount makerAssetData,//encoded address of tokenA takerAssetData,//encoded address of tokenB makerFee: ZERO,//fee if required takerFee: ZERO,//fee if required };
现在我们创建了一个资产交换委托订单。接下来在调用0x.js库的 getOrderHash() 函数获得订单哈希值以便进行签名。根据EIP712对订单计算哈希: const orderHashHex = orderHashUtils.getOrderHashHex(order);
获取订单的哈希后,Maker使用0x.js库的 ecSignHashAsync() 方法签名订单。 const signature = await signatureUtils.ecSignHashAsync(providerEngine, orderHashHex, maker); const signedOrder = { …order, signature };
Taker可以使用资产交易合约的validateFillOrder方法验证订单是否可以执行: await contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( signedOrder, takerAssetAmount, taker );
Taker最终调用资产交易合约的fillOrder方法执行订单: try{ txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, takerAssetAmount, taker, {TX_DEFAULTS,} ); var transaction = await web3Wrapper.awaitTransactionSuccessAsync(txHash); }catch(error){}
原文链接: 0x协议对接开发教程 — 汇智网
区块链
2020-08-05 11:39:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1、降低欺诈风险
众所周知,在线欺诈正在以惊人的速度增长。欺诈者和黑客也在利用这一优势,他们会设立欺诈帐户并销售假冒产品。而区块链可以用于品牌溯源和产品的原创性追寻,例如,通过使用区块链购买任何赛事或者演唱会的门票,您可以从存储的区块中跟踪卖家的信息。此外,这些区块无法篡改或伪造,因此您将获得准确的信息。
利用加密货币付款是安全且不可逆的,资金在公钥加密系统中得到保护。此交易在去中心化的区块链中提供了无法破解的加密级别。
2 、国际认可
加密货币不受利率,汇率,交易费用或任何其他费用的约束。所以,你可以在国际层面进行转账而不会遇到任何问题。这将节省您的时间和金钱,否则将资金从一个国家转移到另一个国家将会耗费您大量的时间跟金钱。
此外,没有电子现金系统,这意味着您的帐户不归其他人所有。使用此系统,您拥有私钥和构成加密货币地址的相应公钥。这意味着除非你自己丢失了,否则没有人可以把它从你身上带走。
3 、降低交易费用
通过加密货币交易,通常不会有任何交易费用。因为矿工挖矿做数字运算产生比特币和其他加密货币从加密货币网络接收补偿。
但是,如果您使用第三方管理服务来维护您的加密货币钱包,则可能会收取一些外部费用。加分的是这笔费用仍低于其他金融系统产生的交易费用。因此,加密货币交易费用非常低,并且具有完全的安全性。
4 、交易保密
每次使用信用卡/借记卡进行在线支付时,银行或所涉及的信用卡公司都将拥有您的整个交易历史记录。这意味着他们可以查看您的银行帐户并查看余额,以确保您有足够的资金。如果您进行关键业务交易,他们可能需要更全面地检查您的财务历史记录。
但是,如果您使用加密货币进行在线交易,则它将是双方之间的唯一的交易渠道。信息通过“推送”进行交易,您可以在其中决定要发送给收件人的内容。因此,这是保护您免遭身份盗用或帐户威胁的好方法。如果您使用传统系统进行交易,则可能会遇到这些类型的威胁。
5 、轻松访问
有数十亿人可以使用手机或互联网。这些人倾向于加密货币而不是传统的金融系统。任何人都可以访问加密货币,您不需要提款软件或企业帐户。入门只需要手机和互联网连接。这对发展中国家的利益很高,因为它很容易获得。
6 、点对点交易
这是加密货币支付的主要资产之一,没有涉及中间商或第三方。该技术旨在促进合理,即时和安全的结算,而无需任何人参与,包括银行或任何其他金融系统。此外,全球网络使用区块链技术来管理记录交易的数据库,这意味着比特币不是由任何一个中央机构操作,而是由其网络操作。
区块链
2020-08-03 11:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> 十年前,随着比特币的推出,区块链在科技领域突如其来。它的首次引入致使许多企业领袖将区块链和加密数字货币视为同义词。事实上,区块链的价值主张远比加密数字货币丰富得多。区块链技术到底是什么?有何价值?又有哪些具体的应用?本文是腾讯云区块链专家李亮&王乐庆老师在「云加社区沙龙online」的分享整理,将从区块链的技术与价值入手,分享腾讯云区块链的应用与技术思路,以及至信链产品方案与应用场景。
点击视频查看完整直播回放
一、区块链技术与价值
1. 区块链的前生
人类的技术可以大致分为两大类:第一类是利用能量,第二类是对信息进行进一步的处理。
第一类是利用能量。比如人类发明了火、发明了轮子、内燃机、原子弹,得以对能量进行进一步的处理,让我们能够支配的能量越来越大。另一类技术是我们对当前的数据和信息进行管理,继而提高协作能力,提高生产力。
举个例子,我们发明的纸让我们可以记录信息、保存信息;发明的通信网络,可以对更大的信息进行处理和交互;发明了互联网,让我们把信息的运用做到了登峰造极。
再往前进一步,我们发明了区块链技术,其实也是对信息进行更进一步的一种处理。所以区块链技术在我们人类的发展当中,属于我们所说的第二类 —— 信息处理技术。
很多人会问什么是区块链,这里可以先举一个比较轻松带有调侃意味的例子。
沈阳某小区有 32 位车主,为了防止外部的车辆进入小区占领车位,他们用了 32 把锁锁住了这个门。有网友对此事调侃说:这不就是一个区块链?
虽然是调侃,但这个故事和区块链有着很相似的内涵。
第一点就是说我们用 32 把锁把它串起来,我进出门的时候只需要我是一个分布式的状态,不需要一个看门的大爷帮我开门。这就是一个去中心化的一种理念体现。
第二点就是进出门时的准入机制。其实我是拿了一把钥匙,钥匙可以理解为区块链中很重要的私钥的概念,我有一个私钥就可以有权限去获取一些我的准入准出,这其实和整个区块链的准入准出机制比较相似。
第三点,我们可以看到锁,前后紧密相连,这和区块链的链式结构很相似。区块链,顾名思义就是很多区块链在一起。
这个调侃的例子引出了很多区块链的一些特性。区块链这项技术很神奇,其不同于5G、AI等是生产力属性的技术,可以很明确的提高某一方向的效率,如5G提高网络传输的速度,如AI在机器视觉识别方面提高了效率,区块链属于一种组织技术或者说制度技术,站在一个个体的角度上很难衡量其价值,而站在全局的角度上就会发现其独特价值。
如同市场经济一般,站在一个个体的角度上很难说清楚其原理及价值,但是站在人类全局看来,市场经济这张无形的大手发挥了及其强大的价值。区块链在监管初期空白或不足的阶段被很多不法分子用于非法集资、诈骗等非法场景,在监管逐步完善后我们看到越来越多的大型科技公司开始在数字领域、实体领域落地应用,为用户及企业创作价值,降低成本。
所以我们也能看到,区块链是一项非常有争议的技术。那么区块链究竟是怎么样诞生,然后怎么样成长为一个现在这种统一的有标准的一项技术?
我们可以看到区块链不是一个新的技术,因为技术的进步都是站在巨人的肩膀上一一实现的,区块链也不例外。
区块链是由多项技术融合成的一个技术体系。比如说 1985 年,莱利斯•兰伯等人提出拜占庭将军问题,Neal Koblitz 等人首次将椭圆曲线应用于密码学;1995 年尼克萨博提出了智能合约的概念,后续发明了点对点的 P2P 技术工作量证明机制。
直到 2008 年,中本聪在密码学的社区里发表了《比特币:一种点对点的电子现金系统》,这也才标志着区块链技术的诞生。
所以大家问区块链什么时候诞生,可以回答 2008 年,但因为 2009 年才正式上线,所以回答 2009 年也可以。
2. 区块链关键技术体系
我们前面提到一点,区块链是一个组合技术,那么它究竟由哪些部分组成的?
我们可以把它抽象为 5 大部分。
首先是动态主网,也叫 P2P 网络。
我们知道区块链是分布式的,它由一个个节点或一个个服务器组成,那么动态组网、P2P 网络就是多个节点之间如何交互、如何通信。
往上是块链数据结构。区块链顾名思义,有块有链,其实它是一种块链数据结构组成的一个防篡改数据结构。
第三部分是共识机制。也就是多个节点都平等的参与,如何对统一的一个信息账本达成一种共识,维护这种时间顺序一致性,就是靠共识机制实现的。
第四部分就是密码学技术。比如区块链的对称加密非对称加密等等。
第五部分是智能合约。我们得以对一个信息或者一段代码进行可信的执行,进行不可篡改的执行,是借助智能合约来实现的。
这 5 大部分组成了现在的区块链技术。
3. 什么是区块链?
了解完技术背景后,我们需要对区块链下一个定义 —— 什么是区块链?
我们一般会说区块链是一种防篡改、可追溯、共享的分布式账本技术(DLT)。那么它的本质就是一种技术,防篡改、可追溯共享是它的重点特性。
我们可以看到防篡改其实是有一种多节点冗余存储以及密码学加密,包括工作量证明机制来保证它的防篡改。
比如多节点冗余存储,我在节点 1 存储了这个信息,那么每一个节点都会同样存储这个信息。如果节点 1 修改了这个信息,剩下的 5 个节点还是有这个信息的。它们会发现你修改了这个信息,判定你是恶意节点,会把你踢出网络或者判定你不诚信。靠这样的方式实现防篡改。
可追溯,是因为这个账本只允许写入,不允许删改,所以说每个信息都是可追溯的,只要写入了信息就不可以改,都是在链上某个时间内存在的。
共享。前面也说到这种冗余存储,每个节点上都会有一份这个数据,所以说它的数据是实现多节点共享
我们可以看到一个比较基础的现象,就是我们传统的信息记录方式。最开始我们只用壁画去记录一些信息,后期我们发明了纸、再到发明互联网,我们所有的信息记录的方式都是中心化的,就是由一个人或者一个机构来维护一个账本或者维护一套信息。
到区块链出现以后,我们会发现记录账本或者记录信息,是可以由多人参与进去的,这个其实是现在区块链技术在记录信息方面一个很大的不同。
以前是一个人参与,现在由多个人参与互相之间的监督、共识,导致这个数据可以实现防篡改的特性。那么区块链的记账方式和传统的中心化数据库的记账方式会有什么不同?我们来看一个对比。
以银行转账为例。比如说我转给李亮老师一笔钱,其实是我发起一个转账请求,银行作为中心化账本的维护者,他在账本上修改相关的数据,然后李亮老师在查这个数据的时候就发现这个数据已经改过来了,那么这就是一个“改”的状态。
我们再看一下区块链的转账是一个什么逻辑。区块链转账的步骤会分的比较多,比如说我还是转账给李亮老师,我会先在我的本地,比如在我的服务器或者手机上新建一笔交易,那么我要转给亮老师多少钱,我会通过 P2P 网络把这笔交易发出去。发布出去之后,网络中的一个个的区块链节点会收到这笔信息,然后会进行验证。首先验证我是不是我、我的签名是否正确,另外就是我的余额是否充足。
验证一旦通过后,他们会把交易发到更多的节点上。我们以比特币举例,发布到相应的节点之后,这些节点就开始“挖矿”,也就叫争夺记账的权利。这么多节点究竟谁来记账,这是要有一个挖矿机制来去争夺权利的。
类似于说我们有一个随机数的机制,可能随机到 A 节点,也可能随机到 B 节点。如果随机到 A 节点,那么 A 节点就会有记账权。
那么同时随着 A 节点付出了挖矿的算力之后,也会得到一定的奖励。A 节点会将转“我转给李亮老师 5 块钱”这个信息记录到区块里头,放到链上,那么整个区块前后紧密相连去做到防篡改。
因此我们可以看到这种转账机制就是由我一个个体发起,在很多人的参与下共同去完成了信息的记录。这一点和中心化数据库的维护是不同的。
4. 如何防篡改?
防篡改是一个很重要的机制,我们大概可以讲讲区块链是如何做到防篡改。其实一个大的技术原理是用了很多技术的组合。
实现防篡改有三条线。第一个是基于密码学的块链数据结构,将每个区块前后紧密相连,修改其中一个区块就要修改其后的全部区块,增大了篡改难度。
另外一个就是 POW 这种算力的博弈,比特币网络平均每10分钟才能依靠算力产出一个区块,修改一个区块需要全网算力计算10分钟,如果修改多个区块难度更大。
第三个通过多方见证、冗余存储这样的一系列的手段,你修改了一个节点的数据,其他节点还存有真实数据,除非你拥有超过全网一半以上的节点支持,篡改的数据才会被全网共识。
其实密码学整体的一个设计逻辑或者说机理,就是实现需要付出的代价会大于你篡改之后获得的收益。这种博弈在比特币上的体现也是比较明显的。
5. 区块链的块链结构
区块链究竟什么是区块?是什么链?这张图就是一个比较好的解释。
区块链的英文叫 blockchain,就是一个个block(区块),把它们chain(链)起来。
我们可以看到每个块里面有上一个区块的哈希值、本区块的哈希值和时间戳,这就是「区块头」的一个构造。
区块的体或者叫区块的body里面,可以看到一笔一笔的交易,里面就有我转给李亮老师 5 块钱的交易放在里面。我们会把每一个区块做一次哈希,也就是本区块的哈希。如果我们是最早的一个区块,如果下面又要产生一个区块,那么这个区块里就要包含我上一个区块里的哈希,也就是我上一个区块里的唯一摘要包含在里面。
还有就是依次紧密的相连。比如说要修改 block31,那么后面的所有区块的哈希都会发生变动。整个比特币网络你需要平均花 10 分钟,全网才能算出一个区块来,才能计算出一个随机数。
改一个区块就要改后面所有的区块,那么篡改的成本和难度是非常高的。整体大概通过这样一个渊源去实现防篡改。区块每一个前后相连,篡改一个就要篡改后面所有的。以比特币为例,转一次账只要是 6 个区块之后,基本是不存在篡改可能性的,就是这样的一个逻辑。
6. 从信息互联网到价值互联网
我们也来聊一下当前的信息互联网,和有了区块链之后称之为的价值互联网,他们之间的区别会在哪里?也再去思考,互联网的伟大之处究竟在于哪里?
思考之后会得出一个结论,就是互联网的伟大之处在于信息的传播,互联网实现了信息传播的零成本,这件事情催生了我们的整个网上的娱乐,我们的游戏、我们的美团、我们的共享单车、我们的支付宝,全部都是基于信息传播零成本这一条逻辑下实现的,所以才有当前的这种互联网的繁荣生态。
但信息在互联网上是以复制性的形式去传播的,还有一点就是互联网上的这种信息是非常容易篡改的,里面有一个中心化的数据库,只要有权限的人都可以进行篡改,并且是改的操作,原始的信息是不被保留的,包括信息以复制的形式传播非常容易被泄密,安全程度也比较低。
但当有了价值互联网、有了区块链之后,区块链的防篡改就实现了一个数据在一个时间下的唯一性,以及不可复制性和不可篡改性。这对一个数据来说,数据安全程度是很高的。
区块链的这种唯一性和不可篡改性,可以说实现了资产传播的零成本。原来的互联网我们用来承载信息,区块链我们可能是用来承载价值或者承载资产。
原来我们做的很繁荣的一点是,我们将互联网传播的信息发展到了体制,催生了这么大的这种信息爆炸。那么在未来,我们可以依托区块链,将我们所有的价值、所有的资产去做数字化,数字资产也能进一步的去做数字化,到链上去更快的做资产的流转。我们知道 GDP 就是一笔一笔的交易,如果我们资产流动的速度变快了,那么也可以想象 GDP 会有多快。
假如说可以用区块链这种方式实现价值的流转,我们不需要一个月发一次工资,可能是一分钟发一次。之前买一栋楼很复杂,那么现在可以一千个人、一万个人一起来买一栋楼,还可以把这栋楼拆分出去,那么资产的流动会非常的快,也会带来翻天覆地的变化,不管是GDP上或者是现实的民生方面。
(1)信息互联网
信息传播趋向零成本:互联网本质是实现信息传播趋向零成本,例如银行间转账、团购、共享单车、游戏、咨询、短视频等等应用,都是实现了信息传播趋向零成本后催收出的新兴应用。
信息易复制、易篡改、易泄露:互联网传播、承载的信息易被篡改、泄密和复制。
比如某作者在网络上发表一篇文章,文章本身很容易就被复制盗取,同时中心化数据库承载的数据也管理员或黑客修改,因此一旦发生纠纷,我们很难使用一个普通电子数据作为证据在司法场景举证,因为该数据的产生时间、归属人、数据本身的内容都是存在很大的不确定性,都有很低成本的篡改手段可以实现数据的修改。
(2)价值互联网
价值传播趋向零成本:信息互联网实现了信息传播趋向零成本,区块链的一个伟大特质是可以实现价值传播趋向零成本。
区块链通过私钥操作的机制,可以通过将“身份”与私钥强绑定来确定链上数据的操作人,同时数据上链可以确定唯一性,并且不可篡改。
不仅如此,区块链的特性价值传播场景下能发挥更大作用,价值的传播或者说资产的传播强依赖唯一性、不可篡改性,因为资产不能像数据,可被复制,一个资产是发送转移后就是你多我少的,不能出现双花情况,区块链很好的满足的资产传播所需要的核心要求。
价值互联网具备确定性:
第一,每一笔区块链的操作都需要一个私钥操作,这个私钥紧密关联“身份”,这个身份可以是个人身份也就是自然人身份,也可以是企业身份也叫法人身份。
第二,区块链上写入信息的时间不是由一个中心化服务器决定的,而是由若干个全量参与区块链网络的节点保障的,因此篡改一个服务器的信息没有用。
第三,内容无法被篡改,从Who、When、What三个方面保障信息的确定性。这样的确定性是信息互联网所无法做到的。
价值互联网将由政府部门参与并主导:
信息互联网的繁荣发展是由B端、C端共同驱动的,因为互联网承载的是信息、娱乐、资讯等。但区块链若要大规模应用,我们认为政府需要成为主导力量,因为无论是区块链上“身份”的合法性,链上数据的合法性,都由需要政府部门参与认可。
区块链最大的应用场景是价值(资产)的低成本传递流转,大额资产如房产、证券、土地等上链的数字化,“资产网关”级的部门都是政府部门,因此价值互联网的繁荣需要由政府部门来牵头主导。
当前很多资产的流转传播都需要很高的时间成本和金钱成本,如果完成社会主流资产的链上数字化后形成我们14亿人口的一个价值传播网络,我们整个经济社会的交易成本将大幅降低,交易效率大幅提升,这将会极大的提升我国的经济活力,创造释放出强大的生产力。
7. 区块链技术分类
区块链的技术分类也比较常规,分成了公有链、联盟链和私有链这几大类,这也是业界比较公认的分类方式。
公有链相较于其他两个最大的区别是,没有准入准出机制,想来就来想走就走。比如说我们的比特币采矿,你随时可以下载它的整个客户端去部署一个节点加入它或者离开它。因为他是没有任何准入准出机制的。但也因为节点参与的数量众多,所以就造成了他的性能低下。比如说比特币的性能,可能就是 7-8 笔/ 秒。
联盟链会有准入机制,它会是多个机构做一个场景,联合起来有准入机制去做一个业务场景,就会使用联盟链的形式。
私有链就是整个链上每一个节点都部署在自己的机房,作为一个私有链。目前这种应用场景比较有限。
8. 区块链能做什么?
区块链最底层的特性是防篡改,这项技术是人类追寻了很多年才实现的一个逻辑。
古代我们可能就是发一封密信,皇帝要调兵遣将,用龙虎符这些对信件进行“加密”实现防篡改。一直到今天,我们仍然输出了极大的成本去防篡改。
现在有了区块链技术,我们发现有很多开源的区块链技术让防篡改这件事情变成了一个低门槛的事情,变得人人都可以接触。这会对整体人类社会带来很大改变。
比如很多数据就代表了信任,比如资产的流转、信用的记录、可信数据的交换等等。
二、腾讯云区块链简介
下图展示了腾讯云区块链产品全景图:
腾讯云区块链是基于腾讯云的云基础设施,向上层搭建了 BaaS平台( blockchain as the service),方便开发者、方便用户快速的搭建区块链。
可支持的链有很多条,比如自主研发的区块链底层平台腾讯云区块链、还有很广泛应用的 Hyperledger Fabric 底层链等,都支持在云端快速低成本的起链。
1. 至信链产品方案与应用场景
对于区块链存证产品,我们先来问一个问题:What?Why?How? 什么是存证:存证是信息存储并证明; 为什么存证:证明一个信息、事件的存在性和真实性; 如何存证:公私钥对,分布式时间戳,账本抗篡改。
具体怎么做存证,需要保证三个 W:Who、When、What。也就是谁在什么时间做了什么事情,需要用这三个维度在链上把它固化下来。
在数字化生活生产下,产生了很多司法存证的需求。这有两大背景: 互联网改变了我们的生活方式,纠纷要素普遍线上化 三大互联网电子法院、微法院等电子诉讼平台日益普及,案件线上审理逐步成为常态。
这也导致了三大痛点: 电子数据量大、易篡改、归属难证明、存证成本高等; 电子数据产生、取证、存证、出证、司法适用的全声明周期环节,流程长、环节多、效率低下; 电子证据司法采信度极低。
所以在涉网案件激增的背景下,电子证据必将成为最主要的证据类型。
区块链存证的基础原理有两个:哈希算法与区块链存证原理。电子信息经过哈希算法之后会产生一个唯一固定长度的哈希值,就靠这个原理实现电子数据的一个初级存证。
2. 至信链 + 微法院:线上诉讼的完整形态
至信链的产品定位,就是希望做一条可信的数据通道,将B端、C端、G端的数据在产生时上链固化,可信的通往司法端。微法院是基于微信小程序平台开发的一款法院全流程办案小程序,系最高人民法院指定的联合项目成果。以前可能需要在法院打官司,现在可以在手机上、小程序上打官司。
至信链+微法院,在未来就可以组成数字化的诉讼手段,数字化的存证到诉讼的闭环。
至信链于 2019 年 7 月 在北京发布。区块链的产品是没有办法一个公司来做的,单一公司做的就会变成一个中心化的产品,所以腾讯联合了北明软件、中国网安等合作共建了至信链的生态服务平台。
腾讯有一个内容生态叫企鹅号,每天产生20 万篇的待确权文章,每日平均10W起侵权,但对外通过律师函进行维权时,存在证据效力不足的问题,诉讼成本高,流程长。如果采用至信链的方案,在发表文章时就上链做存证,并用至信链对侵权的内容进行上链存证,链上就有了相关的明确、可信证据,降低了维权的门槛。
此外还有金融领域的存证流程等,也和知识产权的存证方式类似。
三、至信链技术方案
1. 建链治链
做一个基于联盟链场景的区块链应用,有三种不同的方案。上图中最左边的方案为每个企业都把对应的组织节点建立在自己的数据中心。这种方案,对于企业的技术要求相对较高,每个企业都需要对区块链底层有深刻的认识,同时对区块链的运维有比较深刻的了解才可以实现。
中间的这种解决方案中,各参与的企业可以把自己的节点部署在云上。目前很多云厂商都会提供一站式的区块链解决方案,差不多分钟级就可以把区块链的底层架构部署起来。企业不用关注底层链的部署运维等工作,企业只需要关注自身的业务逻辑如何转为智能合约的代码,这样可以极大的降低企业从传统业务到区块链业务之间的门槛。
但随着企业对区块链了解的程度加深,可能会有把部分节点拉到自身数据中心的需求,也就是第三种方式。把部分节点拉到自身的数据中心,在云上做一些基本的管控,这样可以实现一种完美的结合。
对于不同的区块链搭建模式,也意味着存在不同的管理模式。随着业务的发展,区块链底层组织会不停的扩大。如果所有的参与方组织节点全部部署在自己的数据中心的话,这时候邀请其他参与方加入这个区块链网络相对比较麻烦。各个参与方需要线下交互一些信息,最终完成签名配置,或者各个参与方通过区块链上的智能合约来管理组织的加入和退出,以链治链。以上两种方法都需要相关的参与企业对区块链有比较深刻的了解。如果绝大多数的参与方都利用云上提供的一些区块链服务,比如全云或者混合部署方式,那么可以充分利用云上提供的一些治理服务,包括业务层治理或者以链治链等,这样可以极大地降低对于参与方企业的技术门槛要求。
所以在做区块链的应用之前,首先需要考虑可能参与到底层链协作的各个企业,然后在依据各个企业的能力,选择一个合适的底层链部署方式。
2. 链上数据
搭建好区块链之后,就需要思考什么样的数据需要上链。区块链的透明性确保,只要把数据上到区块链之后,联盟链中所有的参与方都可以看到相同的内容。那么如何处理隐私数据成为一个问题。
如果隐私数据和业务无关,就建议隐私数据不要上链,就不会泄露。若部分隐私数据和业务强相关,也有几种方案可以解决。
最基本的是加密上链, 加密上链有几种不同的方式: HASH 加密对称 同态加密 零知识证明 其他密码学算法
这几种加密方式分别对应不同的使用场景。HASH这种隐私数据处理方式一般用于存证类场景,链上只需要保证用户持有特定的数据的摘要信息就可以。至信链就是采取HASH上链的方式来处理隐私数据,用户不需要提供涉及隐私的信息,只需要把隐私信息对应的摘要提供到链上就可以。
在供应链金融场景中,一些票据流转信息,相对来说比较隐私,不能让所有人都看到,但是需要让特定的人可以看到。这个时候一般可以通过对称加密把隐私数据进行加密,然后把相关的密钥用非对称的方式提供给授权的参与方。
在一些积分场景中,用户的积分如果直接加密后,相对来说流转起来就比较复杂,这个时候可以采用密码学的同态加密,确保密文和明文操作等于明文和明文操作,这样就可以很好的解决加密和可操作性之间的矛盾。
当然如果我们需要判断特定的值是否在一定范围内,比如银行账户等,这个时候可以引入零知识证明等方法来解决问题。密码学中还有很多其他算法可以处理用户的隐私,这个要具体看特定的业务场景来决定。
如果单纯从区块链应用的角度讲,其实开发者不太需要考虑如何实现这些底层的加密方式。开发者可借助第三方平台已经提供的能力,去选择合适的密码学算法来解决自己的隐私数据问题。
另外就是链上的一些敏感词。这个也是客户关心的问题。客户会问,在链上的数据是不是一定是不可以修改的?
由区块链的不可篡改的保证,对于已经存在在区块链上的数据,是不可以修改的。这个其实和我们人生比较接近,我们每一个决定,一旦决定后,其实是无法在回到特定的时间节点进行修改的,我们只能在以后对已经存在的事情进行修正,这个就像在区块链的末尾在追加新的区块。所以,敏感词一旦上链后,这些数据将永远存储在链上,无法修改。
由于数据不可以修改,所以做区块链应用需要考虑敏感词过滤,并且这些敏感词在上链之前就需要过滤掉。明文敏感词相对好处理;如果存在密文敏感词,建议可以在联盟链中引入中立监管角色,在上链之前,监管角色拥有密文对应的私钥进行过滤。
如果没有监管角色,也可以引入一些可信的安全计算硬件进行敏感词的过滤。
第三个部分是数据膨胀问题。
随着业务的发展,区块链上存储的数据越来越多,最终会导致数据膨胀问题。这个问题的解决可以分成几个方面去考虑。
第一个是从区块链数据本身去考虑。区块链上的的数据有证书、签名还有用户本身的数据。首先不建议把数据量很大的数据上链,因为链上的数据相对来说比较宝贵,建议把较大的数据压缩或者哈希后再上链,减少区块链的大小。另一方面是对区块底层的结构进行压缩。在不改变区块本身安全的前提下,减轻相应节点的存储压力。
第二个是选用可以动态扩容的存储,当节点存储压力存在的时候,可以通过动态扩容底层硬件的方式解决存储瓶颈问题。
如果这些操作都尝试后,我们还可以考虑下区块链的归档。比如通过共识达成一个共识的归档点,这样部分企业只需要存储归档点后的区块数据,这样可以极大的减少链上存储的压力。
3. 链间互联
我们的单个区块链应用,一般存储的是单维度的数据,往往是个数据孤岛。如果需要从多维度展示一个实体的数据,这个需要通过跨链方案来实现。
跨链方案相对来说比较复杂,需要有一个跨链治理平台来处理跨链相关的操作。跨链治理平台包含跨链的身份管理、跨链的服务发现、跨链事务操作等。这些操作相对都较为复杂,也会涉及到不同区块链的不同协议。
所以在开发区块链应用前,需要考虑是否有跨链的需求。 如果有跨链的需求,要提前考虑链间互联的问题,确认相关的跨链方案。
4. 技术融合
最后是技术融合的问题,这也是很多企业关注的问题。很多企业会问,区块链是否可以解决所有的问题,答案是否定的。
我个人认为区块链更像是集团军中的特种作战部队,主要是解决一些核心的问题。区块链可以和物联网、人工智能、大数据、云等进行融合,去解决业复杂的业务场景问题。
在广义区块链中,区块链技术结合其他技术包括物联网、人工智能、大数据、云等能力来打通链下的真实世界和链上的数字世界之间的界限, 让链上的数字世界更真实的反应现实世界。
区块链上每一个数据点,可以理解为现实世界中特定的时间点,结合区块链不可篡改的特性,这些单独的数据点合在一起,就可以理解为现实世界中连续的单维度时间点。通过跨链技术的整合,可以从单维度时间点变为多维度时间点。随着时间的累积,多维度的连续时间点,就可以具有价值,就会形成最终的价值互联网。
四、Q&A
Q:区块链存证可以在哪些场景发挥作用?
A: 第一个是司法存证,目前很多大量的纠纷是在线上发生的,产生的数据就是电子证据,把电子数据转化为电子证据就需要进行存证。另外就是知识产权的存证,如果想证明一个原创作品的所属权,就需要一个时间性的证明。第三点就是溯源。一个全流程的产品,如果想知道是在哪个地方生产、销售,本质上也是借助了信息的存证。
哪些场景需要用到防篡改的特性,哪些场景就会用到存证。
Q:用什么方式可以判定,谁可以绑定下一个区块?
A: 在公链里可以有pow、pos等共识算法,在联盟链中一般是通过确定行的共识算法,比如PBFT来决定下个区块的内容。
Q:如果内容上链之后,发现存在违规违禁内容要如何处理?
A: 建议所有的上链数据一定要在上链前做敏感词过滤。同时,对于链上的数据,尽量都是加密处理过的。
Q:归档后的区块链数据,转移的签名是否会受到影响?
A: 归档是说达成全局共识,全局共识形成区块,然后区块构成一个归档点。部分参与方可以不存储在归档点之前的数据,核心节点仍然存储全量数据。
Q:链上是冗余存储,个人的终端设备中如何存储海量的数据?
A: 在联盟链的场景中,联盟的参与方企业提供节点,存储区块数据。客户端只需要调取节点服务,不需要存储数据。
Q:如何保证数据存证前的可信度和真实性?
A: 目前是没有任何一个系统可以保证系统中的数据是 100% 真实的。上链前的数据是否被篡改是没办法作保证的,但可以逼近一个真实值。我们不接受传过来一个东西就做存证,接受的是提供一个SDK、一个开发工具包集成到服务端和业务系统,去做API级别的对接。数据实时产生、实时上链,整个过程要求非人为接触,所以能保证数据产生的时候上链,那么这个数据就是证据。未来可能会在部署到存证SDK的客户里面加入一些检测手段,进一步逼近真实性。
Q:区块链在去中心化后,是否还存在中心化的数据库?
A: 是有的。区块链上并不会承载所有的数据,只会承载一些核心数据。每个企业自身的数据不需要完全上链,中心化的数据库仍然是存在的。
Q:如何提高区块链生成的速度?
A: 目前绝大部分企业使用的是联盟链。联盟链相对来说本身的共识算法是比较确定性的,这些算法的性能都比较高。感兴趣的可以关注腾讯云区块链的公众号,里面会有一些技术方面的讲解。
Q:同一个知识产权出现不同的联盟链怎么办?多个联盟链间的时间如何同步?
A: 在区块链当中没有时间的概念, 每一个上链的数据都要有一个可信的时间戳和数据绑定。这个时间戳是国家授权中心、国家法律认定的。只要链上的数据都有可信的时间戳,那么时间也就是可以比较的。
Q:目前已经存在电子存证,那么区块链存证是否还有必要性?
A: 在区块链诞生之前是有一些电子存证平台的,他们的存证方式和技术原理,基本也是用到了数字签名技术和非对称性加密等技术。这类技术会有两个问题,第一就是无法实现不可篡改,被篡改后无法找回原始的数据。而区块链存证实现了防篡改,这是一个本质的进步和不同。
第二点就是时间戳。传统的对某个信息做一次哈希、做一个签名就会成为一个点,他无法对这个信息或者点进行叠加,而是会关联为另一个信息,这些都是可信不可篡改的。以前的电子存证如果理解为搬运东西,是从a到b的手动搬运,而现在就是一个流水线系统的搬运。
传统的电子存证是中心化的,靠单一的一个机构进行背书,所以中心化作恶的风险还是存在的。而区块链保证了一个制衡和可信。
「云加社区」公众号回复“在线沙龙”,即可获取本场分享PPT~
区块链
2020-07-03 15:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
不得不说,眼下全球经济形势的确很糟糕,所谓二零二零,活着就好看似是自嘲,其实也是个扎心的现实。
受全球新冠疫情的持续影响,过去一个月,美国失业人口已经超过3000万,而作为人口大国,我国的城镇人口失业率据不完全统计,更是捉襟见肘。而雪上加霜的是,另有一组数据称,今年我国还将有874万高校毕业生流入就业市场。
想想看,留学大学生回国,加应届生毕业,再加上裁员潮释放的失业人口,而这种情况下大企业为求自保纷纷裁员优化,中小企业不少也都徘徊在生死边缘。失业潮和就业难成为眼下社会最大的矛盾点,称2020年为史上最难求职季也不为过。
正巧,最近有几个粉丝朋友咨询我,是不是可以考虑加入区块链行业?我的态度很明确:
一、身陷炒币妄念无法自拔,且试图在此行业实现财富自由的朋友,且多次冒险加杠杆炒币被爆仓身负巨债的朋友,请大跨步离开;
二、新晋的大学应届毕业生,且在传统行业没太大竞争优势,且想要在一个全新行业完成学习、积累、价值实现的朋友,请小快步进来。
至于一心炒币追求财富自由的朋友,说再多也没意义,只能劝君好运了。而一些对区块链行业有想法,欲在该领域闯荡一番事业的后浪们,接下来我会系统性的给一些参考建议。
01
相比传统互联网产业,区块链行业是眼下当之无愧的朝阳行业,不管遭受怎样的非议,区块链产业的整体步调相对还算稳健:
1、合规化政策和监管举措正层层渗透进行业,产业区块链引领区块链行业开启下一个黄金十年;
2、头部公链以太坊、EOS除了技术拓展以外,都尝试在产品、DApp生态上做突破,探索大规模落地应用出现的可能;
3、互联网科技企业也都开始拓展联盟链相关应用,国家也在给市场下放区块链解决方案订单,可预见的未来数年内,区块链产业应用将会在金融、政务、民生等领域渐次落地。
作为国家下一步重点发展的新兴领域,区块链行业势必会释放出很多岗位缺口和人才需求,而恰逢传统产业庞大的就业和裁员压力。这种情况下,建议年轻人就不要挑肥拣瘦了,不妨先跨进区块链行业安顿下来再说。如果这样,你还是瞻前顾后不敢冒险的话,不妨看一看,很多年前,因进不了企事业单位被迫选择互联网领域创业的人,现在都混得怎么样了。
历史的经验告诉我们,赌风口的人,不一定会过得很好,但错过风口的人,一定会心有不甘。
02
原本一代人的择业观基本都是寻求铁饭碗,比较看重工作的稳定性。
然而,过去二十年,随着互联网和移动互联网行业的快速发展,高成长性的创业红利让很多人尝到了财富跃迁的甜头,使得不少人的就业观也在悄然发生转变。
现在年轻人毕业后往往会优选阿里、百度、腾讯、头条等互联网大厂,其次是一些熬过A轮、B轮的准上市公司。这些公司也基本都成了大学新晋毕业生优选的黄金饭碗。
但眼下的就业形势,互联网大厂越来越难进,很多人只好选择一些互联网小公司,心想着以小公司为跳板再往大厂跳。但在我看来,这种混互联网小公司跳大厂的可能性在逐年降低。主要是因为,创业小公司十有九坑,一旦融资不畅资金断裂随时就可能面临倒闭,很多人就无奈的被动地跳来跳去,没办法在一个行业内持续积累经验和能力,进而很难攀上互联网大厂的高枝。
如果你面临两个选择,一个是随时可能倒闭破产的互联网小公司,一个是你不懂充满未知变数和可能的区块链公司,我的建议当然是后者。因为,区块链行业短期看进入门槛低,学习成长空间大,长期看也有一定的行业累积优势,是你实现财富跃迁的一次机遇,即时将发展不及预期,也是你抄近道进大厂的一次机会。
我们应该认识到,就像互联网企业取代企事业单位成了就业的黄金饭碗一样,区块链行业也许会在未来某一天变成新一代人争抢的铂金饭碗。
03
当然,对新晋毕业的求职者而言,不能只谈梦想,谈钱也是必要的。由于区块链行业自带金融属性,想要赚钱的话路子相比传统产业要广很多。从投融资模式、到社区激励模型,甚至组织协作模式都可以用通证模型来设计,一家成熟稳定的区块链企业会打破传统组织架构的条条框框,让年轻人的努力有更多可能转化成财富回报。
反倒,在此要提醒年轻人,在区块链行业发展,一定得经得起财富诱惑。
所以,我一直劝诫一些朋友,区块链隐藏的财富机会是优于其他行业,但千万别跟着钱跑,那样下场很可能是竹篮打水一场空。事实证明,能不能在这个行业抓住财富,和进场时机并没有必然关系,13、14年进场的人也有被清零出场的,17、18年进场的也要抓住机遇赚得盆满钵满的。外汇经纪商动态https://www.fx61.com/news这个行业沉淀下来的吸引力不应只是财富效应,因为一旦发财致富成为共识,而技术本身又未创造出匹配的应用落地价值,财富迁移本质上就是一场零和游戏,风险该有多大就不言而喻了。
我们需要跨越区块链行业短期的财富诱惑,看到其技术背后更深远的价值。区块链技术的长远价值,表现在:一方面区块链技术担当了各个行业中“清道夫”的角色,能优化产业上下游协同效率重塑人和人之间的信任;另一方面区块链技术能将壁垒很厚的各垂直行业实现融合互通,让数据真正成为连接各行各业的血液。某种程度上讲,区块链行业的使命是要对现存互联网世界框架进行一次筑底再造和升级,其价值意义和深远影响会让身处其中的每一个参与者都倍感兴奋和骄傲。
很多人进去区块链行业,待久了就变困惑了,说到底来还是因为只盯着眼前可见的财富看,而忽略了区块链技术存在的初衷以及其最终要达到的远方。
04
此外,很多人认为区块链行业的创业门槛比较高,加入后不知道做什么。其实相比传统互联网产业,区块链行业的创业门槛并不高,可做的事情也会多不少。前不久直播带货和地摊经济火了,很多人头脑发热,就蠢蠢欲动想做短视频创业。殊不知,直播带货和摆地摊这些看似简单的行当背后隐性成本却巨高,比如带货背后的供应链实力和线上流量的获取能力等等实际要付出的成本可能无法想象。
区块链世界已经跑出了像以太坊、EOS等不少优秀的公链协议,他们为后来者进入搭建好了一套技术基础设施,虽然还不算完美,但目前也算能支撑起了一个庞大的生态。所谓,前人栽树后人乘凉,这些公链的成熟会带动后续轻应用的诞生。以DeFi赛道为例,传统互联网世界里,你说想做银行的生意,别人会对你冷嘲热讽,然而在区块链世界里,创业者真的可以把传统金融已有的模式搬进来,做银行,做保险大亨,甚至做澳门娱乐城。只要敢想,还是有可能实现的。最近爆火的去中心化银行Compound 就是这方面的典范。而且值得一提的是,做DeFi创业代码写好之后,利用生态的可组合创新特性,和其他已有的产品共享流通性,共享市场用户,共享发展红利,还是很香的。
当然,需要提醒的是,在瘦应用,胖协议的开源、共享,组合、创新的区块链时代,请不要动不动就发币,做公链,做大生态,去做一些吃力不讨好的事情。
05
我个人比较看重的一点是,区块链行业是一个融合互联网、金融、科技、经济等多个行业的组合创新型金融科技行业。这个行业的进入门槛虽然低但是发展门槛却比较高。进入门槛低是因为行业发展还很初期,到处都缺人,发展门槛高则是因为行业对个人的复合能力要求比较高。这就意味着,在区块链行业谋发展对个人综合能力的拔升帮助比较大。
英文是打底的沟通基础语言,PythonGoSolidity等基础编程语言也是深入理解行业的必须;区块链浏览器、SQL等数据处理和分析能力也是学习成长的标配;金融学、经济学、数学等多个不同学科的常识,在区块链行业待久了耳濡目染都会有所提高。这一点完全不像传统互联网行业的螺丝钉式的组织架构,区块链行业的跨知识、跨技能、跨部门甚至跨组织体的协同体系会培养出更多复合型、斜杠型超能个体。
放心,在区块链行业待久了,并不一定会变得浮躁,反倒英文、编程、金融等方方面面都通晓一点点,just like me。
06
另外,有个尖锐的问题必须得说,如何向老妈介绍自己的工作?年轻人会担心这个行业存在各类传销、资金盘等形形色色的骗局项目,整个行业目前的社会认同感不高。
在我看来,大凡是骗局都因为击中了人的软肋,一个刚毕业的新生却妄想月薪两万,工作没两年就幻想当CEO年入百万,骗局正是为这些不自知的人精心策划准备的,而且很可能这些人也是骗局本身。至于社会认同感不高,是任何行业早期都会面临的困窘问题,这会在行业规范化,认知普及化之后有效得到解决。现在,你既然想做第一个吃螃蟹的人就不用担心被扎手,说破天,任何商业模式,只要不触犯法律存在都有一定合理性。
至于更广泛的社会认可度和一个行业的产业成熟度,竞争饱和度,从业人员综合素养等各个维度都有直接关系。我们只需要静静等待就好。
区块链
2020-07-02 11:57:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
SimpleChain的跨链协议已经对外开放很久了,很多应用也已经慢慢支持Simplechain的跨链。最近社区开发者web3.js中集成了Simplechain的跨链接口,开发者只需用 npm 安装包文件。参考原生 RPC接口 的参数,就可以快速上手接入Simplechain跨链。下面是详细流程;
查看RPC接口
首先我们需要熟悉Simplechain的跨链 接口 ,熟悉了接口以后我们就可以直接上手操作。
安装包文件
首先你需要安装node环境,然后使用npm安装跨链包。命令如下: npm install @sipc/web3
安装完以后就可以在你的工程项目面集成跨链。主要的方法有: getCtxQuery , getCtxOwner , getCtxOwnerByPage , getCtxContent , getCtxContentByPage , ctxGet , ctxGetByNumber , ctxQueryDestValue , getCtxTakerByPage , getCtxStats , getPoolStats 。
使用示例
npm库 const rpcUrl = "http://192.168.4.104:8546" const Web3 = require('@sipc/web3') const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl)); (async function () { const blockNumber = await web3.eth.getBlockNumber() const chainId = await web3.cross.net.getId() const owner = await web3.cross.getCtxOwnerByPage("0x6407d2a4cd26fdd884dc2ed4a4f8882e413d84f6", 2, 1) const poolStats = await web3.cross.getPoolStats() const stats = await web3.cross.getCtxStats() for(const item of owner.data['909']){ console.log(item.txHash) } console.log(blockNumber, chainId, owner, poolStats, stats ) })()
以上就是Simplechain的跨链SDK使用方法,如果你在使用过程中遇到任何问题可以添加我们的技术社区负责人微信:youths_1994。加入我们的社群一起讨论
区块链
2020-07-06 17:07:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
不到一个月的时间里,在区块链DeFi协议中锁定的资产价值就已经翻了一倍,超过20亿美元。Aave是第五大并且是第一个支持Flash Loan的DeFi平台,在这篇文章中,我们将学习如何在DApp应用中对接Aave协议,实现存入资产、赎回资产等功能。本教程使用的开发语言为JavaScript。 用自己熟悉的语言学习 以太坊DApp开发 : Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、Aave协议简介
Aave目前支持17个市场: ETH, DAI, USDC, SUSD, TUSD, USDT, BUSD, BAT, KNC, LEND, LINK, MANA, MKR, REP, SNX, WBTC以及ZRX。
让我们以LINK为例进行说明Aave的作用。通过将LINK存入Aave协议,即表明你允许协议借出你的资产,并因此获得利息收入。你可以随时取回你存入的加密资产,就像储蓄账户一样。
将你的LINK存入协议后,你可以进行一些其他操作,例如检查目前的利率、借入其他资产等等。
2、Aave协议技术概述
那么上述过程从技术角度是怎样的?与Compound相比,Aave的协议过程会复杂一点,不过还不难掌控。
Aave协议的核心是 LendingPools 智能合约,它也是整个Aave协议的入口点。开发者可以利用LendingPool合约的 deposit() 方法存入加密资产。此外,开发者也可以获取Aave协议的一些储备数,例如用户的流动性、当前的利率,总体流动性等等。
在Aave协议中,LendingPool合约是可升级的。这意味着其部署地址在将来可能变化。为了让DApp兼容未来的地址,Aave提供了一个 LendingPoolAddressesProvider 智能合约来解决这个问题,该合约永远不会升级,可以利用它来获取最新的LendingPool合约的地址。只要我们拿到了最新的LendingPool合约的地址,就可以对接Aave协议了。
不过我们没法用LendingPool合约赎回存入的资产,这需要用到其他一些智能合约,即 aTokens 。aTokens是一类ERC-20兼容的智能合约,用于实现与各种标的资产(underlying assets)的兑换。例如,当存入LINK代币后,我们就会收到按当前汇率折算数量的aLink代币,aLink合约则提供 redeem() 方法用于赎回之前存入的资产。
总的说来,与Aave协议的交互主要包括以下环节: 利用LendingPoolAddressesProvider合约获取最新的LendingPool合约的部署地址 利用LendingPool合约存入资产 利用aToken类合约赎回资产
上述步骤让Aave协议的对接要比Compound协议复杂一些,因为DApp需要用到若干个不同的智能合约与ABI。
3、向Aave协议存入资产
首先我们先学习如何将ETH资产存入Aave池,主要步骤如下: 载入LendingPoolAddressesProvider合约 获取LendingPool地址 载入LendingPool合约 向LendingPool合约存入ETH
3.1 载入LendingPoolAddressesProvider合约
我们需要的第一个ABI是 LendingPoolAddressesProvider合约 的,该合约在不同网络的部署地址可查阅 Aave官方文档 ,以太坊主网上该合约的部署地址为 0x24a42fD28C976A61Df5D00D0599C34c4f90748c8 。 下面的示例代码展示了如何载入Provider合约: const providerInstance = new web3.eth.Contract( addressProviderABI, "0x24a42fD28C976A61Df5D00D0599C34c4f90748c8" );
3.2 获取LendingPool合约的部署地址
Aave的Provider合约提供了 getLendingPool() 方法返回LendingPool合约的最新部署地址。例如下面的示例代码展示了如何调用该方法获取最新的LendingPool合约地址: const lendingPoolAddress = await providerInstance.methods.getLendingPool().call() .catch((e) => { throw Error(`Error getting lendingPool address: ${e.message}`) });
3.3 载入LendingPool合约实例
LendingPool ABI 是我们需要使用的第二个ABI。下面的示例代码展示了如何利用前面获得地址载入LendingPool合约实例: const lendingPoolInstance = new web3.eth.Contract(lendingPoolABI, lendingPoolAddress);
3.4 向LendingPool合约存入以太币
当向Aave协议存入资产时,需要告诉LendingPool我们将存入的资产类型和数量。这需要传入标的资产的储备地址,不同类型资产对应的储备地址清单可以查阅 Aave文档 。对于ETH而言,其储备地址是 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE 。
下面的示例代码展示了如何向LendingPool合约存入ETH: lendingPoolInstance.methods.deposit("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", supplyValue, 0) .send({from: account, value: supplyValue}) .once('transactionHash', (hash) => { // transaction hash }) .on('confirmation', (number, receipt) => { // number of confirmations }) .on('error', (error) => { console.log(error); });
在上面的代码中, supplyValue 表示要存入的ETH数量,单位:wei。
下面是到目前为止我们已经实现的与Aave协议对接的全部代码: // Load the address provider const providerInstance = new web3.eth.Contract(addressProviderABI, "0x24a42fD28C976A61Df5D00D0599C34c4f90748c8"); // Get lending pool address const lendingPoolAddress = await providerInstance.methods.getLendingPool().call() .catch((e) => { throw Error(`Error getting lendingPool address: ${e.message}`) }); // Load lending pool const lendingPoolInstance = new web3.eth.Contract(lendingPoolABI, lendingPoolAddress); // Deposit funds lendingPoolInstance.methods.deposit("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", supplyValue, 0) .send({from: account, value: supplyValue}) .once('transactionHash', (hash) => { // transaction hash }) .on('confirmation', (number, receipt) => { // number of confirmations }) .on('error', (error) => { console.log(error); });
好了,现在已经将ETH存入Aave了,等着赚利息吧!
4、从Aave协议赎回资产
为了赎回之前存入的资产,我们首先需要了解应该使用哪个aToken合约,然后调用该合约的 redeem() 方法就可以收到赎回的ETH了。具体步骤如下: 从LendingPool合约获取储备数据 使用储备数据载入aToken合约 赎回以太币
1、获取资产储备数据
储备数据(Reserve Data)描述了所存入资产的信息,例如总体流动性和当前利率。我们可以利用 储备数据获取aToken的地址。下面的代码展示了这一过程: const reserveData = await lendingPool.methods .getReserveData("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE") .call() .catch((e) => { throw Error(`Error getting aave reserve data: ${e.message}`) }); const aTokenAddress = reserveData.aTokenAddress;
2、载入aToken实例
aToken ABI 是我们要用到的最后一个ABI,下面的代码展示了如何载入aToken实例: const aTokenInstance = new web3.eth.Contract(aTokenABI, aTokenAddress);
3、赎回资产
最后,下面的代码展示了如何赎回标的资产: aTokenInstance.methods.redeem(withdrawAmount) .send({from: account}) .once('transactionHash', (hash) => { // transaction hash }) .on('confirmation', (number, receipt) => { // number of confirmations }) .on('error', (error) => { console.log(error); });
withdrawAmount 表示要从Aave协议中赎回的ETH数量,单位还是wei。
下面是Aave协议资产赎回功能的完整代码: // Get reserve data const reserveData = await lendingPool.methods .getReserveData("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE") .call() .catch((e) => { throw Error(`Error getting aave reserve data: ${e.message}`) }); // Get aToken address const aTokenAddress = reserveData.aTokenAddress; // Load aToken const aTokenInstance = new web3.eth.Contract(aTokenABI, aTokenAddress); // Redeem asset aTokenInstance.methods.redeem(withdrawAmount) .send({from: account}) .once('transactionHash', (hash) => { // transaction hash }) .on('confirmation', (number, receipt) => { // number of confirmations }) .on('error', (error) => { console.log(error); });
5、Aave协议接入教程小结
随着DeFi变得越来越简单易用,学习如何与这些协议交互将迅速成为开发人员工具箱中的有力武器。
原文链接: Aave协议对接开发入门 — 汇智网
区块链
2020-07-20 10:06:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
6月3日,国家信息安全漏洞共享平台(CNVD)正式上线区块链漏洞子库CNVD-BC。CNVD区块链漏洞子库由国家互联网应急中心运营,技术支持单位为成都链安科技有限公司。目前,区块链技术已广泛应用在数字金融、物联网、智能制造、供应链管理、数字资产交易等多个领域,作为构成我国信息化基础设施的一项重要技术,其安全能否得到保障影响到我国社会经济活动。

记者观察发现,当前收录的区块链相关漏洞基本上都是公链漏洞,以中危漏洞为主。据CNVD统计,当前已收录区块链相关漏洞247个,其中高危漏洞60个,中危漏洞173个,低危漏洞14个。其中,公链漏洞数量占比为99.59%,外围系统占比为0.41%,联盟链为0。以此计算,现有247个漏洞中有246个为公链漏洞,1个为外围系统漏洞。

相较于联盟链而言,公链确存较大的安全性问题。某区块链技术专家对《证券日报》记者分析道,“公链是匿名且无准入控制,作恶难以被发现,此外,公链应用发布没有审核,上链应用质量参差不齐,这或是公链漏洞较多的主要原因。对比而言,联盟链采用实名制,有严格的准入控制。业务协作的组织在相互信任的基础上才会组建联盟链,不相关的组织或个人并无物理访问的权限,因此相对安全,另外,组织内恶意作恶很容易通过审计发现,作恶会被惩罚。”

CNVD区块链漏洞子库的上线有利于提升区块链技术安全水平。火币研究院高级研究员赵文琦对《证券日报》记者表示,此类漏洞库在传统的信息安全领域已长期存在,其中最著名的是CVE(CommonVulnerabilitiesandExposures)平台,各大公司或组织如Apache、Linux等也维护了相应的漏洞平台。“在区块链行业,面向细分领域,如区块链底层系统、分布式协议、智能合约、去中心化应用及周边软件等,建立相应的漏洞平台有助于提升各领域的安全性。此次区块链漏洞子库的上线补充了我国在这一领域的缺失。依据传统安全领域的经验,在未来,不同区块链平台及服务提供机构可能会陆续推出面向各自应用生态的漏洞库。”赵文琦进一步说道。

进一步而言,从长期来看,区块链漏洞凸显出的安全问题则需要社会各方力量携手推进解决。据悉,CNVD区块链漏洞子库充分依托国家级网络安全资源,通过号召和引导区块链安全厂商、白帽子、区块链企业等多方共同参与区块链安全生态建设,提高我国区块链漏洞和安全事件的发现、分析、预警,以及整体研究水平和应急处置能力,为我国区块链行业安全保障工作提供重要技术支撑和数据支持。

文章来源: 证券日报
区块链
2020-06-11 09:27:04
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>

在整合FISCO BCOS非国密单测与国密单测的工作中,我们发现CachedStorage的单测偶然会陷入卡死的状态,且可在本地持续复现。
复现方式为循环执行CachedStorage单测200次左右,便会发生一次所有线程均陷入等待状态、单测无法继续执行的情况,我们怀疑在CachedStroage中发生了死锁,故对此进行调试。

Debug思路

中医治病讲究望闻问切,调试bug同样需要遵循寻找线索、合理推断、验证解决的思路。

观察线程栈
在死锁发生时,使用/usr/bin/sample工具(mac平台环境下)将所有的线程的栈打印出来,观察各线程的工作状态。
从所有线程的线程栈中观察到有一个线程(此处称为T1)卡在CachedStorage.cpp的第698行的touchCache函数中,具体的代码实现可以参考:
https://github.com/FISCO-BCOS/FISCO-BCOS/blob/release-2.3.0-bsn/libstorage/CachedStorage.cpp

从代码片段中可以看到,T1在第691行已经获得了m_cachesMutex的读锁:代码RWMutexScoped(some_rw_mutex, false)的意思是获取某个读写锁的读锁;相应地,代码RWMutexScoped(some_rw_mutex, true)的意思是获取某个读写锁的写锁,这里的RWMutex是一个Spin Lock。
随后在第698行处尝试获取某个cache的写锁。
除了T1,还有另外一个线程(此处称为T2)卡在CachedStorage.cpp的第691行的touchCache函数中:
从代码片段中可以看到,T2在第681行已经获得了某个cache的写锁,随后在第691行处尝试获取m_cachesMutex的读锁。
继续观察后还发现若干线程卡在CachedStorage.cpp第673行的touchCache函数中:
最后还有一个Cache清理线程(此处称为T3)卡在CachedStorage.cpp的第734行的removeCache函数中:
从代码片段中可以看到,这些线程均没有持任何锁资源,只是在单纯地尝试获取m_cachesMutex的写锁。

读写饥饿问题
初期分析问题时,最诡谲的莫过于:在T1已经获取到m_cachesMutex读锁的情况下,其他同样试图获取m_cachesMutex读锁的线程竟然无法获取到。
但是看到T3线程此时正努力尝试获取m_cachesMutex写锁,联想到读写锁饥饿问题,我们认为其他线程获取不到读锁的问题根源很可能就在T3。
所谓读写锁饥饿问题是指,在多线程共用一个读写锁的环境中,如果设定只要有读线程获取读锁,后续想获取读锁的读线程都能共享此读锁,则可能导致想获取写锁的写线程永远无法获得执行机会(因为读写锁一直被其他读线程抢占)。
为了解决饥饿问题,部分读写锁会在某些情况下提高写线程的优先级,即由写线程先占用写锁,而其他读线程只能在写线程后乖乖排队直到写线程将读写锁释放出来。
在上述问题中, T1已经获取了m_cachesMutex的读锁,若此时T3恰好获得时间片并执行到CachedStorage.cpp的第734行,会因获取不到m_cachesMutex的写锁而卡住,随后其他线程也开始执行并到了获取m_cachesMutex读锁的代码行。
若读写防饥饿策略真的存在,那这些线程(包括T2)的确会在获取读锁阶段卡住,进而导致T2无法释放cache锁,从而T1无法获取到cache锁,此时所有线程均会陷入等待中。
在这个前提下,似乎一切都能解释得通。上述流程的时序图如下所示:
我们找到了TBB中Spin RW Lock的实现代码,如下图所示:
获取写锁:
获取读锁:
在获取写锁的代码中,可以看到写线程如果没有获取到写锁,会置一个WRITER_PENDING标志位,表明此时正有写线程在等待读写锁的释放,其他线程请勿打扰。
而获取的读锁代码中,也可以看到,如果读线程发现锁上被置了WRITER_PENDING标志位,就会老实地循环等待,让写线程优先去获取读写锁。这里读写锁的行为完美符合之前对读写锁防饥饿策略的推测,至此真相大白。
既然找到了问题起因,那解决起来就容易多了。在CachedStorage的设计中,Cache清理线程优先级很低,调用频率也不高(约1次/秒),因此给予它高读写锁优先级是不合理的,故将removeCache函数获取m_cachesMutex写锁方式做如下修改:
修改后,获取写锁方式跟获取读锁类似:每次获取写锁时,先try_acquire,如果没获取到就放弃本轮时间片下次再尝试,直到获取到写锁为止,此时写线程不会再去置WRITER_PENDING标志位,从而能够不影响其他读线程的正常执行。
相关代码已提交至2.5版本中,该版本将很快与大家见面,敬请期待。

实现效果
修改前循环执行CachedStorage单测200次左右便会发生死锁;修改后循环执行2000+次仍未发生死锁,且各个线程均能有条不紊地工作。

经验总结

从这次调试过程中,总结了一些经验与大家分享。
首先,分析死锁问题最有效的仍然是“两步走”方法,即通过pstack、sample、gdb等工具看线程栈,推测导致发生死锁的线程执行时序。
这里的第二步需要多发挥一点想象力。以往的死锁问题往往是两个线程间交互所导致,教科书上也多以两个线程来讲解死锁四要素,但在上述问题中,由于读写锁的特殊性质,需要三个线程按照特殊时序交互才可以引发死锁,算是较为少见的情况。
其次,『只要有线程获取到读锁,那其他想获取读锁的线程一定也能获取读锁』的思维定势是有问题的。
至少在上面的问题中,防饥饿策略的存在导致排在写线程后的读线程无法获取读锁。但本文的结论并非放之四海而皆准,要不要防饥饿、怎么防饥饿在各个多线程库的实现中有着不同的取舍。有的文章提到过某些库的实现就是遵循『读线程绝对优先』规则,那这些库就不会遇到这类问题,所以仍然需要具体问题具体分析。
《超话区块链》话题征集:我的Debug经历
欢迎与我们聊聊你经历过的有趣/难忘的debug过程,我们将挑选具备参考意义的debug经历与更多开发者分享,经社区采纳将可获得FISCO BCOS纪念衫一件。
Debug经历征集传送 门 :
https://jinshuju.net/f/i8m0Il
FISCO BCOS的代码完全开源且免费 下载地址 ↓↓↓
https://github.com/FISCO-BCOS/FISCO-BCOS

区块链
2020-06-09 22:09:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
完全移植自 「CTP商品期货多品种均线策略」 ,由于Python版本商品期货策略还没有一个多品种的策略,所以就移植了JavaScript版本的「CTP商品期货多品种均线策略」。提供一些Python商品期货多品种策略的设计思路、例子。不论JavaScript版本还是Python版本,策略架构设计源于 商品期货多品种海龟策略 。
均线策略作为最简单的策略,是非常易于学习的,因为均线策略没有什么高深的算法,复杂的逻辑。思路清晰不绕弯,可以让初学者更专注于策略设计方面的学习,甚至可以把均线策略相关的代码剔除,留下一个多品种策略框架,可以很轻松的扩展成ATR、MACD、BOLL等策略。
JavaScript版本相关文章: https://www.fmz.com/bbs-topic/5235。

策略源码 '' 'backtest start : 2019 - 07 - 01 09 : 00 : 00 end : 2020 - 03 - 25 15 : 00 : 00 period : 1 d exchanges : [{ "eid" : "Futures_CTP" , "currency" : "FUTURES" }] '' ' import json import re import time _bot = ext . NewPositionManager () class Manager : '策略逻辑控制类' ACT_IDLE = 0 ACT_LONG = 1 ACT_SHORT = 2 ACT_COVER = 3 ERR_SUCCESS = 0 ERR_SET_SYMBOL = 1 ERR_GET_ORDERS = 2 ERR_GET_POS = 3 ERR_TRADE = 4 ERR_GET_DEPTH = 5 ERR_NOT_TRADING = 6 errMsg = [ "成功" , "切换合约失败" , "获取订单失败" , "获取持仓失败" , "交易下单失败" , "获取深度失败" , "不在交易时间" ] def __init__ ( self , needRestore , symbol , keepBalance , fastPeriod , slowPeriod ): # 获取symbolDetail symbolDetail = _C ( exchange . SetContractType , symbol ) if symbolDetail [ "VolumeMultiple" ] == 0 or symbolDetail [ "MaxLimitOrderVolume" ] == 0 or symbolDetail [ "MinLimitOrderVolume" ] == 0 or symbolDetail [ "LongMarginRatio" ] == 0 or symbolDetail [ "ShortMarginRatio" ] == 0 : Log ( symbolDetail ) raise Exception ( "合约信息异常" ) else : Log ( "合约" , symbolDetail [ "InstrumentName" ], "一手" , symbolDetail [ "VolumeMultiple" ], "份,最大下单量" , symbolDetail [ "MaxLimitOrderVolume" ], "保证金率:" , _N ( symbolDetail [ "LongMarginRatio" ]), _N ( symbolDetail [ "ShortMarginRatio" ]), "交割日期" , symbolDetail [ "StartDelivDate" ]) # 初始化 self . symbol = symbol self . keepBalance = keepBalance self . fastPeriod = fastPeriod self . slowPeriod = slowPeriod self . marketPosition = None self . holdPrice = None self . holdAmount = None self . holdProfit = None self . task = { "action" : Manager . ACT_IDLE , "amount" : 0 , "dealAmount" : 0 , "avgPrice" : 0 , "preCost" : 0 , "preAmount" : 0 , "init" : False , "retry" : 0 , "desc" : "空闲" , "onFinish" : None } self . lastPrice = 0 self . symbolDetail = symbolDetail # 持仓状态信息 self . status = { "symbol" : symbol , "recordsLen" : 0 , "vm" : [], "open" : 0 , "cover" : 0 , "st" : 0 , "marketPosition" : 0 , "lastPrice" : 0 , "holdPrice" : 0 , "holdAmount" : 0 , "holdProfit" : 0 , "symbolDetail" : symbolDetail , "lastErr" : "" , "lastErrTime" : "" , "isTrading" : False } # 对象构造时其他处理工作 vm = None if RMode == 0 : vm = _G ( self . symbol ) else : vm = json . loads ( VMStatus )[ self . symbol ] if vm : Log ( "准备恢复进度,当前合约状态为" , vm ) self . reset ( vm [ 0 ]) else : if needRestore : Log ( "没有找到" + self . symbol + "的进度恢复信息" ) self . reset () def setLastError ( self , err = None ): if err is None : self . status [ "lastErr" ] = "" self . status [ "lastErrTime" ] = "" return t = _D () self . status [ "lastErr" ] = err self . status [ "lastErrTime" ] = t def reset ( self , marketPosition = None ): if marketPosition is not None : self . marketPosition = marketPosition pos = _bot . GetPosition ( self . symbol , PD_LONG if marketPosition > 0 else PD_SHORT ) if pos is not None : self . holdPrice = pos [ "Price" ] self . holdAmount = pos [ "Amount" ] Log ( self . symbol , "仓位" , pos ) else : raise Exception ( "恢复" + self . symbol + "的持仓状态出错,没有找到仓位信息" ) Log ( "恢复" , self . symbol , "持仓均价:" , self . holdPrice , "持仓数量:" , self . holdAmount ) self . status [ "vm" ] = [ self . marketPosition ] else : self . marketPosition = 0 self . holdPrice = 0 self . holdAmount = 0 self . holdProfit = 0 self . holdProfit = 0 self . lastErr = "" self . lastErrTime = "" def Status ( self ): self . status [ "marketPosition" ] = self . marketPosition self . status [ "holdPrice" ] = self . holdPrice self . status [ "holdAmount" ] = self . holdAmount self . status [ "lastPrice" ] = self . lastPrice if self . lastPrice > 0 and self . holdAmount > 0 and self . marketPosition != 0 : self . status [ "holdProfit" ] = _N (( self . lastPrice - self . holdPrice ) * self . holdAmount * self . symbolDetail [ "VolumeMultiple" ], 4 ) * ( 1 if self . marketPosition > 0 else - 1 ) else : self . status [ "holdProfit" ] = 0 return self . status def setTask ( self , action , amount = None , onFinish = None ): self . task [ "init" ] = False self . task [ "retry" ] = 0 self . task [ "action" ] = action self . task [ "preAmount" ] = 0 self . task [ "preCost" ] = 0 self . task [ "amount" ] = 0 if amount is None else amount self . task [ "onFinish" ] = onFinish if action == Manager . ACT_IDLE : self . task [ "desc" ] = "空闲" self . task [ "onFinish" ] = None else : if action != Manager . ACT_COVER : self . task [ "desc" ] = ( "加多仓" if action == Manager . ACT_LONG else "加空仓" ) + "(" + str ( amount ) + ")" else : self . task [ "desc" ] = "平仓" Log ( "接收到任务" , self . symbol , self . task [ "desc" ]) self . Poll ( True ) def processTask ( self ): insDetail = exchange . SetContractType ( self . symbol ) if not insDetail : return Manager . ERR_SET_SYMBOL SlideTick = 1 ret = False if self . task [ "action" ] == Manager . ACT_COVER : hasPosition = False while True : if not ext . IsTrading ( self . symbol ): return Manager . ERR_NOT_TRADING hasPosition = False positions = exchange . GetPosition () if positions is None : return Manager . ERR_GET_POS depth = exchange . GetDepth () if depth is None : return Manager . ERR_GET_DEPTH orderId = None for i in range ( len ( positions )): if positions [ i ][ "ContractType" ] != self . symbol : continue amount = min ( insDetail [ "MaxLimitOrderVolume" ], positions [ i ][ "Amount" ]) if positions [ i ][ "Type" ] == PD_LONG or positions [ i ][ "Type" ] == PD_LONG_YD : exchange . SetDirection ( "closebuy_today" if positions [ i ]. Type == PD_LONG else "closebuy" ) orderId = exchange . Sell ( _N ( depth [ "Bids" ][ 0 ][ "Price" ] - ( insDetail [ "PriceTick" ] * SlideTick ), 2 ), min ( amount , depth [ "Bids" ][ 0 ][ "Amount" ]), self . symbol , "平今" if positions [ i ][ "Type" ] == PD_LONG else "平昨" , "Bid" , depth [ "Bids" ][ 0 ]) hasPosition = True elif positions [ i ][ "Type" ] == PD_SHORT or positions [ i ][ "Type" ] == PD_SHORT_YD : exchange . SetDirection ( "closesell_today" if positions [ i ][ "Type" ] == PD_SHORT else "closesell" ) orderId = exchange . Buy ( _N ( depth [ "Asks" ][ 0 ][ "Price" ] + ( insDetail [ "PriceTick" ] * SlideTick ), 2 ), min ( amount , depth [ "Asks" ][ 0 ][ "Amount" ]), self . symbol , "平今" if positions [ i ][ "Type" ] == PD_SHORT else "平昨" , "Ask" , depth [ "Asks" ][ 0 ]) hasPosition = True if hasPosition : if not orderId : return Manager . ERR_TRADE Sleep ( 1000 ) while True : orders = exchange . GetOrders () if orders is None : return Manager . ERR_GET_ORDERS if len ( orders ) == 0 : break for i in range ( len ( orders )): exchange . CancelOrder ( orders [ i ][ "Id" ]) Sleep ( 500 ) if not hasPosition : break ret = True elif self . task [ "action" ] == Manager . ACT_LONG or self . task [ "action" ] == Manager . ACT_SHORT : while True : if not ext . IsTrading ( self . symbol ): return Manager . ERR_NOT_TRADING Sleep ( 1000 ) while True : orders = exchange . GetOrders () if orders is None : return Manager . ERR_GET_ORDERS if len ( orders ) == 0 : break for i in range ( len ( orders )): exchange . CancelOrder ( orders [ i ][ "Id" ]) Sleep ( 500 ) positions = exchange . GetPosition () if positions is None : return Manager . ERR_GET_POS pos = None for i in range ( len ( positions )): if positions [ i ][ "ContractType" ] == self . symbol and ((( positions [ i ][ "Type" ] == PD_LONG or positions [ i ][ "Type" ] == PD_LONG_YD ) and self . task [ "action" ] == Manager . ACT_LONG ) or (( positions [ i ][ "Type" ] == PD_SHORT ) or positions [ i ][ "Type" ] == PD_SHORT_YD ) and self . task [ "action" ] == Manager . ACT_SHORT ): if not pos : pos = positions [ i ] pos [ "Cost" ] = positions [ i ][ "Price" ] * positions [ i ][ "Amount" ] else : pos [ "Amount" ] += positions [ i ][ "Amount" ] pos [ "Profit" ] += positions [ i ][ "Profit" ] pos [ "Cost" ] += positions [ i ][ "Price" ] * positions [ i ][ "Amount" ] # records pre position if not self . task [ "init" ]: self . task [ "init" ] = True if pos : self . task [ "preAmount" ] = pos [ "Amount" ] self . task [ "preCost" ] = pos [ "Cost" ] else : self . task [ "preAmount" ] = 0 self . task [ "preCost" ] = 0 remain = self . task [ "amount" ] if pos : self . task [ "dealAmount" ] = pos [ "Amount" ] - self . task [ "preAmount" ] remain = int ( self . task [ "amount" ] - self . task [ "dealAmount" ]) if remain <= 0 or self . task [ "retry" ] >= MaxTaskRetry : ret = { "price" : ( pos [ "Cost" ] - self . task [ "preCost" ]) / ( pos [ "Amount" ] - self . task [ "preAmount" ]), "amount" : ( pos [ "Amount" ] - self . task [ "preAmount" ]), "position" : pos } break elif self . task [ "retry" ] >= MaxTaskRetry : ret = None break depth = exchange . GetDepth () if depth is None : return Manager . ERR_GET_DEPTH orderId = None if self . task [ "action" ] == Manager . ACT_LONG : exchange . SetDirection ( "buy" ) orderId = exchange . Buy ( _N ( depth [ "Asks" ][ 0 ][ "Price" ] + ( insDetail [ "PriceTick" ] * SlideTick ), 2 ), min ( remain , depth [ "Asks" ][ 0 ][ "Amount" ]), self . symbol , "Ask" , depth [ "Asks" ][ 0 ]) else : exchange . SetDirection ( "sell" ) orderId = exchange . Sell ( _N ( depth [ "Bids" ][ 0 ][ "Price" ] - ( insDetail [ "PriceTick" ] * SlideTick ), 2 ), min ( remain , depth [ "Bids" ][ 0 ][ "Amount" ]), self . symbol , "Bid" , depth [ "Bids" ][ 0 ]) if orderId is None : self . task [ "retry" ] += 1 return Manager . ERR_TRADE if self . task [ "onFinish" ]: self . task [ "onFinish" ]( ret ) self . setTask ( Manager . ACT_IDLE ) return Manager . ERR_SUCCESS def Poll ( self , subroutine = False ): # 判断交易时段 self . status [ "isTrading" ] = ext . IsTrading ( self . symbol ) if not self . status [ "isTrading" ]: return # 执行下单交易任务 if self . task [ "action" ] != Manager . ACT_IDLE : retCode = self . processTask () if self . task [ "action" ] != Manager . ACT_IDLE : self . setLastError ( "任务没有处理成功:" + Manager . errMsg [ retCode ] + ", " + self . task [ "desc" ] + ", 重试:" + str ( self . task [ "retry" ])) else : self . setLastError () return if subroutine : return suffix = "@" if WXPush else "" # switch symbol _C ( exchange . SetContractType , self . symbol ) # 获取K线数据 records = exchange . GetRecords () if records is None : self . setLastError ( "获取K线失败" ) return self . status [ "recordsLen" ] = len ( records ) if len ( records ) < self . fastPeriod + 2 or len ( records ) < self . slowPeriod + 2 : self . setLastError ( "K线长度小于 均线周期:" + str ( self . fastPeriod ) + "或" + str ( self . slowPeriod )) return opCode = 0 # 0 : IDLE , 1 : LONG , 2 : SHORT , 3 : CoverALL lastPrice = records [ - 1 ][ "Close" ] self . lastPrice = lastPrice fastMA = TA . EMA ( records , self . fastPeriod ) slowMA = TA . EMA ( records , self . slowPeriod ) # 策略逻辑 if self . marketPosition == 0 : if fastMA [ - 3 ] < slowMA [ - 3 ] and fastMA [ - 2 ] > slowMA [ - 2 ]: opCode = 1 elif fastMA [ - 3 ] > slowMA [ - 3 ] and fastMA [ - 2 ] < slowMA [ - 2 ]: opCode = 2 else : if self . marketPosition < 0 and fastMA [ - 3 ] < slowMA [ - 3 ] and fastMA [ - 2 ] > slowMA [ - 2 ]: opCode = 3 elif self . marketPosition > 0 and fastMA [ - 3 ] > slowMA [ - 3 ] and fastMA [ - 2 ] < slowMA [ - 2 ]: opCode = 3 # 如果不触发任何条件,操作码为0,返回 if opCode == 0 : return # 执行平仓 if opCode == 3 : def coverCallBack ( ret ): self . reset () _G ( self . symbol , None ) self . setTask ( Manager . ACT_COVER , 0 , coverCallBack ) return account = _bot . GetAccount () canOpen = int (( account [ "Balance" ] - self . keepBalance ) / ( self . symbolDetail [ "LongMarginRatio" ] if opCode == 1 else self . symbolDetail [ "ShortMarginRatio" ]) / ( lastPrice * 1.2 ) / self . symbolDetail [ "VolumeMultiple" ]) unit = min ( 1 , canOpen ) # 设置交易任务 def setTaskCallBack ( ret ): if not ret : self . setLastError ( "下单失败" ) return self . holdPrice = ret [ "position" ][ "Price" ] self . holdAmount = ret [ "position" ][ "Amount" ] self . marketPosition += 1 if opCode == 1 else - 1 self . status [ "vm" ] = [ self . marketPosition ] _G ( self . symbol , self . status [ "vm" ]) self . setTask ( Manager . ACT_LONG if opCode == 1 else Manager . ACT_SHORT , unit , setTaskCallBack ) def onexit (): Log ( "已退出策略..." ) def main (): if exchange . GetName (). find ( "CTP" ) == - 1 : raise Exception ( "只支持商品期货CTP" ) SetErrorFilter ( "login|ready|流控|连接失败|初始|Timeout" ) mode = exchange . IO ( "mode" , 0 ) if mode is None : raise Exception ( "切换模式失败,请更新到最新托管者!" ) while not exchange . IO ( "status" ): Sleep ( 3000 ) LogStatus ( "正在等待与交易服务器连接," + _D ()) positions = _C ( exchange . GetPosition ) if len ( positions ) > 0 : Log ( "检测到当前持有仓位,系统将开始尝试恢复进度..." ) Log ( "持仓信息:" , positions ) initAccount = _bot . GetAccount () initMargin = json . loads ( exchange . GetRawJSON ())[ "CurrMargin" ] keepBalance = _N (( initAccount [ "Balance" ] + initMargin ) * ( KeepRatio / 100 ), 3 ) Log ( "资产信息" , initAccount , "保留资金:" , keepBalance ) tts = [] symbolFilter = {} arr = Instruments . split ( "," ) arrFastPeriod = FastPeriodArr . split ( "," ) arrSlowPeriod = SlowPeriodArr . split ( "," ) if len ( arr ) != len ( arrFastPeriod ) or len ( arr ) != len ( arrSlowPeriod ): raise Exception ( "均线周期参数与添加合约数量不匹配,请检查参数!" ) for i in range ( len ( arr )): symbol = re . sub ( r '/\s+$/g' , "" , re . sub ( r '/^\s+/g' , "" , arr [ i ])) if symbol in symbolFilter . keys (): raise Exception ( symbol + "已经存在,请检查参数!" ) symbolFilter [ symbol ] = True hasPosition = False for j in range ( len ( positions )): if positions [ j ][ "ContractType" ] == symbol : hasPosition = True break fastPeriod = int ( arrFastPeriod [ i ]) slowPeriod = int ( arrSlowPeriod [ i ]) obj = Manager ( hasPosition , symbol , keepBalance , fastPeriod , slowPeriod ) tts . append ( obj ) preTotalHold = - 1 lastStatus = "" while True : if GetCommand () == "暂停/继续" : Log ( "暂停交易中..." ) while GetCommand () != "暂停/继续" : Sleep ( 1000 ) Log ( "继续交易中..." ) while not exchange . IO ( "status" ): Sleep ( 3000 ) LogStatus ( "正在等待与交易服务器连接," + _D () + "\n" + lastStatus ) tblStatus = { "type" : "table" , "title" : "持仓信息" , "cols" : [ "合约名称" , "持仓方向" , "持仓均价" , "持仓数量" , "持仓盈亏" , "加仓次数" , "当前价格" ], "rows" : [] } tblMarket = { "type" : "table" , "title" : "运行状态" , "cols" : [ "合约名称" , "合约乘数" , "保证金率" , "交易时间" , "柱线长度" , "异常描述" , "发生时间" ], "rows" : [] } totalHold = 0 vmStatus = {} ts = time . time () holdSymbol = 0 for i in range ( len ( tts )): tts [ i ]. Poll () d = tts [ i ]. Status () if d [ "holdAmount" ] > 0 : vmStatus [ d [ "symbol" ]] = d [ "vm" ] holdSymbol += 1 tblStatus [ "rows" ]. append ([ d [ "symbolDetail" ][ "InstrumentName" ], "--" if d [ "holdAmount" ] == 0 else ( "多" if d [ "marketPosition" ] > 0 else "空" ), d [ "holdPrice" ], d [ "holdAmount" ], d [ "holdProfit" ], abs ( d [ "marketPosition" ]), d [ "lastPrice" ]]) tblMarket [ "rows" ]. append ([ d [ "symbolDetail" ][ "InstrumentName" ], d [ "symbolDetail" ][ "VolumeMultiple" ], str ( _N ( d [ "symbolDetail" ][ "LongMarginRatio" ], 4 )) + "/" + str ( _N ( d [ "symbolDetail" ][ "ShortMarginRatio" ], 4 )), "是#0000ff" if d [ "isTrading" ] else "否#ff0000" , d [ "recordsLen" ], d [ "lastErr" ], d [ "lastErrTime" ]]) totalHold += abs ( d [ "holdAmount" ]) now = time . time () elapsed = now - ts tblAssets = _bot . GetAccount ( True ) nowAccount = _bot . Account () if len ( tblAssets [ "rows" ]) > 10 : tblAssets [ "rows" ][ 0 ] = [ "InitAccount" , "初始资产" , initAccount ] else : tblAssets [ "rows" ]. insert ( 0 , [ "NowAccount" , "当前可用" , nowAccount ]) tblAssets [ "rows" ]. insert ( 0 , [ "InitAccount" , "初始资产" , initAccount ]) lastStatus = "`" + json . dumps ([ tblStatus , tblMarket , tblAssets ]) + "`\n轮询耗时:" + str ( elapsed ) + " 秒,当前时间:" + _D () + ", 持有品种个数:" + str ( holdSymbol ) if totalHold > 0 : lastStatus += "\n手动恢复字符串:" + json . dumps ( vmStatus ) LogStatus ( lastStatus ) if preTotalHold > 0 and totalHold == 0 : LogProfit ( nowAccount . Balance - initAccount . Balance - initMargin ) preTotalHold = totalHold Sleep ( LoopInterval * 1000 )
策略地址: https://www.fmz.com/strategy/208512

回测对比
我们用该策略的JavaScript版本和Python版本回测进行对比。 Python版本回测
我们使用公共服务器进行回测,可以看到Python版本的回测略微快了一点。
JavaScript版本回测
可以看到回测结果一模一样,有兴趣的小伙伴可以钻研一下代码,会有不小的收获。

花里胡哨的扩展
我们来做个扩展示范,给策略扩展出图表功能,如图:
主要增加代码部分: 给 Manager 类增加一个成员: objChart 给 Manager 类增加一个方法: PlotRecords
其它的一些修改都是围绕这两点进行,可以对比两个版本区别,学习扩展功能的思路。
python版商品期货多品种均线策略 (扩展图表)
以上策略学习为主,实盘慎用。
欢迎留言。
区块链
2020-06-16 09:25:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
简介
我们知道比特币就是挖矿产生的,那么在比特币网络中,挖矿有什么特点呢?怎么分配挖矿收入呢?在这篇文章中你都能找到答案。
比特币的节点构造
上篇文章我们提到了,比特币是一个P2P网络,P2P网络中就有很多个节点,从P2P的定义来看,各个节点的地位是相同的,其实不然。比特币网络的节点各有作用。
我们先来看一个总体的图,比特币节点总共有4种类型:
这四种类型分别是钱包,挖矿节点,全节点,和网络路由节点。
不同的角色组合成了一个庞大的比特币网络。根据功能的不同,不同的角色可能需要不同的类型。
上面我们介绍了7个常见的节点。 Bitcoin Core 这个是你在官方下载的bitcoin软件,它包含了4中类型的功能。 Full Block Chain Node,这个节点包含了所有的比特币区块链历史的信息,叫做全节点,全节点主要用来做历史交易的验证。 Solo Miner,这个是独立的挖矿节点。 SPV wallet, 这个是我们之前介绍的轻量级的钱包。 Pool Protocol Servers, 这个是矿池连接比特币网络的网关。 注意,比特网网络除了自身的P2P网络协议之外,还有一个Stratum协议,Stratum协议被应用于挖矿、以及轻量级或移动端比特币钱包之中。 Mining Nodes,这是连接到比特币矿池的矿机节点。 SPV stratum wallet, 使用Stratum协议的轻量级钱包。
这些节点组合在一起,构成了庞大的比特币网络。
挖矿
挖矿是增加比特币货币供应的一个过程。挖矿同时还保护着比特币系统的安全,防止欺诈交易,避免“双重支付”,“双重支付”是指多次花费同一笔比特币。矿工们通过为比特币网络提供算力来换取获得比特币奖励的机会。
每10分钟就会有一个新的区块被“挖掘”出来,每个区块里包含着从上一个区块产生到目前这段时间内 发生的所有交易,这些交易被依次添加到区块链中
矿工们在挖矿过程中会得到两种类型的奖励:创建新区块的新币奖励,以及区块中所含交易的交易费。为了得到这些奖励,矿工们争相完成一种基于加密哈希 算法的数学难题,这些难题的答案包括在新区块中,作为矿工的计算工作量的证明,被称为”“工作量证明”。该算法的竞争的机制以及获胜者有权在区块链上进行 交易记录的机制,这二者比特币安全的基石。
新比特币的生成过程被称为挖矿是因为它的奖励机制被设计为速度递减模式,类似于贵重金属的挖矿过程。比特币的货币是通过挖矿发行的,类似于中央银行 通过印刷银行纸币来发行货币。
矿工通过创造一个新区块得到的比特币数量大约每四年(或准确说是每隔210,000个块)减少一半。开始时为2009年1月 每个区块奖励50个比特币,然后到2012年11月减半为每个区块奖励25个比特币。之后将在2016年的某个时刻再次减半为每个新区块奖励12.5个比 特币。基于这个公式,比特币挖矿奖励以指数方式递减,直到2140年。届时所有的比特币(20,999,999,980)全部发行完毕。
换句话说在 2140年之后,不会再有新的比特币产生。(通货紧缩货币)
挖矿节点
在比特币网络中,一些节点被称为专业节点矿工。
与其他任一完整节点相同,这些节点在比特币网络中进行接收和传播未确认交易记录。然而,这些节点也能够在新区块中整合这些交易记录。
矿工间的竞争以新区块的传播而 结束,如同宣布谁是最后的赢家。对于矿工们来说,获得一个新区块意味着某个参与者赢了,而他们则输了这场竞争。然而,一轮竞争的结束也代表着下一轮竞争的 开始。新区块并不仅仅是象征着竞赛结束的方格旗;它也是下一个区块竞赛的发令枪。
创币交易
区块中的第一笔交易是笔特殊交易,称为创币交易或者coinbase交易。
这个交易是由挖矿节点构造并用来奖励矿工们所做的贡献的。挖矿节点会创建“向XX的地址支付25.09094928个比特币”这样一个交易,把生成交易的奖励发送到自己的钱包。矿工挖出区块获得的奖励金额 是coinbase奖励(25个全新的比特币)和区块中全部交易矿工费的总和。
与常规交易不同,创币交易没有输入,不消耗UTXO。它只包含一个被称作coinbase的输入,仅仅用来创建新的比特币。
创币交易有一个输出,支付到这个矿工的比特币地址。
矿池收入分配
根据矿池的收入分配不同,可以分为两种。 PPLNS
全称Pay Per Last N Shares,意思是说“根据过去的N个股份来支付收益”,这意味着,所有的矿工一旦发现了一个区块,大家将根据每个人自己贡献的股份数量占比来分配区块中的货币。 PPS
PPS矿池(类似于打工模式)PPS全称为Pay Per Share。为了解决PPLNS那种有时候收益很高,有时候没有收益的情况,PPS采用了新的算法。PPS根据你的算力在矿池中的占比,并估算了矿池每天可以获得的矿产,给你每天基本固定的收益。
挖矿方向
从2009年开始,原来普通的计算机就可以“挖矿”,但是到了2014年,所有挖矿的计算机也变成由专业设计芯片公司为比特币度身定制的“矿机”。
随着参与挖矿的计算机变得越来越昂贵,比特币生产的成本也水涨船高。截止到2014年10月,每个比特币生产的成本已经达到接近3000元人民币。这个生产包括计算机的生产制造成本,生产过程中产生的电费,以及人员费用和场地费用。也就是说在2016年年底之前,因为每天生产3600个比特币,每天所投入的资金就达到1000万元人民币。并且随着竞争越来越激烈,这个成本还在处于上升阶段。
算力浪费
那么挖矿花了这么多电费到底做了什么事情呢?无他,就是算一个hash值而已。
所以这造成严重的浪费。当然也有人想出了一些解决办法,使用这些算力去做些有用的事情: Sunny King的素数币 质数币(PrimeCoin代码XPM)寻找质数 格雷德币(GridCoin代码GRC)分布式科学计算
算力调整
注意比特币的挖矿难点并不是一定增加的。它是动态调整的。
如果在上个周期(2016个区块)中平均区块产生时间大于10分钟,也就是全网算力下降的情况下,则在当前周期的难度就会下降,使得区块产生时间加快。不过目前为止好像还没有出现过全网算力下降的情况,难度是一直增加。
由于是基于事后统计,所以难度的变化会滞后于全网算力的变化1~2个周期。如果全网算力增加,则在这1~2个周期中挖矿速度加快,则挖矿收益增多;反之,收益减少。但是从长期来看还是保持平衡。
总结
本文介绍了比特币网络中挖矿相关的内容,希望大家能够喜欢。 本文作者:flydean程序那些事
本文链接: http://www.flydean.com/bitcoin-mine-consensus/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
区块链
2020-06-26 11:18:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
简介
钱包在比特币中是做什么的呢?比特币的交易又有什么特点呢?怎么才能伪造比特币的交易呢?今天和大家一起学习一下比特币中的钱包和交易。
比特币密码学的基础
之前我们提到过比特币使用的并不是什么新技术,只是对于老的技术比如:P2P网络,分布式系统,密码学,共识算法的重新而又巧妙的应用。
在钱包和交易生成验证的过程中,都需要使用到密码学的计算。这里我们先介绍一下比特币中会使用到的几种密码学技术。
更多精彩内容且看: 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新 Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新 Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新 java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
单向散列函数(hash算法)
在介绍单向散列函数之前,我们先了解一下什么情况下需要使用到单向散列函数。
如果你需要从国外的网站上下载一个软件,但是因为种种原因,国外的网络太慢了,下载几个G的数据几乎是不可能的。刚好国内有镜像网站,可以从国内下载数据。但是如何保证国内的镜像不是被篡改过后的呢?这个时候就需要单向散列函数了。一般来说网站会提供MD5或者SHA的值作为验证值。
单向散列函数有一个输入和输出。输入称为消息,输出称为散列值。
散列值的长度跟消息的长度无关,不论多少大小的长度的消息,都会计算出固定长度的散列值。
hash算法有下面几个特点: 能够根据任意长度的消息计算出固定长度的散列值。 计算速度要快。 消息不同,散列值也不同。
这就意味着,如果仅仅是一点点的变动都会引起整个散列值的巨大变化。
因为散列值的大小是固定的,所以有可能会出现不同的消息产生相同散列值的情况。这种情况叫做碰撞。
难以发现碰撞的性质被称为抗碰撞性。当给定某条消息的散列值时,必须保证很难找到和该消息具有相同散列值的另一条消息。 单向散列函数必须具有单向性。所谓单向性是指无法通过散列值来反推出消息的性质。
比特币使用的散列算法是SHA256,他是安全散列算法SHA(Secure Hash Algorithm)系列算法的一种(另外还有SHA-1、SHA-224、SHA-384 和 SHA-512 等变体),SHA是美国国家安全局 (NSA) 设计,美国国家标准与技术研究院(NIST) 发布的,主要适用于数字签名标准(DigitalSignature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。
RIPEMD(RACE Integrity Primitives Evaluation Message Digest,RACE原始完整性校验消息摘要),是Hans Dobbertin等3人在md4,md5的基础上,于1996年提出来的。
非对称加密算法
非对称加密算法也叫公钥密码算法,通过生成的公私钥来对明文密文进行加密解密。
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
扩展阅读:同态加密
同态加密是一种加密形式,它允许人们对密文进行特定的代数运算得到仍然是加密的结果,将其解密所得到的结果与对明文进行同样的运算结果一样。换言之,这项技术令人们可以在加密的数据中进行诸如检索、比较等操作,得出正确的结果,而在整个处理过程中无需对数据进行解密。其意义在于,真正从根本上解决将数据及其操作委托给第三方时的保密问题,例如对于各种云计算的应用。
密钥,地址和钱包
比特币的所有权是通过数字密钥、比特币地址和数字签名来确立的。数字密钥实际上并不是存储在网络中,而是由用户生成并存储在一个文件或简单的数据库 中,称为钱包。存储在用户钱包中的数字密钥完全独立于比特币协议,可由用户的钱包软件生成并管理,而无需区块链或网络连接。密钥实现了比特币的许多有趣特性,包括去中心化信任和控制、所有权认证和基于密码学证明的安全模型。
比特币钱包只包含私钥而不是比特币。每一个用户有一个包含多个私钥的钱包。钱包中包含成对的私钥和公钥。用户用这些私钥来签名交易,从而证明它们拥有交易的输出(也就是其中的比特币)。比特币是以交易输出的形式来储存在区块链中(通常记为vout或txout)。
如果钱包只包含私钥,那么钱包地址是什么呢?钱包地址是从公钥的hash值的出来的,如下图所示:
首先使用随机数发生器生成一个『私钥』。一般来说这是一个256bits的数,拥有了这串数字就可以对相应『钱包地址』中的比特币进行操作,所以必须被安全地保存起来。 『私钥』经过SECP256K1算法处理生成了『公钥』。SECP256K1是一种椭圆曲线算法,通过一个已知『私钥』时可以算得『公钥』,而『公钥』已知时却无法反向计算出『私钥』。这是保障比特币安全的算法基础。 同SHA256一样,RIPEMD160也是一种Hash算法,由『公钥』可以计算得到『公钥哈希』,而反过来是行不通的。 将一个字节的地址版本号连接到『公钥哈希』头部(对于比特币网络的pubkey地址,这一字节为“0”),然后对其进行两次SHA256运算,将结果的前4字节作为『公钥哈希』的校验值,连接在其尾部。 将上一步结果使用BASE58进行编码(比特币定制版本),就得到了『钱包地址』。 比如,1A1zP1eP5QGefi2DMPTfTL5TTmv7DivfNa。
所以私钥,公钥和钱包地址的关系如下图所示:
大家看到钱包地址1A1zP1eP5QGefi2DMPTfTL5TTmv7DivfNa有什么想法呢?
肯定有人在想,这么一大长串字母和数字实在是太不好记忆了。能不能生产一个比较好记的钱包地址呢? 比如MyNameIsHanMeiMei....这样开头的地址呢?
当然可以,这叫做靓号地址,只不过需要大量的算力才行。
比特币中的交易
简单来说,交易就是告知全网:比特币的持有者已授权把比特币转帐给其他人。而新持有者能够再次授权,转移给该比特币所有权链中的其他人。 注意, 在比特币的世界里既没有账户,也没有余额,只有分散到区块链里的UTXO(Unspent Transaction Outputs)。
怎么理解这个UTXO呢?没有账户也没有余额,那么钱包里面的金额是怎么计算出来的呢?
别急,让我们一一道来。
话说,在比特币中,比特币钱包间的转账是通过交易(Transaction)实现的。
我们看一个标准的交易流程。
那么问题来了,世界上第一个比特币是哪里来的呢?
答,是挖矿来的。好了,我们的001交易表示的就是一个挖矿的过程,在这个交易中,输入就是挖矿,输出编号1,BTC数目是50,目的地址是A,表示这50个BTC给A了。
接下来,A想发25个BTC给B,怎么构造这个交易呢?
同样的,我们需要一个输入,这个输入就是001交易的1号输出,我们用001.1来表示。输出分为两个,第一个输出编号1,表示要付25个BTC给B。第二个输出编号2,表示剩下的BTC要还给A。
大家可能会问了,输入是50BTC,两个输出加起来才45个BTC,好像还少了5个BTC?没错,这个5个BTC就是给矿工的挖矿所得。
接下来,A又继续转账给C,同样的道理,把一个一个的交易连接起来。
从上面的例子我们可以看到,实际上钱是存在一个一个的交易记录里面的,那些未被花费的输出,就叫做UTXO(Unspent Transaction Outputs)。
那么怎么保证转账给B的钱,不会被其他的人消费呢?这就涉及到交易的加密过程了。
我们以单个输入和输出为例来详细了解一下交易的构成:
上图中,交易的输入就是txid,也就是之前生成的还有未花费暑输出的交易ID。output index就是交易的输出id。
一个非常重要的ScriptSig是输入交易的验证,表明这个用户拥有这个账户的转账权限。
输出是一个脚本,只有满足脚本运行条件的人才能花费这个output。这也就是ScriptSig需要验证的脚本。
我们看下脚本是怎么做认证的吧。
比特币的标准输出形式有两种。Pay To Public Key Hash (P2PKH) 和 Pay To Script Hash (P2SH)。两者的区别在于,一个是输出到public key的hash,一个是输出到任意的一个脚本输出hash。
为了保证输出只能由特定的人来花费,一般的情况下是直接输出到对方的public key hash。由于只有对方拥有的私钥能够生成这个public key hash,也就是说只有对方才能够对这个输出进行验证。
但每次都需要知道对方的public key hash还是比较麻烦的,更简单的做法就是,发送者直接输出到一个特定的hash值就行了,只要对方能够生成这个hash就可以。
下面的例子是一个P2PKH的脚本形式。
P2PKH的输出是一个脚本,里面一个重要的值就是PK hash。
怎么验证呢?
验证方提供两个值,一个是sig,一个是PubKey。因为比特币的虚拟机是栈结构的,我们先把这两个值入栈。
然后调用OP_DUP对最上层的PubKey进行拷贝,然后调用OP_HASH160算法来计算Pk Hash,然后将发送方保存的Pk Hash入栈。接下来调用OP_EQUALVERIFY对两个PK Hash进行对比。
如果对比成功,最后一步就是验证Sig和PubKey是否匹配。
如果都成功,说明接收方的确是这个PK Hash的拥有者。那么对方就可以尽情使用了。
扩展阅读:图灵非完备性
和冯·诺伊曼同为现代计算机奠基人的阿兰·图灵(AlanTurin)在1950年提出了判定计算机能否像人那般实际“思考”的标准,也就是著名的“图灵检验”。
他设想一台超级计算机和一个人躲藏在幕后回答提问者的问题,而提问者则试图分辨哪个是人哪个是计算机。
图灵争辩说,假如计算机伪装得如此巧妙,以致没有人可以在实际上把它和一个真人分辨开来的话,那么我们就可以声称,这台计算机和人一样具备了思考能力,或者说,意识(他的原词是“智慧”)。
在可计算性理论里,如果一系列操作数据的规则(如指令集、编程语言、细胞自动机)按照一定的顺序可以计算出结果,被称为图灵完备(turing complete)。
比特币脚本语言不是图灵完备的,具有一定的局限性,它没有循环语句和复杂的条件控制语句。
总结
本文介绍了比特币的钱包和交易的概念,希望大家能够喜欢。 本文作者:flydean程序那些事
本文链接: http://www.flydean.com/bitcoin-transactions/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
区块链
2020-06-20 07:27:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
#百度超级链学院·公开课#
开发者福利来袭!
还在为如何降低合约开发成本而苦恼?本期公开课将带你解锁一款超好用、超低开发成本的智能合约工具xdev。
【主讲嘉宾】:樊冰新 百度资深研发工程师
【课程简介】:使用xdev创建和编译合约工程、管理第三方合约library、测试合约,以及xdev和vscode的集成方法。
【时间】:5月21日 20:00
【直播预约链接】:
http://abcxueyuan.cloud.baidu.com/#/live_detail?liveId=237&linkToken=xf5Ik

区块链
2020-05-20 21:09:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Wiz工具箱可以快速搭建一个Hyperledger Fabric开发网络作为链码和应用开发环境,官方下载地址: http://sc.hubwiz.com/codebag/fabric-wiz/ 。
Wiz工具箱的主要特性如下: 内置原生Fabric 1.4 LTS版本,无需虚拟机/Docker等复杂环境安装 内置多语言Fabric链码模板和应用模板,支持Go、Java和JavaScript 支持Fabric区块链链码和应用开发流程的完整命令集
Wiz工具箱目前支持Linux和OSX,Windows环境下可以使用 BYFN一键启动工具 快速搭建Fabric区块链开发环境。
2、使用Wiz工具箱
启动Fabric网络需要使用三个终端,分别称为1#、2#和3#。
STEP 1 :在1#终端创建一个新目录 devnet 用来初始化fabric项目。例如下面的命令选择 JavaScript 作为链码和应用开发语言进行初始化: ~$ mkdir devnet && cd devnet ~/devnet$ wiz init js
结果如下:
初始化之后的项目目录结构如下: network :fabric网络定义与配置数据目录 chaincode :链码源代码目录 application :应用源代码目录 script :Wiz工具箱脚本目录
wiz工具箱目前支持三种开发语言,在执行 wiz init 命令时需要声明项目的开发语言,以便wiz工具箱生成正确的项目代码: go :项目链码和应用开发语言:golang java :项目链码和应用开发语言:java js :项目链码和应用开发语言:javascript
STEP 2 :在1#终端使用 wiz net reset 初始化Fabric网络的密码学资料和通道 初始化交易资料: ~/devnet$ wiz net reset
结果如下:
STEP 3 :在1#终端使用 wiz net start 启动Fabric网络的peer节点和orderer节点: ~/devnet$ wiz net start
结果如下:
Wiz工具箱提供的Fabric开发网络中包含单一的peer节点和orderer节点,网络配置描述如下: 机构:Org1 MSPID:Org1MSP 通道名称:ch1 链码名称:wizcc 排序节点:127.0.0.1:7050 对等节点:127.0.0.1:7051/7052
STEP 4 :在2#终端使用 wiz cc start 启动wiz工具箱预置的链码: ~/devnet$ wiz cc start
结果如下:
STEP 5 :在3#终端使用 wiz ch start 命令创建通道 ch1 并将peer节点加入通道: ~/fabric-chaincode-python/devnet$ wiz ch start
结果如下:
测试链码 :在3#终端使用 wiz admin 命令进入管理控制台: ~/fabric-chaincode-python/devnet$ wiz admin
结果如下:
使用 peer chaincode query 命令测试预置链码的查询: admin@org1> peer chaincode query -n wizcc -c '{"args":[]}' -C ch1
结果如下:
使用 peer chaincode invoke 命令测试预置链码的交易: admin@org1> peer chaincode invoke -n wizcc -c '{"args":[]}' -C ch1
结果如下:
3、Wiz工具箱命令速查表
Fabric区块链快速开发工具箱下载地址: http://sc.hubwiz.com/codebag/fabric-wiz/
区块链
2020-06-01 20:00:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
2020年4月20日,国家发展改革委通过互联网举行了4月份新闻发布会。会议指出:新型基础设施是以新发展理念为引领,以技术创新为驱动,以信息网络为基础,面向高质量发展需要,提供数字转型、智能升级、融合创新等服务的基础设施体系。
当天阿里云就宣布:在未来3年再投2000亿元,用于云操作系统、服务器、芯片、网络等重大核心技术研发攻坚和面向未来的数据中心建设。
5月26日,腾讯也宣布将在5年投资5000亿元,用于云计算、人工智能、区块链、大型数据中心、超算中心、物联网操作系统、5G 网络等领域,并将陆续在全国新建多个百万级服务器规模的大型数据中心。
先阿里,后腾讯,两拨操作猛如虎,一个3年2000亿话音未落。一个5年5000亿再掀高潮,新基建的牌桌,筹码越堆越高。
目前来看,新型基础设施主要包括三个方面内容:
一、信息基础设施
主要是指基于新一代信息技术演化生成的基础设施,比如,以5G、物联网、工业互联网、卫星互联网为代表的通信网络基础设施,以人工智能、云计算、区块链等为代表的新技术基础设施,以数据中心、智能计算中心为代表的算力基础设施等。
二、融合基础设施
主要是指深度应用互联网、大数据、人工智能等技术,支撑传统基础设施转型升级,进而形成的融合基础设施,比如,智能交通基础设施、智慧能源基础设施等。
三、创新基础设施
主要是指支撑科学研究、技术开发、产品研制的具有公益属性的基础设施,比如,重大科技基础设施、科教基础设施、产业技术创新基础设施等。
至此,国家发展改革委正式明确了区块链是“新基建”的基础设施,正式将区块链纳入“新基建”范畴。
中心化存储能迎接5G时代的数据浪潮吗?
不难看出,在未来新基建的建设中,无论是5G、AI、物联网,还是人工智能或者大数据的应用,都需要极其庞大的数据来作为支撑。
就拿5G来说,在未来的数字化世界里,5G联接了千行百业,就像道路一样,为我们构造了“新联接”,可以预见的是,5G和物联网等的到来必然会带来数据的激增,毕竟,一辆自动驾驶的汽车,一天就能产生64TB的数据,足以填满32块硬盘。
而阿里云与腾讯这两大巨头正是看到了现在与未来这一迫切的需求,才会着重与数据中心的建设,但是,随着5G时代的来临数据的爆发增长,中心化存储的弊端也逐渐显露,如:不安全、成本过于高昂、集中化、效率低...,尤其近两年中心化存储事件更是屡出不穷,如:信息泄漏、某云宕机、黑客攻击,由此造成的损失更是无法估量,可以看出中心化存储已经不堪重负。
因此,面对海啸般爆发式增长的数据有没有更高安全、高效率的的存储方式呢?
有的,致力于存储的区块链分布式存储项目,IPFS/Filecoin无疑是最佳选择!
IPFS能为新基建做什么?
Filecoin是基于区块链的分布式存储,其共识算法:复制证明、时空证明,也能够保护我们的数据能够被有效地存储。由于数据将分散存储,黑客很难找到进入系统的单一入口。IPFS可以极大的降低对中心主干网络的依赖,提高互联网数据的安全性,有效防御DDoS、XSS、CSRF等攻击。并可以按照我们的要求保存数据,数据安全指数也得到提高。
那么数据的隐私该如何保障呢?其实,所有Filecoin中存储的数据都是自我认证的,这种自我认证来自散列函数的功能。哈希函数是特殊的数学实体,如果输入的数据,会得到一个独一无二的指纹叫哈希值。哈希相当于指纹。他的特点是唯一性。并且我们无法从指纹中重建一个人。这意味着散列是唯一的标识符而且不会损害原始数据的隐私性,不能仅从散列中复制数据。
新基建的建设,数据的大爆发,IPFS/Filecoin或将成为数据的“守护者”,助力解决数据存储瓶颈和数据安全问题。新基建中将区块链纳入范围,让我们看到了IPFS/Filecoin在存储应用的巨大潜力。新基建的建设,也将推动IPFS/Filecoin的发展。结合了IPFS/Filecoin技术的新基建,定能在未来步入超高速轨道。
区块链
2020-06-03 16:18:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
零知识证明可以在不泄露具体信息的情况下向其他人证明自己掌握该信息,这听起来非常适合去中心化应用。在这个教程中,我们将利用zksnark来实现一个具体的NodeJS零知识证明应用:渔船无需透露自己的具体位置,就可以向监管机构证明自己处于划定的合法捕捞区内 —— 我们的主要武器是snarkjs和circom。
用自己熟悉的语言学习以太坊DApp开发: Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、需求分析
设计零知识证明应用方案的第一步是要将具体的问题转换为一个电路。我们要证明渔船处于合法捕捞区内,这个问题中存在以下变量: 合法捕捞区的范围,可以用该区域的经度/维度的最大值和最小值来表示渔船的位置,用渔船的经度和维度来表示
容易得到如下的输入输出映射: +--------------+ 渔船经度/维度 ->| | | | 捕捞区经度最大/最小值 ->| 电路 |-> 在/不在合法捕捞区 | | 捕捞区纬度最大/最小值 ->| | +--------------+
2、circom电路实现
据此,我们可以得到如下的circom电路定义:
其中: latitudeRange:电路输入,表示合法捕捞区域的纬度的最小值和最大值,数组 longitudeRange:电路输入,表示合法捕捞区域的经度的最小值和最大值,数组 fishingLocation:电路输入,表示渔船的经度和维度,数组 out:电路输出,1表示渔船在合法捕捞区,0表示渔船不在合法捕捞区
由于我们要隐藏渔船的具体位置,因此在上面的circom电路中,你可以看到fishingLocation被定义为private。
3、circom电路编译
如果还没有安装circom的话,使用如下命令全局安装circom: npm install -g circom
注意:推荐使用node 12,因为内置了原生的大数计算,效率提升10倍!
使用如下命令编译电路文件InRange.circom,输出结果命名为InRange.json: circom InRange.circom -o InRange.json
4、zksnark的可信设置
在使用zksnark之前,需要一个可信设置,而且该可信设置依赖于具体的电路,例如我们编译得到的InRange.json。
使用snarkjs来创建这个可信设置,同样,如果需要安装的话,使用如下命令: npm install -g snarkjs
现在我们利用渔业监控电路进行可信设置: snarkjs setup -c InRange.json
上面的命令将会在当前目录创建两个文件:proving_key.json和verification_key.json。其中proving_key.json用于证明你的输入是有效的(满足电路约束),而verification_key.json用来验证别人提供的证据。
5、计算ziksarnk电路信号的见证(witness)
在我们创建提供给其他人的证据之前,需要先计算出电路中所有信号(包括输入信号和中间信号) 的见证。为此我们需要创建一个输入文件input.json,其中包含所有输入(公开输入和私有输入)的值,然后利用这个输入文件计算得到见证文件witness.json,这两个文件都不会公开。
下面是我们的渔业监控电路的输入文件示例: { "latitudeRange": [ 20, 21], "longitudeRange": [ 176, 190], "fishingLocation": [ 20, 180] }
使用sparkjs来计算得出见证文件witness.json: snarkjs calculatewitness -c InRange.json
6、创建zksnark证据
有了witness.json,我们就可以创建提供给其他人的证据了: snarkjs proof
上面的命令将在当前目录生成proof.json和公开文件public.json,publc.json实际上就是witness.json文件内容的一个子集,其中仅包含电路中可公开信号的值。
现在目录里的文件如下图所示:
7、校验zksnark证据
现在你(渔船船长)可以把verification_key.json、proof.json和public.json提供给监管机构了,监管方使用如下命令即可验证你的船的确在合法捕捞区内,但却不知道你的具体位置: snarkjs verify
GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD!
原文链接: 零知识证明实战渔业监 — 汇智网
区块链
2020-05-11 10:12:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
2020年全球因为疫情的原因,经济一度低迷,包括比特币也没如投资者预期那样,减半期间价格起飞。而Filecoin成为2020年最备受期待的加密货币,在日渐火热的进展下,无数项目与之挂钩,希望通过蹭热度获得相应的流量。
那Filecoin最近到底有多火?4月18日,WBF交易所将FIL6期货价格拉高至6500美元,比肩目前比特币的价格,让无数投资者震惊。
即使目前价格已经下来,但是FIL6期货在WBF交易所的交易价格还是偏高,213美元/1500多元,这个价格已经达到大多数投资者对Filecoin上线后的价格预期。
在如此高涨的价格下,FIL期货到底能不能买?我们可以看下官方的回答。
更多问题与解答请咨询V(zly197718)
也是在4月18日,Filecoin的Slack讨论组,某矿工在线咨询IPFS/Filecoin官方:在中国市场上,有很多公司在销售Filecoin代币。是真的吗?
并表示,这里有近2000万枚Filecoin代币要出售,包括当年参与私募股权投资的股东?他们还说他们有官方的电子签名,可以转移官方的钱包。而且,想要多少就有多少。
之后,官方人员在线回复:
不,在主网上线之前不能买卖Filecoin。可以查看官方在博客上常见问题解答中的投资者警告声明:
投资者注意事项:在出售Filecoin代币期间和之后,我们已经看到各方声称出售Filecoin SAFT或代币,以及交易所列出Filecoin和Filecoin衍生品。请记住,只有在主网启动后,Filecoin代币才会生效,并且任何现在列出Filecoin代币或IPFS代币的交易所都可能是欺诈性的。我们将在Filecoin博客上宣布Filecoin主网和代币何时生效。在此之前,我们强烈建议您远离任何声称购买、出售或交易Filecoin或IPFS SAFTS,代币或衍生品的交易所或实体。
官方已经强烈建议、警告投资者远离FIL期货,那么 FIL 期货风险究竟来自哪里?
我们可以从两个角度来分析:Filceion代币的发行和来源。
从Filecoin发行上说:
首先,FIL在官方设定中,一方面用户存储数据支付FIL,另一方面矿工贡献自己的存储资源获得FIL,整体形成良好的供需。
其次,Filecoin官方将20亿枚中的 70%分配给未来的矿工,对于矿工而言,14亿无疑充满吸引力。同时,这14亿枚FIL币线性释放,每周递减、六年减半。这种分配模式,有效的规避了市场上出现官方或者私募团队大规模的抛售,造成的价格大幅波动,而且投资人大多都是大机构的情况下,这些FIL都是惜售的。
先阶段IPFS测试网长居榜首的至联云,每天保持完成激励层任务。平均能获得每个节点1-3枚FIL币。在未来的日子希望至联云能继续保持这个数据,为未来大数据做出更大的贡献。
如果按照交易所承诺的主网上线后期货可以兑换为现货。那我们拿FIL6来说,上线6个月后交易所极有可能无法兑现造成崩盘。所以从发行的角度来说,FIL的期货风险比现货风险高很多。
联系客服请搜索zly197718,朋友圈尽知FIL
区块链
2020-04-28 10:31:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
每隔210240个区块(约383.25天),达世币的发行率就会减少约7.14%。达世币最近预计于4月28日减产7%,区块奖励将由目前的约1.55个达世币下降到约1.44个达世币。
关于达世币
达世币(DASH)是一种加密数字货币,具有可选的隐私功能和分散的自治组织(DAO)进行治理。达世币比2017年12月创下的历史新高10000人民币元下跌了95%以上,目前价格约人民币560元。在coinmarketcap市值榜上排名第18位,目前为7.09亿美元,在过去24小时内交易额为2.56亿美元。
该项目是由杜菲尔德(Evan Duffield)在2014年1月以旨在改进比特币缺点创建的山寨数字货币。该项目最初名为XCoin,随后更名为DarkCoin暗黑币,最终命名为DASH达世币,并在2015年被描述为电子现金Digital Cash。瑞恩泰勒(Ryan Taylor)是现任DASH Core首席执行官,杜菲尔德(Duffield)担任战略顾问。
该项目使用混合PoW(PoW)和权益证明(PoS)共识机制。PoW挖矿使用两分半钟的区块时间来验证分布式帐本。PoS通过超级节点Masternodes进行,并执行更高功能的任务,包括治理和独特的发送功能。集体奖励目前在三个实体之间分配;PoW矿工占45%,主节点占45%,DASH基金会占10%。
达世币总量2100万个,区块奖励每年减少7%,直到不存在任何奖励为止。目前,通货膨胀率为每年6.54%。在2014年发布时,第一天就开采了200万枚达世币,其中有些是“预挖”。不过,目前流通量最高的前100个达世币帐户中占总流通量的19.7%,而持有排名前100位的比特币地址占总流通量的15.22%。
所有具有隐私保护功能的匿名数字货币之间的比较表明,达世币DASH在每日总费用,每日交易和每日活跃地址方面处于领先地位。其他具有隐私保护功能的匿名数字货币包括Monero(XMR),Zcash(ZEC),Grin(GRIN)和PIVX(PIVX)。其中门罗币XMR和古灵币GRIN都掩盖了真实区块链交易的价值和地址。
达世币挖矿盈利情况
在挖矿方面,达世币的全网算力(哈希率)和挖矿难度在2020年1月底创下了历史新高,但在过去几周中下降了20%。该网络使用由Duffield开发的X11哈希算法,该算法由以下哈希函数组成:BLAKE,BLUE MIDNIGHT WISH(BMW),Grøstl,JH,Keccak,Skein,Luffa,CubeHash,SHAvite-3,SIMD, 和回声。X11算法在计算散列过程中按顺序循环计算11种算法中的每一种。
达世币目前可以通过当前市场上的24种专用ASIC矿机进行挖矿。但是在2020年能保持盈利领先的达世币矿机只有思创优u6和泛思x7这两种机型, 在24种ASIC矿机中,剩余的达世币矿机几乎无法盈利或是利润微薄。迄今为止,还没有新的X11 算法ASIC矿机计划在2020年发布。总体而言,达世币挖矿业的盈利能力目前处于历史最低水平,并且在下个月通货膨胀降低之后将进一步下降。影响挖矿盈利能力的其他网络因素包括:币价,区块时间,挖矿难度和交易费用。
超级节点和应用生态
经过几个月的开发,分布式密钥生成(DKG)更新于2019年6月上线,从而形成了长期有效的主节点定额(LLMQ)。外汇IB http://www.kaifx.cn/ib/ 此更新旨在增强达世网络的性能和可拓展性。基于LLMQ的ChainLocks通过防止矿工偷偷挖掘更长的链然后尝试重组达世币的区块链,提供了一种针对防止网络出现51%攻击的保护机制。
协议更改还包括针对每个网络超级节点的服务证明(PoSE)评分系统。计算中涉及各种指标,以减轻系统的投机性,但是无法响应ping请求的节点被禁止进入网络。重新加入网络之前,必须先修复该节点。
每个主节点需要1000个DASH,目前价值80000美元,在治理职能期间充当抵押品,以防止Sybil攻击或“恶意选票”。尽管存在容易招致负面影响和价格波动的风险,但自2015年以来,这些超级节点一直以稳定的速度增长。但是,此增长自2019年1月以来一直处于平稳状态。
当前网络上有4626个超级节点,这意味着目前达世币有超过50%的循环供应量被用作抵押。区块奖励的主节点份额在所有节点之间分配,这意味着随着节点数量增加,每个节点的支出减少。 达世币的超级节点目前每年赚取6.63%的达世币,这和通胀率相当。相比之下,PIVX当前有1426个活动主节点,需要10000个PIVX作为抵押。这些节点的价值为2780美元,可提供8.88%的投资回报率,而网络的通货膨胀率为4.11%。
达世主节点可以使用InstantSend或PrivateSend发送交易。InsantSend启用了一种链下0确认的交易,该交易完全绕开了矿工。这是通过使用钱包或客户的交易锁定命令来完成的,该命令显示了将资金从特定输入锁定到特定输出的意图。
PrivateSend本质上是一种混币服务,类似于CoinJoin,它将来自多个用户的相同输入组合到具有多个输出的单个交易中。因此,DASH与XMR和ZEC一起通常被标记为“匿名数字货币”。尽管PrivateSend和混币交易(下图)在总交易中所占的比例很小,但自2015年以来,这些功能一直在稳步增长。但是,与XMR或ZEC相比,网络上的DASH个人交易要少得多。
主节点治理模型还为与DASH相关的项目启用了分散投票机制,该机制通过金库整体奖励支付。这些项目及其相关预算由超级节点投票表决。如果每个项目都投票通过,则将其添加到总预算中,并支付执行工作的人员或实体的费用。虽然该机制导致该网络资助了各种项目,但在过去几个月中,大量提案集中在发展中国家的营销和推广上。
DASH很大程度上是受Duffield的本地关系影响,为许多亚利桑那州的计划提供了资金或与之建立了合作伙伴关系。2017年8月,美国财政部为区块链研究实验室(BRL)预留了50,000美元,并于2017年11月协助亚利桑那州立大学(ASU)在该大学开设了BRL。2018年1月,达世基金会宣布与ASU进一步合作,价值30万美元,旨在加速区块链领域的研究,开发和教育。
达世币的市场交易数据和相关指标
自2018年8月最低点的4800笔交易,网络上每天的交易总数在稳步增长,目前为20000笔。交易峰值代表发送超过350万笔交易的压力测试时期。
每天的平均交易价值在2017年末达到峰值,此后在2019年1月降至不到100美元。此后,平均交易价值略有上升,从150美元到800美元不等 在过去的几个月中。自2018年初以来,平均交易费用(未显示)稳步下降,目前为0.007美元,接近多年以来的最低水平。XMR,ZEC,GRIN和PIVX的平均交易费用目前分别为0.0148美元,0.0069美元,0.00424美元和0.0284美元。
在过去两个月中,为期30天的网络价值与估计的链上日常交易(NVT)比率已降至60,达到了多年以来的最低水平。NVT中的拐点可能是资产价值逆转的主要指标。如果NVT保持在20以下,则表明市场状况乐观。NVT的明显上升趋势表明,基于其经济活动和效用,币价被高估了,应将其视为看跌价格指标,而NVT的下降趋势则表明相反的情况。 在使用梅特卡夫定律确定网络的基本价值时,必须考虑有效和唯一的地址。达世币的月活跃地址在2019年7月和2020年1月创下近10万的历史新高。活跃地址逐年持续稳定增长,这表明对该网络的兴趣持续增长。
数字货币市值与已实现价值的比值(MVRV)是用于评估超买或超卖情况的一种加密货币投机基本指标。已实现的上限通过将币种最后一次在区块链上移动时的市场价值相加来估算已存在的所有硬币所支付的价值。
从历史上看,MVRV小于0.5的时期代表超卖状态,而MVRV大于3的时期代表超买状态。2017年12月的历史高点也代表MVRV的历史高点。MVRV当前为0.39,这表明增加上行空间的可能性越来越大。但是,DASH的链上混币服务可能会导致MVRV达到历史最低水平。
关于开发人员的活动,在过去的一年中,超过100个开发人员为33个DASH Github代码库贡献了1000多个提交。但除了五个协议意外,大多数协议几乎都处于非活动状态。 代码协议在过去的一年中已由9个开发人员进行了600多次提交。在过去的一年中,DASH改进协议在很大程度上是不活跃的。DASH Core v0.15于2月发布,对本机UI,内存池同步和PrivateSend进行了改进。Electrum,Android和iOS钱包也会定期更新。
大多数使用GitHub的开发人员社区,在该社区中,文件保存在称为“存储库”或“ repos”的文件夹中,并且对这些文件的更改通过“ commit”记录,这些记录保存了进行了哪些更改,何时何地进行更改的记录。尽管提交代表数量,但不一定代表质量,但是更多的提交可以表示更高的开发人员活动和兴趣。
DASH 的交易量主要由币安,OKEx和火币上的Tether(USDT)和比特币(BTC)主导。截止到2019年,DASH已经有数次上市和退市。 CEX.io于2019年8月从DASH对中退市,UpBit于2019年9月结束了达世币交易对,这两者都可能是由于围绕启用隐私交易的代币的监管问题引起的。OKEx韩国出于相同的原因也在考虑采取相同的行动方针。 同时,DASH对在2019年9月中旬添加到Coinbase,Binance.US在2019年10月添加了DASH交易对.Brave Browser为发布者和内容创作者提供无缝小额支付,在2019年也添加了DASH作为付款方式。
托管解决方案包括Trezor和Ledger硬件钱包,以及Abra,Electrum和Jaxx移动钱包。BitGo还于2019年10月启用了DASH抵押。在UpHold钱包服务中,DASH是2018年1月至2019年1月最受欢迎的加密货币。在2019年4月,spread.com应用程序还宣布支持Spend Visa卡。
除了2017年末的短暂时期外,“ DASH”一词的Google趋势数据大部分都在地板上。2017年的增长可能预示着当时大量的新市场参与者。2015年的一项研究发现Google趋势数据与比特币价格之间存在很强的相关性,而2017年的一项研究得出结论,当美国Google的“比特币”搜索量急剧增加时,比特币价格就会下跌。
总结
过去两年来达世币链上活动不断增加。尽管可选的隐私交易功能在网络上并不占主导地位,但自开始以来,这些类型的交易也逐年增加。协议的开发仍在继续,2月的最新版本对本机UI,内存池同步和PrivateSend进行了改进。
与同在2014年创立的其他已经绝种的数字货币情况不同,达世币(DASH)可能由于主节点和相对分散的筹码而幸免于难。Master Nodes阻止了绝大多数的流通供应量进入公开市场,并且在过去的六年中,基金会继续为DASH相关的开发和营销提供资金,以维持达世币的价值。
DASH / USD和DASH / BTC交易对的技术均显示出不确定的趋势,3月12日下跌后均值成功恢复。在接下来的几周中,DASH / USD有望突破88美元,并有可能重新获得看涨势头。DASH / BTC对具有超过六年的价格历史,这表明需要进一步的巩固期才能进一步突破0.016 BTC的更高高点。
区块链
2020-04-24 11:57:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
距离Filecoin主网上线还有 二 个月左右的时间,相较于IPFS/Filecoin远大的目标,大多数的人还是比较关心,Filecoin上线后所能带来的财富到底是几倍增长。
据市场调查,目前国内Filecoin矿机销售商至少达到200-300家,大约估算Filecoin矿机市场上几年来的总销售额预计超过 200 亿元,这个数据已经超过多家主流比特币矿机厂商的近两年销售额。这还是不完全统计,因为2018年市面上涌现了大量打着IPFS矿机的骗局。
那么,按照这个数据来看,Filecoin已成为目前最受瞩目的项目,参与人数众多。
Filecoin币到底会涨到多少钱?什么时候可以挖?一天能挖多少?这些问题,也成为人们越来越关心的热点。
今天,我们逐一来聊一聊。
第一,Filecoin币到底会涨到多少?
FIL(Filecoin)的保守估值
根据Filecoin融资时代币的分配机制,总发行量20亿枚,其中70%(14亿)留给矿工,挖矿的规则是每6年区块奖励减半。第一年每天释放44万枚,一年平均释放1.584亿枚。
那么像这样一个世界公认的项目,至少会进入世界数字货币市值的前10名,目前第10名是恒星币,市值是100亿人民币,明年会发行1.584亿枚,那么一枚就在63.13元左右。
FIL(Filecoin)的畅想估值
那我们不妨把这个市场大胆估测下。
2018年全球存储市场为4000亿美金,那么除以明年发行的1.584亿枚,就会达到2525.25美金一枚。当然IPFS不可能一上线就推翻传统互联网的HTTP,如果按照10%的市场份额来算,就是252.525美金一枚。
如果我们进一步思考,不是所有发行的FIL都会流通到市面上,毕竟好的币种,有识之士会囤起来,所以一般按照流通到市面上为20%(1.584×0.2亿枚),那么就是1265.8美金一枚,等于8860.6人民币。
我们可以进一步畅想,随着5G到来,人类数据存储需求将呈指数倍增,到了2025年,全球存储市值会达到23万亿美金,到那时,HTTP已经被淘汰,23万亿全都是分布式存储的天下。而到那时,诸多的分布式存储的项目中,IPFS是最有机会独占鳌头的。
如果IPFS有20亿美金市值,届时发行的9.504亿枚FIL,一枚价值就接近2万美金!
还有一个细节,2026年FIL将迎来减半!而看BTC的历史,每一次减半随即就迎来了一波牛市,2012年减半,2013年牛市BTC价格从2美金增长到1200美金;2016年减半,2017年牛市BTC价格从650美金增长到19000美金。
所以,错过了BTC,不要再错过下一个财富风口,我们发财的机会即将到来!
第二,IPFS/Filecoin什么时候可以挖?
根据IPFS/Filecoin官方最新时间计划,Filecoin主网上线时间为6月至7月,那么也就是还有3个月左右就可以开始挖矿了。而要想在主网上线就能及时挖矿,或者说主网上线就能拿到最好也是最大的红利,现在布局正是关键。为什么这么说?
1)初期,全网有效矿机少,矿工相对后期较少,而出币量多能挖到的币自然多。
2)2020年比特币减半产生牛市预期,全球共识度高,极有可能让头矿收益变得非常惊人!
3)出现超高收益,甚至1个月就回本, 但这不会持续很久, 因为这也必然会引起大量竞争者涌入,最终让收益逐渐回归正常值。
4)挖矿设备和系统的布局一般需要2-3个月的时间,后期整体需求暴增时,可能需要半年时间才能完成。
5)临近上线设备供不应求,价格相对的上涨。
6)早挖早回本、回报高。根据市场调查研究,Filecoin上线后1至3月可能面临价格的小高峰,如果错过头矿,也错过了最佳回本周期。大批的竞争者需要6到12个月的时间完成大规模涌入。这时,早期矿工轻松躺赚的阶段将逐渐终结,进入由大矿工和大资本主导的充分竞争阶段。
所以,只有在最初期阶段参与进来的矿工,才有机会享受超高的收益!
第三,Filecoin币一天可以挖多少呢
我们都知道,FIL代币总量20亿枚,其中矿工可挖总量占70%,也就是14亿枚,剩下15%归协议实验室所有,10%归ICO,还有5%由基金会所有。
根据FIlecoin分配与释放规则,矿工按70%比例分配,每周递减、6年减半,上线之后的六年内大约释放7亿枚。预估IPFS/Filecoin主网上线第一年FIL释放情况,第一年起挖矿所得FIL币释放量大约为44万枚/天,第六年年末释放量大约为20万枚/天。
而Filecoin一天挖多少币是有前提条件的,现今知道前几家大公司,Filecoin是集群共同协作挖矿,硬件设备也是要考虑的,更关键的是各技术团队技术能力的算力及出块率,是Filecoin一天可以挖多少币的关键。
因此,想要参与Filecoin挖矿的朋友,选择Filecoin挖矿能力前三的合作伙伴,所产出的收益才是最高的。
Filecoin上线在即,预祝每一位朋友早日完成自己的财富梦想!
区块链
2020-05-08 10:18:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>

Unblocked的作者Alison McCauley 正在Radar上探索区块链的应用和机会。这是 我们在过去几个月中分三部分发布的系列文章中的第三篇 。
尽管区块链技术仍处于早期阶段,但企业的势头正在增强。尽管在银行业和支付领域一直非常关注区块链,但其影响已经远远超出了金融领域。这只是其中一些工作的一瞥,以及可以在各个行业中利用的那种深入学习的内容。

卫生保健
凭借其对数据隐私和安全性的高标准,在医疗保健领域获得的经验教训可以为政府和其他法规繁重的行业的发展和实践提供信息。法规要求使医疗保健成为更具挑战性的行业之一,因此,要想真正改变患者的状况,变革将需要时间。但是发展已经进行了多年。有远见的人们希望利用区块链来提供安全,通用的数据共享基础架构,以帮助解决卫生保健系统中数十年的特有问题。由于当今的提供商没有办法安全地共享数据,因此希望由区块链驱动的协作最终可以提高诊断的准确性和治疗的协调性。
例如,MedRec是麻省理工学院正在开发的系统,旨在使患者能够管理自己的记录,并允许不同的提供者访问和更新数据。该系统正在使用匿名数据进行测试,例如,即使这些疫苗是由不同的提供者提供的,也可以用作可信任的中央疫苗库。Gem和Tierion是从事数据存储,验证和共享(与飞利浦医疗保健合作)的不同方面的初创公司,而Hu-manity.co与IBM合作则是为患者提供对数据的更多控制权,并使他们能够从共享数据中直接受益。大都会人寿现在可以立即向妊娠糖尿病测试呈阳性的孕妇支付索赔,尽管这只是一小部分业务,

房地产
先锋们正在努力增加流动性,减轻管理负担,并开辟新的房地产商业模式的可能性。他们的工作可以激发其他具有类似特征的领域的创新。他们正在使用该技术记录,跟踪和转让土地所有权,契约和留置权,并促进付款,租赁和销售。他们甚至正在探索通过代币化(价值的可编程表示)将房地产细分的新方法。
瑞典土地注册机构Lantmäteriet与各种各样的合作伙伴一起,正在私有区块链上测试土地注册。如今,即使Lantmäteriet已经无纸化且高度数字化,从签订合同到注册销售可能还需要几个月的时间。该注册表使区块链上的交易实现自动化,使买卖双方可以对销售清单进行数字签名,并自动验证签名,而不是在代理商办公室进行签名验证。当土地所有权易手时,它将通过区块链进行验证,并再次记录。在瑞典广泛使用由区块链驱动的注册表之前,还有很长的路要走,但是据估计,纳税人每年可能节省超过1亿美元。在美国,佛蒙特州的南伯灵顿市也在区块链上运行了具有土地所有权和注册处的飞行员。
已经出现了促进房地产令牌化的平台,这可以帮助使流动性较差的资产更具流动性。买方购买代币,每个代币代表资产的一小部分。去年,科罗拉多州瑞吉阿斯彭度假酒店的所有者以这种方式筹集了1800万美元,每个代币的价值为1美元。

包装消费品
消费者包装产品公司对区块链技术进行了大量投资,这些公司被承诺提高供应链透明度所吸引。他们的具有挑战性的工作(例如,如何对草莓进行数字化处理)可以为任何希望在其生态系统中实现商品可视化的行业奠定重要基础。
超过100家公司参与了IBM的Food Trust网络,其中包括许多消费包装商品公司和杂货零售商。消费者,零售商和食品安全组织要求更高的透明度,而区块链正希望成为这一复杂生态系统的有前途的解决方案。
从捕捞金枪鱼到到达杂货店货架的整个过程,Bumble Bee Foods正在使用区块链来实现其供应链的透明性。该公司旨在证明其产品的来源会影响消费者的偏爱甚至价格。雀巢已经在包括IBM Food Trust在内的10多个项目中测试了区块链,该公司正在使用该技术跟踪Gerber婴儿食品等产品中成分的来源。
百威英博正在探索一系列飞行员。啤酒公司为一些消费者提供了一种选择,可以将其驾驶执照信息上传到区块链,该区块链可以验证年龄,以便他们可以通过扫描手机在自动售货机上购买啤酒。百威英博(Anheuser-Busch InBev)还与BanQu建立了合作伙伴关系,后者使用区块链为没有银行账户的农民付款。在非洲等快速发展的市场中,这可以使公司与更多农民合作,从而更有效地满足需求。

广告
数字广告依赖于广告商,发行商和中间商的复杂生态系统,并受到普遍欺诈的困扰。区块链为更智能,更安全的广告产生更高的收益提供了希望。企业家和内部企业家正在探索许多角度,包括使用区块链获取更高质量的数据,确定目标并降低成本。这项工作可能会为正在以欺诈或高收费中介为特征的大型生态系统运作的一系列行业提供信息。
例如,康卡斯特(Comcast)以及竞争对手维亚康姆(Viacom)和Spectrum Reach合作推出了Blockgraph,旨在寻求更精确的定位,而又不会向广告商透露观众的个人信息。勇敢是一种新的浏览器,旨在攻击浏览器生态系统中效率低下的每一层。这个新模型使用区块链消除了中间商,而中间商如今已占据了一半以上的收入。例如,广告商不会去Google或Facebook,而是直接在Brave的基于区块链的浏览器上列出。广告商和发布商都获得了更多价值,消费者获得了更少但针对性更强的广告。

保险
区块链在保险业中的应用是一个巨大的探索领域。该技术的目标是检测欺诈,提高理赔效率以及简化保险公司与再保险公司之间的数据流和支付流程。但是,它也正在被探索为创新保险方法的关键机制。区块链(以及可用于计算风险和监控资产的大量新的物联网驱动数据)可以使保险公司更轻松地提供可根据个人需求而变化和变化的细粒度保护。它降低了成本,并启用了无需人工即可执行的唯一标识符,不变的跟踪和合同,从而使保险业务可以用于越来越小的事物或时间段。
保险业巨头安联(Allianz SE)已测试了一系列区块链应用程序。例如,通过一家合资企业,该公司正在测试航班延误保险,一旦航班延误了保险延误时间,该延误保险便会自动启动。它还参与了一个加快向医疗服务提供者支付保险费的项目。State Farm正在开发一个区块链,以加快保险公司从涉及索赔的其他保险公司寻求部分偿还索赔的过程,今天这是一个痛苦的过程,具有高昂的管理成本。

势头遍及整个业务领域
这些行业仅是正在蓬勃发展的各种项目的一瞥。几乎每个行业都已经建立和颠覆性参与者都在寻求使用区块链技术来发展业务方式。根据德勤(Deloitte)在其2019年全球区块链调查中表示,``高管们的问题不再是,' 区块链会起作用吗?' 但是,“我们如何让区块链为我们服务?”。尽管许多企业项目倾向于存放在深层办公室中,但它们创建了一个基础,可以在一天之内影响我们的工作和娱乐方式。随着全球精通区块链的团队建立并聚集盟友,随着时间的推移,项目可能会泛滥成灾,难以超越。

区块链
2020-05-05 22:53:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
基础设施,是指为社会生产和居民生活提供公共服务的物质工程设施,包括交通、邮政、供水供电等领域的公共设施。数字基础设施的提出,其背景是新一代信息通信技术蓬勃发展。像水、电、公路一样,数字信息已成为生产生活必备要素。具体来说,数字基础设施主要包括信息基础设施和对物理基础设施的数字化改造两部分。
数字基础设施是立足当下、面向未来的新型基础建设。它顺应网络化、数字化、智能化的社会发展趋势,为人类未来新的生产生活方式提供平台和保障。在这一新型平台之上,人类生活、产业格局、经济发展、社会治理、文化生态都将翻开崭新一页。
在数字基础设施之上展开生产生活新图景
设想10年后,当全社会实现大规模数字化时,整个社会基础设施的存在形态、建设方式、运营方式和典型特征都将发生根本性改变。数字化将成为人与人、人与物、物与物交互的重要形态。这是我们思考数字基础设施的起点。
从技术层面看,当前数字基础设施主要涉及5G、数据中心、云计算、人工智能、物联网、区块链等新一代信息通信技术,以及基于上述数字技术而形成的各类数字平台。购物、娱乐、出行、政务等各类数字平台,是数字商业、产业数字化、数字政务的基础设施。此外,传统物理基础设施,经过数字化改造,正在形成融合基础设施。3D打印、智能机器人、AR眼镜、自动驾驶等新型应用科技,则将把数字基础设施延伸到整个物理世界。一个全新的技术图景正在构建之中。
数字基础设施是新型基础设施,会在物理世界之上孕育出新价值网络和新服务体系、新“物种”和新业态。比如,工业互联网里的C2M(从消费者到制造商),可以实时把消费者需求传递给生产侧——数字基础设施不仅赋能供给侧与需求侧,还使供需两侧形成双螺旋的持续互动,从而大幅提升全要素的经济效率。
升级云数据中心,融合关键技术,让数据“跑”起来
“新一代云数据中心”不同于传统的“物理机房”。后者损耗大,但难以提供真正意义上的大规模计算服务。前者依照新一代云计算标准建设,可以为社会提供源源不断的云服务,即通过服务器、存储、软件、网络、安全等软硬件设备的一体化,根据用户需求提供弹性颇高的服务,高效支持数字经济发展和产业数字化变革。
云计算具有巨大的规模化效应以及按需计费、灵活弹性等特性,已经成为数字经济时代的创新中心和能力底座。承载大数据、人工智能、物联网,区块链等技术的云计算,依托算力、数据、算法这三个关键要素,与5G、新一代自动化技术聚合发展,产生聚变效应和辐射效应,是推动物理世界数字化转型、传统企业上云、各行各业数字化转型升级的数字基础设施。“一切智能即服务”。人工智能作用也将日益凸显,加速关键技术的融合发展。5G将大幅增加实时处理、现场处理、虚实融合的数据需求。物联网则通过各类网络接入,实现物与物、物与人的泛在连接,实现对物品和过程的智能化感知、识别和管理。在这个过程中,“物”将变得更具智能。物联网带来的“万物上云”和“物”的数字化、5G驱动下消费互联网和产业互联网的加速增长,都将创造前所未有的数据量,数据维度、价值密度也会前所未有的丰富,进而对大数据计算、存储、分析和利用的技术和应用提出更高要求。简言之,云计算底座承载大数据处理和人工智能算法,通过5G触达人们手中的智能端,完成云网端一体的大闭环,共同构成一个万物智能的世界。
需要强调的是,数据要想创造价值,必须在广义的互联网上“跑”起来。“要想富,先修路”。数字基础设施的目标是为数据流动修通“信息高速公路”,即为数据安全有序流动建章立制、保驾护航,让数据的“路”畅通起来。近期发布的《中共中央国务院关于构建更加完善的要素市场化配置体制机制的意见》,提出加快培育数据要素市场,“推进政府数据开放共享”,“提升社会数据资源价值”,“加强数据资源整合和安全保护”。中国是数据资源和应用场景最为丰富的国家之一。在防控新冠肺炎疫情中,人工智能技术在疑似病例探索和辅助诊断过程中积极发挥作用,为人工智能在医疗领域的应用打开新的突破口。
作为新一代数字技术集大成者,工业互联网不断迭代升级
工业互联网作为数字基础设施,其本质是以数据为驱动,化解数字时代的复杂问题。即利用数据进行信息交换与传递、洞察生产与商业运行规律、驱动全价值链和网络化协同,产生新价值、新模式、新业态和新产业。
作为新一代数字技术集大成者,工业互联网是数字技术与传统工业技术的“叠加”与“融合”。未来,每一件产品、每一台设备、每一条生产线、每一座工厂都将实现数据化,并实时映射到数字世界,形成物理世界和数字世界的“双生子”。数字世界将利用数据、算力、算法与模型,对物理世界发生的行为进行描述、分析、诊断、决策,从而以最低的试错风险和成本,指导物理世界的生产运营。例如,借助大数据与人工智能技术,钢铁企业可以有效降低铁的损耗,每年节省成本上千万元。
未来,工业互联网在技术、架构、模式、生态等方面都将升级、迭代或是重构。工业互联网发展将呈现以下主要特征:第一,工业互联网与消费互联网将形成双轮驱动、横向耦合,最终达到供给侧平衡。例如C2M模式,可有效将消费端数据注入到供给侧,帮助制造企业实现以销定产,同时打通金融、物流等消费端资源,整体赋能中小制造企业“端到端”的转型。第二,更多制造企业将启动数字中台战略,快速响应前端业务变化。第三,打造“共生、共赢”生态体系。工业互联网平台建设是复杂又漫长的系统工程,涉及众多学科、技术与人才。只有相互信任、相互成就,才能构建一个共生、利他的生态系统,从而产生巨大的协同效应。
城市大脑为政府数字化转型提供重要路径和方法
推进国家治理体系和治理能力现代化,需以城市治理水平的提升为基础。城市大脑是提升城市治理水平的重要基础设施。运用大数据、云计算、区块链、人工智能等前沿技术,可推动城市管理手段、管理模式、管理理念的创新。从数字化到智能化再到智慧化,是城市治理体系和治理能力现代化的必由之路,前景广阔。
城市大脑为政府数字化转型提供重要路径和方法。数字化治理目标是全社会的数据互通、数字化的全面协同与跨部门的流程再造。城市大脑核心由中枢系统、系统、平台和数字驾驶舱组成,通过云数据中心底座输出相关能力,推动社会治理、经济发展、民生服务的场景化应用。健康码就是基于城市大脑的创新应用。2月11日,杭州推出全国首个健康码。很快,健康码在浙江全省各市上线,并向全国推广,成为科学防控疫情、方便居民生活、有序推动复工复产的抓手。
在传统基础设施逐步完备的基础上,如果我们能在数字基础设施建设上走在前面,将有力助推中国经济的跨越式发展和可持续发展,创造经济发展新动能、新变革,提升国家总体实力。同时,我们也要看到数字经济时代的问题和挑战。一方面,要避免“重建设、轻运营;重硬件、轻软件”,防止重复投资。一方面,因应日益复杂的国际环境、全球产业链疏离的风险、新科技应用的科技伦理等问题,数字基础设施建设应坚持开放的科技创新生态,积极加强国际科研合作。同时,创新投资模式,积极构建数字新基建生态,让技术的红利服务于高质量发展、可持续发展的大目标。
不断更新的制造业技术、不断发展的数字技术,以及数字应用环境下群众的广泛参与,为数字化升级带来巨大发展机遇。以未来眼光看待数字基础设施建设新浪潮,抓住机遇,未来可期。
区块链
2020-05-05 15:21:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1.Java程序引入相关依赖,后面用于调用智能合约中的函数 org.web3j core 4.5.15 com.squareup.okhttp3 okhttp 4.4.0 com.squareup.okhttp3 okhttp-ws 3.4.2
2.将合约使用 remix 进行编译
编译后,复制abi、Bytecode,放入指定位置,生成abi和bin文件
@Test void generateABIAndBIN() { String abi = ""; String bin = ""; String abiFileName = "AWMain.abi"; String binFileName = "AWMain.bin"; File abiFile = new File("E:\\solidity\
区块链
2020-03-23 21:49:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
前 言
随着区块链技术发展,越来越多的企业与个人开始将区块链与自身业务相结合。
区块链所具有的独特优势,例如,数据公开透明、不可篡改,可以为业务带来便利。但与此同时,也存在一些隐患。数据的公开透明,意味着任何人都可以读取;不可篡改,意味着信息一旦上链就无法删除,甚至合约代码都无法被更改。
除此之外,合约的公开性、回调机制,每一个特点都可被利用,作为攻击手法,稍有不慎,轻则合约形同虚设,重则要面临企业机密泄露的风险。所以,在业务合约上链前,需要预先对合约的安全性、可维护性等方面作充分考虑。
幸运的是,通过近些年Solidity语言的大量实践,开发者们不断提炼和总结,已经形成了一些"设计模式",来指导应对日常开发常见的问题。
智能合约设计模式概述
2019年,IEEE收录了维也纳大学一篇题为《Design Patterns For Smart Contracts In the Ethereum Ecosystem》的论文。这篇论文分析了那些火热的Solidity开源项目,结合以往的研究成果,整理出了18种设计模式。
这些设计模式涵盖了安全性、可维护性、生命周期管理、鉴权等多个方面。
接下来,本文将从这18种设计模式中选择最为通用常见的进行介绍,这些设计模式在实际开发经历中得到了大量检验。
安全性(Security)
智能合约编写,首要考虑的就是安全性问题。
在区块链世界中,恶意代码数不胜数。如果你的合约包含了跨合约调用,就要特别当心,要确认外部调用是否可信,尤其当其逻辑不为你所掌控的时候。
如果缺乏防人之心,那些“居心叵测”的外部代码就可能将你的合约破坏殆尽。比如,外部调用可通过恶意回调,使代码被反复执行,从而破坏合约状态,这种攻击手法就是著名的Reentrance Attack(重放攻击)。
这里,先引入一个重放攻击的小实验,以便让读者了解为什么外部调用可能导致合约被破坏,同时帮助更好地理解即将介绍的两种提升合约安全性的设计模式。
关于重放攻击,这里举个精简的例子。
AddService合约是一个简单的计数器,每个外部合约可以调用AddService合约的addByOne来将字段_count加一,同时通过require来强制要求每个外部合约最多只能调用一次该函数。
这样,_count字段就精确的反应出AddService被多少合约调用过。在addByOne函数的末尾,AddService会调用外部合约的回调函数notify。AddService的代码如下: contract AddService{ uint private _count; mapping(address=>bool) private _adders; function addByOne() public { //强制要求每个地址只能调用一次 require(_adders[msg.sender] == false, "You have added already"); //计数 _count++; //调用账户的回调函数 AdderInterface adder = AdderInterface(msg.sender); adder.notify(); //将地址加入已调用集合 _adders[msg.sender] = true; } } contract AdderInterface{ function notify() public; }
如果AddService如此部署,恶意攻击者可以轻易控制AddService中的_count数目,使该计数器完全失效。
攻击者只需要部署一个合约BadAdder,就可通过它来调用AddService,就可以达到攻击效果。BadAdder合约如下: contract BadAdder is AdderInterface{ AddService private _addService = //...; uint private _calls; //回调 function notify() public{ if(_calls > 5){ return; } _calls++; //Attention !!!!!! _addService.addByOne(); } function doAdd() public{ _addService.addByOne(); } }
BadAdder在回调函数notify中,反过来继续调用AddService,由于AddService糟糕的代码设计,require条件检测语句被轻松绕过,攻击者可以直击_count字段,使其被任意地重复添加。
攻击过程的时序图如下:
在这个例子中,AddService难以获知调用者的回调逻辑,但依然轻信了这个外部调用,而攻击者利用了AddService糟糕的代码编排,导致悲剧的发生。
本例子中去除了实际的业务意义,攻击后果仅仅是_count值失真。真正的重放攻击,可对业务造成严重后果。比如在统计投票数目是,投票数会被改得面目全非。
打铁还需自身硬,如果想屏蔽这类攻击,合约需要遵循良好的编码模式,下面将介绍两个可有效解除此类攻击的设计模式。
Checks-Effects-Interaction - 保证状态完整,再做外部调用
该模式是编码风格约束,可有效避免重放攻击。通常情况下,一个函数可能包含三个部分: Checks:参数验证 Effects:修改合约状态 Interaction:外部交互
这个模式要求合约按照Checks-Effects-Interaction的顺序来组织代码。它的好处在于进行外部调用之前,Checks-Effects已完成合约自身状态所有相关工作,使得状态完整、逻辑自洽,这样外部调用就无法利用不完整的状态进行攻击了。
回顾前文的AddService合约,并没有遵循这个规则,在自身状态没有更新完的情况下去调用了外部代码,外部代码自然可以横插一刀,让_adders[msg.sender]=true永久不被调用,从而使require语句失效。我们以checks-effects-interaction的角度审阅原来的代码: //Checks require(_adders[msg.sender] == false, "You have added already"); //Effects _count++; //Interaction AdderInterface adder = AdderInterface(msg.sender); adder.notify(); //Effects _adders[msg.sender] = true;
只要稍微调整顺序,满足Checks-Effects-Interaction模式,悲剧就得以避免: //Checks require(_adders[msg.sender] == false, "You have added already"); //Effects _count++; _adders[msg.sender] = true; //Interaction AdderInterface adder = AdderInterface(msg.sender); adder.notify();
由于_adders映射已经修改完毕,当恶意攻击者想递归地调用addByOne,require这道防线就会起到作用,将恶意调用拦截在外。
虽然该模式并非解决重放攻击的唯一方式,但依然推荐开发者遵循。
Mutex - 禁止递归
Mutex模式也是解决重放攻击的有效方式。它通过提供一个简单的修饰符来防止函数被递归调用: contract Mutex { bool locked; modifier noReentrancy() { //防止递归 require(!locked, "Reentrancy detected"); locked = true; _; locked = false; } //调用该函数将会抛出Reentrancy detected错误 function some() public noReentrancy{ some(); } }
在这个例子中,调用some函数前会先运行noReentrancy修饰符,将locked变量赋值为true。如果此时又递归地调用了some,修饰符的逻辑会再次激活,由于此时的locked属性已为true,修饰符的第一行代码会抛出错误。
可维护性(Maintaince)
在区块链中,合约一旦部署,就无法更改。当合约出现了bug,通常要面对以下问题: 合约上已有的业务数据怎么处理? 怎么尽可能减少升级影响范围,让其余功能不受影响? 依赖它的其他合约该怎么办?
回顾面向对象编程,其核心思想是将变化的事物和不变的事物相分离,以阻隔变化在系统中的传播。所以,设计良好的代码通常都组织得高度模块化、高内聚低耦合。利用这个经典的思想可解决上面的问题。
Data segregation - 数据与逻辑相分离
了解该设计模式之前,先看看下面这个合约代码: contract Computer{ uint private _data; function setData(uint data) public { _data = data; } function compute() public view returns(uint){ return _data * 10; } }
此合约包含两个能力,一个是存储数据(setData函数),另一个是运用数据进行计算(compute函数)。如果合约部署一段时间后,发现compute写错了,比如不应是乘以10,而要乘以20,就会引出前文如何升级合约的问题。
这时,可以部署一个新合约,并尝试将已有数据迁移到新的合约上,但这是一个很重的操作,一方面要编写迁移工具的代码,另一方面原先的数据完全作废,空占着宝贵的节点存储资源。
所以,预先在编程时进行模块化十分必要。如果我们将"数据"看成不变的事物,将"逻辑"看成可能改变的事物,就可以完美避开上述问题。Data Segregation(意为数据分离)模式很好地实现了这一想法。
该模式要求一个业务合约和一个数据合约:数据合约只管数据存取,这部分是稳定的;而业务合约则通过数据合约来完成逻辑操作。
结合前面的例子,我们将数据读写操作专门转移到一个合约DataRepository中: contract DataRepository{ uint private _data; function setData(uint data) public { _data = data; } function getData() public view returns(uint){ return _data; } }
计算功能被单独放入一个业务合约中: contract Computer{ DataRepository private _dataRepository; constructor(address addr){ _dataRepository =DataRepository(addr); } //业务代码 function compute() public view returns(uint){ return _dataRepository.getData() * 10; } }
这样,只要数据合约是稳定的,业务合约的升级就很轻量化了。比如,当我要把Computer换成ComputerV2时,原先的数据依然可以被复用。
Satellite - 分解合约功能
一个复杂的合约通常由许多功能构成,如果这些功能全部耦合在一个合约中,当某一个功能需要更新时,就不得不去部署整个合约,正常的功能都会受到波及。
Satellite模式运用单一职责原则解决上述问题,提倡将合约子功能放到子合约里,每个子合约(也称为卫星合约)只对应一个功能。当某个子功能需要修改,只要创建新的子合约,并将其地址更新到主合约里即可,其余功能不受影响。
举个简单的例子,下面这个合约的setVariable功能是将输入数据进行计算(compute函数),并将计算结果存入合约状态_variable: contract Base { uint public _variable; function setVariable(uint data) public { _variable = compute(data); } //计算 function compute(uint a) internal returns(uint){ return a * 10; } }
如果部署后,发现compute函数写错,希望乘以的系数是20,就要重新部署整个合约。但如果一开始按照Satellite模式操作,则只需部署相应的子合约。
首先,我们先将compute函数剥离到一个单独的卫星合约中去: contract Satellite { function compute(uint a) public returns(uint){ return a * 10; } }
然后,主合约依赖该子合约完成setVariable: contract Base { uint public _variable; function setVariable(uint data) public { _variable = _satellite.compute(data); } Satellite _satellite; //更新子合约(卫星合约) function updateSatellite(address addr) public { _satellite = Satellite(addr); } }
这样,当我们需要修改compute函数时,只需部署这样一个新合约,并将它的地址传入到Base.updateSatellite即可: contract Satellite2{ function compute(uint a) public returns(uint){ return a * 20; } }
Contract Registry - 跟踪最新合约
在Satellite模式中,如果一个主合约依赖子合约,在子合约升级时,主合约需要更新对子合约的地址引用,这通过updateXXX来完成,例如前文的updateSatellite函数。
这类接口属于维护性接口,与实际业务无关,过多暴露此类接口会影响主合约美观,让调用者的体验大打折扣。Contract Registry设计模式优雅地解决了这个问题。
在该设计模式下,会有一个专门的合约Registry跟踪子合约的每次升级情况,主合约可通过查询此Registyr合约取得最新的子合约地址。卫星合约重新部署后,新地址通过Registry.update函数来更新。 contract Registry{ address _current; address[] _previous; //子合约升级了,就通过update函数更新地址 function update(address newAddress) public{ if(newAddress != _current){ _previous.push(_current); _current = newAddress; } } function getCurrent() public view returns(address){ return _current; } }
主合约依赖于Registry获取最新的卫星合约地址。 contract Base { uint public _variable; function setVariable(uint data) public { Satellite satellite = Satellite(_registry.getCurrent()); _variable = satellite.compute(data); } Registry private _registry = //...; }
Contract Relay - 代理调用最新合约
该设计模式所解决问题与Contract Registry一样,即主合约无需暴露维护性接口就可调用最新子合约。该模式下,存在一个代理合约,和子合约享有相同接口,负责将主合约的调用请求传递给真正的子合约。卫星合约重新部署后,新地址通过SatelliteProxy.update函数来更新。 contract SatelliteProxy{ address _current; function compute(uint a) public returns(uint){ Satellite satellite = Satellite(_current); return satellite.compute(a); } //子合约升级了,就通过update函数更新地址 function update(address newAddress) public{ if(newAddress != _current){ _current = newAddress; } } } contract Satellite { function compute(uint a) public returns(uint){ return a * 10; } }
主合约依赖于SatelliteProxy: contract Base { uint public _variable; function setVariable(uint data) public { _variable = _proxy.compute(data); } SatelliteProxy private _proxy = //...; }
生命周期(Lifecycle)
在默认情况下,一个合约的生命周期近乎无限——除非赖以生存的区块链被消灭。但很多时候,用户希望缩短合约的生命周期。这一节将介绍两个简单模式提前终结合约生命。
Mortal - 允许合约自毁
字节码中有一个selfdestruct指令,用于销毁合约。所以只需要暴露出自毁接口即可: contract Mortal{ //自毁 function destroy() public{ selfdestruct(msg.sender); } }
Automatic Deprecation - 允许合约自动停止服务
如果你希望一个合约在指定期限后停止服务,而不需要人工介入,可以使用Automatic Deprecation模式。 contract AutoDeprecated{ uint private _deadline; function setDeadline(uint time) public { _deadline = time; } modifier notExpired(){ require(now <= _deadline); _; } function service() public notExpired{ //some code } }
当用户调用service,notExpired修饰符会先进行日期检测,这样,一旦过了特定时间,调用就会因过期而被拦截在notExpired层。
权限(Authorization)
前文中有许多管理性接口,这些接口如果任何人都可调用,会造成严重后果,例如上文中的自毁函数,假设任何人都能访问,其严重性不言而喻。所以,一套保证只有特定账户能够访问的权限控制设计模式显得尤为重要。
Ownership
对于权限的管控,可以采用Ownership模式。该模式保证了只有合约的拥有者才能调用某些函数。首先需要有一个Owned合约: contract Owned{ address public _owner; constructor() { _owner = msg.sender; } modifier onlyOwner(){ require(_owner == msg.sender); _; } }
如果一个业务合约,希望某个函数只由拥有者调用,该怎么办呢?如下: contract Biz is Owned{ function manage() public onlyOwner{ } }
这样,当调用manage函数时,onlyOwner修饰符就会先运行并检测调用者是否与合约拥有者一致,从而将无授权的调用拦截在外。
行为控制(Action And Control)
这类模式一般针对具体场景使用,这节将主要介绍基于隐私的编码模式和与链外数据交互的设计模式。
Commit - Reveal - 延迟秘密泄露
链上数据都是公开透明的,一旦某些隐私数据上链,任何人都可看到,并且再也无法撤回。
Commit And Reveal模式允许用户将要保护的数据转换为不可识别数据,比如一串哈希值,直到某个时刻再揭示哈希值的含义,展露真正的原值。
以投票场景举例,假设需要在所有参与者都完成投票后再揭示投票内容,以防这期间参与者受票数影响。我们可以看看,在这个场景下所用到的具体代码: contract CommitReveal { struct Commit { string choice; string secret; uint status; } mapping(address => mapping(bytes32 => Commit)) public userCommits; event LogCommit(bytes32, address); event LogReveal(bytes32, address, string, string); function commit(bytes32 commit) public { Commit storage userCommit = userCommits[msg.sender][commit]; require(userCommit.status == 0); userCommit.status = 1; // comitted emit LogCommit(commit, msg.sender); } function reveal(string choice, string secret, bytes32 commit) public { Commit storage userCommit = userCommits[msg.sender][commit]; require(userCommit.status == 1); require(commit == keccak256(choice, secret)); userCommit.choice = choice; userCommit.secret = secret; userCommit.status = 2; emit LogReveal(commit, msg.sender, choice, secret); } }
Oracle - 读取链外数据
目前,链上的智能合约生态相对封闭,无法获取链外数据,影响了智能合约的应用范围。
链外数据可极大扩展智能合约的使用范围,比如在保险业中,如果智能合约可读取到现实发生的意外事件,就可自动执行理赔。
获取外部数据会通过名为Oracle的链外数据层来执行。当业务方的合约尝试获取外部数据时,会先将查询请求存入到某个Oracle专用合约内;Oracle会监听该合约,读取到这个查询请求后,执行查询,并调用业务合约响应接口使合约获取结果。
下面定义了一个Oracle合约: contract Oracle { address oracleSource = 0x123; // known source struct Request { bytes data; function(bytes memory) external callback; } Request[] requests; event NewRequest(uint); modifier onlyByOracle() { require(msg.sender == oracleSource); _; } function query(bytes data, function(bytes memory) external callback) public { requests.push(Request(data, callback)); emit NewRequest(requests.length - 1); } //回调函数,由Oracle调用 function reply(uint requestID, bytes response) public onlyByOracle() { requests[requestID].callback(response); } }
业务方合约与Oracle合约进行交互: contract BizContract { Oracle _oracle; constructor(address oracle){ _oracle = Oracle(oracle); } modifier onlyByOracle() { require(msg.sender == address(_oracle)); _; } function updateExchangeRate() { _oracle.query("USD", this.oracleResponse); } //回调函数,用于读取响应 function oracleResponse(bytes response) onlyByOracle { // use the data } }
总  结
本文的介绍涵盖了安全性、可维护性等多种设计模式,其中,有些偏原则性,如Security和Maintaince设计模式;有些是偏实践,例如Authrization,Action And Control。
这些设计模式,尤其实践类,并不能涵盖所有场景。随着对实际业务的深入探索,会遇到越来越多的特定场景与问题,开发者可对这些模式提炼、升华,以沉淀出针对某类问题的设计模式。
上述设计模式是程序员的有力武器,掌握它们可应对许多已知场景,但更应掌握提炼设计模式的方法,这样才能从容应对未知领域,这个过程离不开对业务的深入探索,对软件工程原则的深入理解。
FISCO BCOS的代码完全开源且免费
下载地址****↓↓↓
https://github.com/FISCO-BCOS/FISCO-BCOS
区块链
2020-04-19 19:05:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> 本文作者为万向区块链、PlatON首席经济学家邹传伟。
2020 年 1 月,由比特币核心开发人员 Pieter Wuille 于去年 5 月提出的 Taproot/Schnorr 软分叉升级提案已正式作为比特币改进提案(BIPs)发布,相关提案序号为 BIP 340-342。Taproot/Schnorr 升级如果获得社区支持,将是比特币自闪电网络上线后最大的技术拓展。本文查询了 BIP 340-342 相关文档 ,对 Taproot/Schnorr 升级做一个简单介绍。本文分三部分,第一部分简单介绍比特币目前的 ECDSA 签名算法,第二部分详细介绍 Schnorr 签名算法,第三部分介绍 Taproot。

一、比特币 ECDSA 签名算法
比特币目前使用的 ECDSA 签名算法与建议的 Schnorr 签名算法,都属于椭圆曲线数字签名算法,它们使用的椭圆曲线都是 secp256k1。这一部分先介绍椭圆曲线 secp256k1,再介绍 ECDSA 签名算法。

(一)椭圆曲线 secp256k1

图 1:椭圆曲线图示



(二) ECDSA 签名算法
注: G 坐标为
(79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8),
阶等于
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,
均采用 16 进制表达。


二、Schnorr 签名算法
这一部分先介绍 Schnorr 签名算法主要特点,再分步骤介绍 Schnorr 签名算法及批验证,最后介绍基于 Schnorr 签名的多重签名算法。

(一)主要特点
Schnorr 签名算法与 ECDSA 签名算法使用同样的椭圆曲线 secp256k1 和哈希函数 SHA256,所以在这个层面它们具有同样的安全性。Schnorr 签名算法主要有以下优点。
第一,Schnorr 签名算法有可证明安全性。在假设椭圆曲线离散对数问题难度的随机寓言(Random Oracle)模型,以及假设原像抗性(Preimage Resistance)和次原像抗性(Second Preimage Resistance)的通用群模型下,Schnorr 签名算法具备选择消息攻击下的强不可伪造性(Strong Unforgeability under Chosen Message Attack,SUF-CMA)。换言之,如果不知道 Schnorr 签名的私钥,即使有针对任意消息的有效 Schnorr 签名,也没法推导出其他有效 Schnorr 签名。而 ECDSA 签名算法的可证明安全性则依赖于更强的假设。
第二,Schnorr 签名算法具有不可延展性(Non-malleability)。签名延展性的含义是,第三方在不知道私钥的情况下,能将针对某一公钥和消息的有效签名,改造成针对该公钥和信息的另一个有效签名。ECDSA 签名算法则有内在的可延展性,这是 BIP 62 和 BIP 146 针对的问题。
第三,Schnorr 签名算法是线性的,使得多个合作方能生成对他们的公钥之和也有效的签名。这一特点对多重签名、批验证(Batch Verification)等应用非常重要,既能提高效率,也有助于保护隐私。而在 ECDSA 签名算法下,如无额外的见证数据,批验证相对逐个验证并无效率提升。
最后,Schnorr 签名算法因为使用同样的椭圆曲线 secp256k1 和哈希函数 SHA256,能兼容目前的比特币公私钥生成机制。

(二) Schnorr 签名算法

公私钥生成


签名生成


签名验证

批验证

图 2:逐个验证签名的时间 / 批验证所需时间

(三) Schnorr 签名算法与多重签名

密钥生成

签名生成

签名验证

三、Taproot 升级
Taproot 升级可以视为默克抽象语言树(Merkelized Abstract Syntax Tree,简称 MAST)的一个应用,而 MAST 又与支付到脚本哈希(Pay-to-Script-Hash,简称 P2SH)有关。因此,这部分依次介绍 P2SH、MAST 和 Taproot。

(一) P2SH
P2SH 是 2012 年推出的一类新型交易,使复杂脚本的使用与直接向比特币地址支付一样简单。在 P2SH 中,复杂的锁定脚本被其哈希值所取代,称为兑换脚本(Redeem Script)。当随后出现的一笔交易试图花费这个 UTXO 时,必须包含与哈希值匹配的脚本,同时解锁脚本。P2SH 的主要优点包括:一是在交易输出中,复杂脚本由哈希值取代,使得交易代码变短。二是将构建脚本的负担转移至接收方,而非发送方。三是隐私保护性更好。理论上,除了接收方,任何其他方都可以不知道兑换脚本中包含的支出条件。比如,在多重交易中,发送方可以不知道与多重签名地址有关的公钥;只在接收方支出资金时,才披露公钥。但 P2SH 也存在不足:一是所有可能的支出条件最终都必须被披露,包括那些实际上没有被触发的支出条件。二是在有多个可能的支出条件时,P2SH 将变得繁复,会增加计算和验证的工作量。

(二) MAST
MAST 使用默克树来加密复杂的锁定脚本(图 3),其叶子是一系列相互不重叠的脚本(比如,多重签名或时间锁)。要支出时,只需披露相关脚本以及从该脚本通向默克树根的路径。比如,在图 3 中,要使用 script 1,只需披露 script 1、script 2 以及 hash 3 即可。
图 3:MAST,来源: https://medium.com/@listedreserve/schnorr-and-taproot-cc4fa1edc828

MAST 的主要优点包括:一是支持复杂的支出条件。二是不用披露未被执行的脚本或未被触发的支出条件,提供更好的隐私保护。三是压缩交易大小。随着脚本数量的增加,非 MAST 交易大小是线性增长,而 MAST 交易大小是对数增长(图 4)。
图 4:脚本数量与交易大小,来源: https://bitcointechtalk.com/what-is-a-bitcoin-merklized-abstract-syntax-tree-mast-33fdf2da5e2f

(三) Taproot
但 P2SH 与常见的支付到公钥哈希(Pay-to-Public-Key-Hash,P2PKH)在表现上不一样,仍然有隐私保护问题。有没有可能让 P2SH 和 P2PKH 在链上看起来一样?这就是 Taproot 要解决的问题。
涉及有限数量签名者的脚本,可以分解成两部分:第一部分是多重签名,所有签名者都同意某一支出结果,称为「协作式支出」;第二部分称为「非协作式支出」,可以有非常复杂的脚本结构。这两部分是「或」的关系。比如,在图 3 中,Script 3 是一个 2-of-2 型多重签名,需要 Alice 和 Bob 两人都签名才有效,是「协作式支出」;Script 1 和 2 是「非协作式支出」。
图 5:Taproot,来源: https://medium.com/@listedreserve/schnorr-and-taproot-cc4fa1edc828


参考文献
1 Maxwell, Gregory, Andrew Poelstra, Yannick Seurin, and Pieter Wuille, 2018, "Simple Schnorr Multi-Signatures with Applications to Bitcoin".
区块链
2020-03-02 19:18:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最近和朋友聊策略的时候,了解到有不少使用my语言编写策略苦于灵活的问题。很多情况下需要使用非系统提供的标准K线周期,例如提出最多的就是需求使用4小时K线。这个问题已经在一篇文章中得以解决,有兴趣的可以先看下: 链接 。不过在my语言策略中这个问题由于my语言高度的封装特性,无法灵活的自行处理数据。这个时候就需要把策略思路移植为其它语言。
对于趋势策略移植来说是非常简单的,我们可以使用一段范例代码,填充驱动策略的数据计算部分代码,填充交易信号触发条件即可。 可复用的范例代码:
以用于OKEX期货的策略为例。 // 全局变量 var IDLE = 0 var LONG = 1 var SHORT = 2 var OPENLONG = 3 var OPENSHORT = 4 var COVERLONG = 5 var COVERSHORT = 6 var BREAK = 9 var SHOCK = 10 var _State = IDLE var Amount = 0 // 记录持仓数量 var TradeInterval = 500 // 轮询间隔 var PriceTick = 1 // 价格一跳 var Symbol = "this_week" function OnTick(){ // 驱动策略的行情处理部分 // 待填充... // 交易信号触发处理部分 // 待填充... // 执行交易逻辑 var pos = null var price = null var currBar = records[records.length - 1] if(_State == OPENLONG){ pos = GetPosition(PD_LONG) // 判断是不是 满足状态,如果满足 修改状态 if(pos[1] >= Amount){ _State = LONG Amount = pos[1] // 更新实际量 return } price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2 Trade(OPENLONG, price, Amount - pos[1], pos, PriceTick) // (Type, Price, Amount, CurrPos, PriceTick) } if(_State == OPENSHORT){ pos = GetPosition(PD_SHORT) if(pos[1] >= Amount){ _State = SHORT Amount = pos[1] // 更新实际量 return } price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2 Trade(OPENSHORT, price, Amount - pos[1], pos, PriceTick) } if(_State == COVERLONG){ pos = GetPosition(PD_LONG) if(pos[1] == 0){ _State = IDLE return } price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2 Trade(COVERLONG, price, pos[1], pos, PriceTick) } if(_State == COVERSHORT){ pos = GetPosition(PD_SHORT) if(pos[1] == 0){ _State = IDLE return } price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2 Trade(COVERSHORT, price, pos[1], pos, PriceTick) } } // 交易逻辑部分 function GetPosition(posType) { var positions = _C(exchange.GetPosition) var count = 0 for(var j = 0; j < positions.length; j++){ if(positions[j].ContractType == Symbol){ count++ } } if(count > 1){ throw "positions error:" + JSON.stringify(positions) } for (var i = 0; i < positions.length; i++) { if (positions[i].ContractType == Symbol && positions[i].Type === posType) { return [positions[i].Price, positions[i].Amount]; } } Sleep(TradeInterval); return [0, 0]; } function CancelPendingOrders() { while (true) { var orders = _C(exchange.GetOrders) for (var i = 0; i < orders.length; i++) { exchange.CancelOrder(orders[i].Id); Sleep(TradeInterval); } if (orders.length === 0) { break; } } } function Trade(Type, Price, Amount, CurrPos, OnePriceTick){ // 处理交易 if(Type == OPENLONG || Type == OPENSHORT){ // 处理开仓 exchange.SetDirection(Type == OPENLONG ? "buy" : "sell") var pfnOpen = Type == OPENLONG ? exchange.Buy : exchange.Sell var idOpen = pfnOpen(Price, Amount, CurrPos, OnePriceTick, Type) Sleep(TradeInterval) if(idOpen) { exchange.CancelOrder(idOpen) } else { CancelPendingOrders() } } else if(Type == COVERLONG || Type == COVERSHORT){ // 处理平仓 exchange.SetDirection(Type == COVERLONG ? "closebuy" : "closesell") var pfnCover = Type == COVERLONG ? exchange.Sell : exchange.Buy var idCover = pfnCover(Price, Amount, CurrPos, OnePriceTick, Type) Sleep(TradeInterval) if(idCover){ exchange.CancelOrder(idCover) } else { CancelPendingOrders() } } else { throw "Type error:" + Type } } function main() { // 设置合约 exchange.SetContractType(Symbol) while(1){ OnTick() Sleep(1000) } } 举例:双均线策略的移植
麦语言回测:
麦语言策略代码: MA5^^MA(C,5); MA15^^MA(C,15); CROSSUP(MA5,MA15),BPK; CROSSDOWN(MA5,MA15),SPK; 移植为JavaScript策略
首先给可复用的范例代码填充上行情获取、指标计算部分: // 驱动策略的行情处理部分 var records = _C(exchange.GetRecords) if (records.length < 15) { return } var ma5 = TA.MA(records, 5) var ma15 = TA.MA(records, 15) var ma5_pre = ma5[ma5.length - 3] var ma15_pre = ma15[ma15.length - 3] var ma5_curr = ma5[ma5.length - 2] var ma15_curr = ma15[ma15.length - 2]
可以看到,双均线策略非常简单,只是首先获取K线数据 records ,然后使用 TA函数库 的均线函数 TA.MA 计算出5日均线、15日均线(回测界面上可以看到,K线周期设置的是日K线,所以 TA.MA(records, 5) 计算出的就是5日均线, TA.MA(records, 15) 15日均线)。
然后获取 ma5 指标数据的倒数第二个点 ma5_curr (指标值),倒数第三个点 ma5_pre (指标值), ma15 指标数据同理。然后就可以使用这些指标数据去判断金叉死叉了,如图:
只要形成这样的状态,即为确定的金叉死叉。
那么判断信号的部分就可以写成: if(_State == IDLE && ma5_pre < ma15_pre && ma5_curr > ma15_curr){ _State = OPENLONG Amount = 1 } if(_State == IDLE && ma5_pre > ma15_pre && ma5_curr < ma15_curr){ _State = OPENSHORT Amount = 1 } if(_State == LONG && ma5_pre > ma15_pre && ma5_curr < ma15_curr){ _State = COVERLONG Amount = 1 } if(_State == SHORT && ma5_pre < ma15_pre && ma5_curr > ma15_curr){ _State = COVERSHORT Amount = 1 }
这样就移植OK了,可以回测试下: JavaScript策略的回测
回测配置:
回测结果:
my语言的回测
可以看到回测结果基本一样,这样如果希望对于策略继续增加交互功能、增加数据处理(例如K线合成)、增加自定义的图表画图显示就可以实现了。
有兴趣的同学动手试试吧
区块链
2020-02-28 16:34:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一、摘要
沃伦 · 巴菲特的导师本杰明 · 格雷厄姆曾经在《聪明的投资者》一书中,曾经提到过一种股票债券动态平衡的交易模式。
这种交易模式非常简单:把手中 50% 的资金投资于股票基金,剩下 50% 投资于债券基金。即股票和债券两者各占一半。根据固定间隔时间或市场变化进行一次资产再平衡,使股票资产和债券资产的比例恢复到初始的 1:1。这就是整个策略的全部逻辑,包含了什么时候买卖,以及买卖多少。够简单吧!

二、动态平衡原理
在这个方法中,债券基金的波动率其实很小,远远低于股票波动率,所以债券在这里被当做『 参照锚 』,也就是说,用债券来衡量股票究竟是涨得太多了,还是涨得太少了。

如果,股票价格上涨,会使得股票的市值大于债券的市值,当两者市值比率超过设定的阈值时,则对总仓位进行重新调整,卖出股票,并且买入债券,使股债市值比例恢复至初始的 1:1。

反之,股票价格下跌,会使得股票的市值小于债券的市值,当两者市值比率超过设定的阈值时,则对总仓位进行重新调整,买入股票,并且卖出债券,使股债市值比例恢复至初始的 1:1。
就这样,在动态平衡股票和债券之间的比例,就够享受到股票成长的果实,并且减少了资产波动率。作为价值投资的先驱,格雷厄姆为我们提供了一个很好的思路。既然这是一个完整的策略,为何我们不把它用在数字货币上呢?

三、策略逻辑
按照当前的 BTC 的价值,账户余额保留¥5000 现金和 0.1个 BTC,即现金和BTC 市值的初始比例是 1:1。如果 BTC 的价格上涨至¥6000,即 BTC 市值大于账户余额,并且其之间的差超过设定的阈值,就卖掉(6000-5000)/6000/2个币。说明 BTC 升值了,把钱兑换回来。

如果 BTC 的价格下跌至¥4000,即 BTC市值小于账户余额,并且其之间的差超过设定的阈值,就买入(5000-4000)/4000/2个币。说明 BTC 贬值了,把 BTC 买回来。就这样,不管 BTC 是升值还是贬值,始终动态保持账户余额和 BTC 的市值相等。如果 BTC 贬值了就买一些,等再涨回来,就再卖一些,就好像天平一样。

四、策略框架
那么,如何用代码去实现呢?我们以发明者量化交易平台为例,首先让我们看一下策略框架:
整个策略框架其实很简单,一个 main 主函数、一个 onTick 下单函数、一个 CancelPendingOrders 函数、以及必要参数。

五、下单模块
下单交易逻辑条理清晰,所有的注释都已经写到代码里面了,可以点击图片放大查看。

主要流程如下:
1、获取账户信息。
2、获取 Tick 数据。
3、计算 Tick 数据买卖价差。
4、计算账户余额和 BTC 市值价差。
5、计算买卖条件、下单价格、下单量。
6、下单,并返回 true。

六、撤单模块

撤单模块就更简单了,步骤如下:
1、撤单前先等待 1 秒,个别交易所,你懂的。
2、持续获取未成交订单数组,如果返回异常,则继续获取。
3、如果未成交订单数组为空,即时返回撤单状态。
4、如果有未成交的订单,则遍历整个数组,并依次根据订单号撤单。

七、完整策略源码

外部参数

八、策略回测
接下来,让我们测试一下这个简单的动态平衡策略,看看到底有没有效果。以下是在 BTC 的历史数据上的回测,仅供大家参考。

回测环境

回测绩效

回测曲线
再来一张,同时期 BTC 价格走势图
在回测时间段,BTC 已经持续了长达 8 个月下跌,甚至最大跌幅超过70%,这造成很多投资者对区块链资产失去信心。本篇策略累计收益高达 160%,年化收益风险比超过 5。对于一个这么简单的投资策略,这个投资回报率已经超过绝大多数梭哈的群众了。

九、获取策略源码
策略源码已经公开到发明者量化官网 https://www.fmz.com/strategy/110545 无需配置直接在线回测。

十、总结
本篇动态平衡策略,只有一个核心参数(threshold 阈值),是一个很简单的投资方法,追求的不是超额的收益,而是稳健的收益。与趋势策略相反,动态平衡策略却是逆势而动。而动态平衡策略则恰好相反,市场热的时候减仓降温,市场冷清的时候加仓蛰伏,有点类似宏观经济调控。

其实,动态平衡策略正是秉承了价格不可预测的观念,同时又捕捉价格波动的一门手艺。动态平衡策略的关键核心在设定和调整资产配置比例,还有触发阈值。鉴于篇幅原因,一篇文章没办法做到面面俱到,要知道文字之外,存乎一心。动态平衡策略最重要的是投资思想,你甚至可以把本篇中的单个 BTC 资产换成一篮子区块链资产组合。

最后,让我们以本杰明 · 格雷厄姆在《聪明的投资者》一书中的名言来结束本篇: 股票市场并非一个能精确衡量价值的『 称重计 』,相反它是一个『 投票机 』,不计其数的人所做出的决定是一种理性和感性的掺杂物,有很多时候这些抉择和理性的价值评判相去甚远。投资的秘诀就是在价格远远低于内在价值时投资,并且相信市场趋势会回升。 ——本杰明 · 格雷厄姆《聪明的投资者》
区块链
2020-03-17 15:11:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
区块链允许数据提供者和消费者直接在单个开放系统中交易信息,而不是订阅世界各地的数十个集中服务,并编写他们的软件来与每个API进行通信。阅读此区块链API教程,了解如何根据你的特定需求使用它。
API(应用程序编程接口)是单个计算机程序可以用来与另一个程序交互的方法(类,过程,函数,结构或常量)的描述。它通常包含在任何Internet协议(例如RFC)的描述中,软件框架或对操作系统函数的标准调用。它通常由单独的软件库或操作系统服务实现。开发人员通常使用区块链API来编写各种应用程序。
API定义程序(模块,库)提供的功能,并允许从该功能的实现方式中抽象出来。软件组件通过API相互交互。在这种情况下,组件通常形成层次结构:高级组件使用低级组件的API,而这些组件又使用甚至更低级别组件的API。通过因特网进行数据传输的协议是根据该原理构建的。
标准协议栈(OSI网络模型)包含7层(从物理位传输层到应用协议层,类似于HTTP和IMAP协议)。每个级别使用先前底层数据传输级别的功能,并为下一个覆盖级别提供必要的功能。
注意:协议的概念与API的概念意义相近。两者都是功能的抽象,除了协议涉及数据传输,而API与应用程序的交互相关。
区块链API品种
区块链软件的开发通常包括各种困难部分。其中最重要的是创建区块链API接口。有些项目通过提供以下API服务来帮助用户和开发人员:
网站收到比特币付款的难以置信的简便方式。这种服务是完全安全的,是商务或个人使用的理想选择: 区块链链接的钱包服务。 用于从区块链钱包发送和接收付款的API。 每个块和交易的数据请求的JSON。 用于请求的简单区块链API:用于查询区块链数据的文本格式的简单API。 Web套接字:具有低延迟的流式套接字,为新块和交易提供数据。
让我们从区块链钱包API评论开始。区块链Wallet API提供了一个简单的界面。要使用此API,你需要启动一个负责管理钱包的小型本地服务。你的应用程序通过HTTP API调用在本地与此服务进行交互。
现在,你可以从新的区块链钱包API转移比特币。所有交易均价值0.0001 BTC矿工的费用。这是它在PHP中的样子: <? $guid="GUID_HERE"; $firstpassword="PASSWORD_HERE"; $secondpassword="PASSWORD_HERE"; $amounta = "10000000"; $amountb = "400000"; $addressa = "1A8JiWcwvpY7tAopUkSnGuEYHmzGYfZPiq"; $addressb = "1ExD2je6UNxL5oSu6iPUhn9Ta7UrN8bjBy"; $recipients = urlencode('{ "'.$addressa.'": '.$amounta.', "'.$addressb.'": '.$amountb.' }'); $json_url = "http://localhost:3000/merchant/$guid/sendmany?password=$firstpassword&second_password=$secondpassword&recipients=$recipients"; $json_data = file_get_contents($json_url); $json_feed = json_decode($json_data); $message = $json_feed->message; $txid = $json_feed->tx_hash; ?>
WebSocket API允许开发人员获取有关新交易和块的实时数据。
从URL链接 wss://ws.blockchain.info/inv 开始。部署套接字时,用户通过发送 op 消息 {“op”:“ping”} 来订阅该频道。然后,订阅有关所有新比特币交易的通知 {“op”:“unconfirmed_sub”} 。最后,订阅地址 {“op”:”addr_sub”, “addr”:”$bitcoin_address”} 。
有关新交易的通知如下所示: "op": "utx", "x": { "lock_time": 0, "ver": 1, "size": 192, "inputs": [ { "sequence": 4294967295, "prev_out": { "spent": true, "tx_index": 99005468, "type": 0, "addr": "1BwGf3z7n2fHk6NoVJNkV32qwyAYsMhkWf", "value": 65574000, "n": 0, "script": "76a91477f4c9ee75e449a74c21a4decfb50519cbc245b388ac" }, "script": "483045022100e4ff962c292705f051c2c2fc519fa775a4d8955bce1a3e29884b2785277999ed02200b537ebd22a9f25fbbbcc9113c69c1389400703ef2017d80959ef0f1d685756c012102618e08e0c8fd4c5fe539184a30fe35a2f5fccf7ad62054cad29360d871f8187d" } ], "time": 1440086763, "tx_index": 99006637, "vin_sz": 1, "hash": "0857b9de1884eec314ecf67c040a2657b8e083e1f95e31d0b5ba3d328841fc7f", "vout_sz": 1, "relayed_by": "127.0.0.1", "out": [ { "spent": false, "tx_index": 99006637, "type": 0, "addr": "1A828tTnkVFJfSvLCqF42ohZ51ksS3jJgX", "value": 65564000, "n": 0, "script": "76a914640cfdf7b79d94d1c980133e3587bd6053f091f388ac"
对于区块链数据API,如果向 GET 请求添加 &cors=true 参数,则可以使用 CORS 进行一些数据API调用。
CORS(跨源资源共享)是现代浏览器的一种技术,它提供可以访问另一个域的资源的网页。直到最近,克服同源策略对XSS请求施加的限制的主要方法是使用JSONP。JSONP本身有一个致命的限制:它只能通过GET方法接收数据。通过POST方法发送数据仍然无法访问。
技术本身非常简单。有三个域希望从服务器下载资源。为了实现这一点,提供内容的Web服务器足以在响应头中指示可信域列表Access-Control-Allow-Origin:A,B,C。然后相同源原则的限制 在请求的页面上将不适用于这些域的页面。要启动跨源请求,客户端浏览器会向HTTP请求(发出请求的站点域)添加原始请求。例如,页面 http://www.a.com/page.html尝试从http://www.b.com/cors.txt页面获取数据。
在区块链数据API中,单个块如下所示: "hash":"0000000000000bae09a7a393a8acded75aa67e46cb81f7acaa5ad94f9eacd103", "ver":1, "prev_block":"00000000000007d0f98d9edca880a6c124e25095712df8952e0439ac7409738a", "mrkl_root":"935aa0ed2e29a4b81e0c995c39e06995ecce7ddbebb26ed32d550a72e8200bf5", "time":1322131230, "bits":437129626, "nonce":2964215930, "n_tx":22, "size":9195, "block_index":818044, "main_chain":true, "height":154595, "received_time":1322131301, "relayed_by":"108.60.208.156", "tx":[--Array of Transactions--]
区块链图表和统计API允许与blockchain.info上显示的图表和统计信息进行交互。(区块链信息API)。
可以使用Charts API方法接收有关blockchain.info图表的信息: "status": "ok", "name": "Confirmed Transactions Per Day", "unit": "Transactions", "period": "day", "description": "The number of daily confirmed Bitcoin transactions.", "values": [ { "x": 1442534400, // Unix timestamp (2015-09-18T00:00:00+00:00) "y": 188330.0 }, ...
Stats API可用于接收有关blockchain.info统计信息的信息: "market_price_usd": 610.036975, "hash_rate": 1.8410989266292908E9, "total_fees_btc": 6073543165, "n_btc_mined": 205000000000, "n_tx": 233805, "n_blocks_mined": 164, "minutes_between_blocks": 8.2577, "totalbc": 1587622500000000, "n_blocks_total": 430098, "estimated_transaction_volume_usd": 1.2342976868108143E8, "blocks_size": 117490685, "miners_revenue_usd": 1287626.6577490852, "nextretarget": 431423, "difficulty": 225832872179, "estimated_btc_sent": 20233161880242, "miners_revenue_btc": 2110, "total_btc_sent": 184646388663542, "trade_volume_btc": 21597.09997288, "trade_volume_usd": 1.3175029536228297E7, "timestamp": 1474035340000
比特币API
接受比特币支付变得越来越受欢迎和需求。在网站上接受比特币支付的方法有很多种。最方便的方法之一是区块链API。在这里,你不需要绑定特定语言或SDK;你甚至不需要在那里注册。所需要的只是拥有一个钱包来接受比特币,并有时间将相当简单的API连接到你的系统。此外,客户不会看到你的钱包,而是交易所的临时钱包。
在直接谈论代码之前(我们将在示例中使用PHP,但可以在Java,Python等中轻松实现),有必要阐明支付接受机制本身。
整个过程符合以下顺序: 1.用户通过发送一系列数据从区块链请求临时钱包。 2.区块链返回其临时钱包以接收对用户的付款。 3.用户向客户端显示此钱包,以及有关如何处理的一小组说明。 4.客户付款(将资金转入钱包)。 5.用户应该等待比特币系统中的支付验证。 6.在区块链系统成功验证的情况下,将在用户的站点上调用脚本(用户必须指明哪个),并且传输所有交易数据。 7.之后,在用户系统内安全地确认支付。
要获得临时钱包,你应该发送一系列数据: 在成功确认交易的情况下将被抄写的脚本的URL。值得注意的是,建议指定某个参数(甚至是一些参数),以便识别当前系统中的付款。只需在用户系统中指定客户端ID并将任何数据输入数据库,但只有在收到确认交易后才可以。但是,官方文档建议使用预先创建的付款编号和任何验证短语。总的来说,我们通过常规GET传输请求中的参数获取URL。对于区块链系统,此参数称为回调。应该将值编码为URL链接。 用户钱包用于接收付款。区块链将把收到的钱转移到这个钱包。参数被称为地址。 最后一个参数被称为方法,并用于创建临时钱包。
此数据将发送到区块链脚本( https://blockchain.info/api/receive),每个参数都是常用的GET参数。其执行结果由用户系统处理(结果将采用JSON格式)。关于区块链信息API的所有内容都在区块链API文档中说明。
现在,用户已准备好接受对钱包的付款,但无法从系统中注册其收据的事实。用户应该记住,在实际系统中,建议使用经过深思熟虑且编写良好的代码,以及存储准备好的付款的数据库(将付款号码,用户ID存储在系统和验证短语或其组成部分)。此外,验证付款的时间可能不同且非常重要,比特币汇率可能会发生变化。用户有两种选择:在付款时保留费率,或在收到交易确认后请求费率。
交易确认收据文件应该叫做receive_payment.php,并且应该存储在网站的根目录中;在请求临时钱包时,用户在创建 $ callback_url 时指定了其名称。
实际上,同一付款的脚本不仅会被调用一次,而且会根据其在各个节点上的确认数量来调用。这意味着用户必须先检查是否有确认。
区块链提供了许多参数: Transaction_hash,唯一的交易哈希。 Input_transaction_hash,原始交易的唯一哈希值。 Input_address,将收到付款的区块链钱包。 Destination_address,将发送付款的用户的钱包。 Confirmations,按节点确认的数量(如果此参数的值大于或等于6,则建议接受付款确认)。
value参数在Satoshi中生成值,而不是比特币(1Satoshi=0.00000001BTC)。因此,结果值应该减少到比特币。名为invoice_id和secret的参数由用户在接收区块链钱包阶段设置。因此,可能存在更多或更少的它们,并且它们可以具有任何名称。
建议将收到的值存储在支付历史中的比特币中;但是,应该将其转换为另一种货币(例如美元),由用户系统使用。如果系统仅适用于比特币,则无需转换任何内容。
有单独的汇率API文档,用于将比特币转换为其他货币。用户必须指定两个参数: 货币名称(货币列表在文档中可用,用户也可以使用调用 Print_r($ Exchange_data_obj) 获取它。 用户想要兑换的比特币数量。
区块链开发平台和API
今天,有许多公司开发提供应用程序开发工具的平台和项目。Blockchain.info有许多区块链信息API,用于处理他们的电子钱包服务(这是最大的电子钱包服务之一),旨在发送和接收付款并执行其他操作。该链创建了用于访问分布式记录注册表的完整节点中包含的数据的接口,以及标准信息请求:例如,关于你的比特币余额。此外,你可以在特定地址执行操作时发送通知。
Stellar是一个半去中心化的(由网关组织服务,而不是矿工),可公开访问的日志和统一开发环境(区块链API,多签名API)绑定到Stripe支付网络。还有其他公司拥有带有多边签名的区块链钱包API,例如Block.io,Gem,BlockCypher等。
将来,需要更加统一的区块链API开发环境,包括区块链生态系统的各种不断变化的组件(存储,文件维护,钱包交互,移动支付,身份验证和声誉)。智能合约将允许我们创建一个全球气象数据市场 meteorological data market ,消费者将在其中请求实时数据并以通用格式接收数据(使用区块链信息API)。
集中数据提供商可以告别自己的格式和销售活动,而是将数据传送到全球可访问的气象市场dApp。可以将区块链的开发环境与其他大型网段联系起来:例如,机器到机器(M2M)通信和物联网网络的基础设施,用于快速应用程序开发。在遥远的未来,这种类型的高级集成应用程序的一个例子可以是与智能城市基础设施内的交通传感器交互的智能手表,以便使用比特币中的智能合约自动预留和支付流量。
API操作系统和多样性问题
几乎所有操作系统(UNIX,Windows,OS X等)都有一个API,程序员可以使用该API为操作系统创建应用程序。主API操作系统是一组系统调用。应该注意的是,开发人员通常有几种不同的API来实现相同的结果。此外,每个API通常使用较低抽象级别的API程序组件来实现。例如:为了看到“Hello,world!”这一行,在浏览器中,你只需创建一个具有最小标题的HTML文档和包含给定行的最简单的主体。
当浏览器打开此文档时,浏览器程序会将文件的名称(或已打开的文件描述符)传输到处理HTML文档的库,而库文件将使用操作API系统读取此文件,然后通过“clear window”类型的标准图形/基本操作的API库调用它。在所选字体中写下“Hello,world!”。在执行这些操作期间,图形基元库将使用相应的请求访问窗口接口库。该库已经与操作系统API联系,将数据写入视频卡缓冲区。
与此同时,几乎每个级别实际上都有几种可能的替代API。例如,我们可以不在HTML上编写源文档,而是在LaTeX上编写。我们可以使用任何浏览器进行显示。一般来说,不同的浏览器使用不同的HTML库,所有这些都可以使用不同的原始库和不同的操作系统进行编译。
因此,现有多级API系统的主要困难是: 将软件代码从一个API系统移植到另一个API系统的复杂性(例如,更改操作系统时)。 从较低级别移动到较高级别时的功能丧失。粗略地讲,每个API“层”被创建以促进一些标准操作集的执行。但同时,它真的很难,或者它根本不可能执行由较低API级别提供的其他操作。 从一个API移动到另一个API时移植程序代码的困难。将模块传输到其他操作系统时经常会出现这些问题。 从低级管理到高级管理时,降低接口功能的范围。在这种情况下,促进了严格定义的任务类别的实施。与此同时,访问其他监管机构的控制权已经失去了。毕竟,较低级别允许你轻松管理程序的基本组件。
软件接口的分类与通过它们控制的应用程序的目的和功能密切相关。事实上,在运行复杂系统时,通常有其他API可以通过其他方式解决相同的问题。
单独的组分配用于管理软件模块(wxWidgets,Qt,GTK等),操作系统(Amiga ROM内核,Cocoa,Linux内核API,OS/2 API,POSIX,Windows API),声音(DirectMusic /)的图形组件的接口DirectSound,OpenAL),窗口接口等。它们的分离取决于层次结构和功能中的应用程度。计算机游戏的用户通常不会怀疑这个图形API为他们提供如此快速的图片绘制和惊人的图像亮度。
全局区块链API通常包括各个编程语言的接口。在他们的帮助下,你可以管理非常具体和本地任务的解决方案。这一切都取决于具体算法的实现。
总结
区块链引发了大量极其重要的问题。它的使用具有广泛的优势:拒绝第三方,保护交易,安全交易,资源共享,保证交易,自动执行合约等。
让我们从角度看一下这项技术: 区块链可以包含多个API,包括简单区块链API,区块链信息API,区块链钱包API,交易脚本语言,P2P节点通信API和用于检查网络中的交易的客户端API。 应用程序编程接口(API)现在包含在密码保护的公共基础结构中(区块链)。 区块链被用作数据库的一种新形式:例如,作为永久存储不可变密码区块链API密钥(或哈希)的分布式哈希表(DHT),与大量存储的数据链相关联。 一种新型浏览器将允许用户运行去中心化式应用程序(Dapps),而不仅仅是网页(例如,以太坊中的Mist)。
它还可以解决许多更棘手的问题。其中之一是集中化。区块链技术在未来的世界中可能非常有用,在这个世界中,集中式和去中心化式模型都将得到应用。它不仅会破坏现有的陈规定型观念和计划,还有助于发展结合了旧的和创新的方法的大型生态系统。
如果你需要有关区块链技术的更多信息,请联系应用团队。
==================================================================
如果你想学习区块链并在Blockchain Technologies建立职业生涯,那么请查看我们分享的一些以太坊、比特币、EOS、Fabric等区块链相关的交互式在线编程实战教程: java以太坊开发教程 ,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。 python以太坊 ,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。 php以太坊 ,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。 以太坊入门教程 ,主要介绍智能合约与dapp应用开发,适合入门。 以太坊开发进阶教程 ,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。 ERC721以太坊通证实战 ,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。 C#以太坊 ,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。 java比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。 php比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。 c#比特币开发教程 ,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。 EOS入门教程 ,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。 深入浅出玩转EOS钱包开发 ,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。 Hyperledger Fabric 区块链开发详解 ,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。 Hyperledger Fabric java 区块链开发详解 ,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。 tendermint区块链开发详解 ,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是 如何更好的利用区块链API
区块链
2019-06-18 14:33:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一、摘要
价格不是上就是下,长期而言,价格的涨跌概率应各是50%,那么要正确预测未来的价格,就需要实时获取影响价格的全部因素,然后给每个因素一个正确权重,最后作出客观理性分析。要把影响价格的全部因素罗列出来,可能会写满整个屏幕。
概括为:全球经济环境、国家宏观政策、相关产业政策、供需关系、国际事件、利率与汇率、通货膨胀与紧缩、市场心理、未知因素等等。预测也就变成了一个工程浩大,又不可能完成的任务。所以很早的时候,我就明白市场不可预测。那么在市场中所有的预测,都变成了假设,交易也成了概率游戏,这就有意思了。
二、为何利用资金流向
既然市场无法预测,那真的就无动于衷了吗?不,所有的宏观因素和微观因素都已经反映到价格上了,也就是说价格是全部因素相互作用的结果。我们只需要分析价格,就可以做出一个完整的交易策略。
先仔细想一想,为什么价格会涨?
你可能会说,因为:国家对相关产业政策扶持、原产地又双叒叕下暴雨了、国际贸易战、MACD金叉了、别人都买了等等,当然这些也许都没错。事后看,总能找出推动价格上涨的理由。
其实,价格的涨跌类似于水涨船高。价格的上涨离不开资金的推动,盘面上,如果买的人多过卖的人,价格就会上涨。反之,如果卖的人多过买的人,价格就会下跌。有了这个概念,我们就可以根据资金净流向反映出来的供求关系,对未来价格的走势给出合理的预期。
三、资金流向原理
与传统分析不同的是,资金流向分析根据一段时间序列的交易数据中,分析哪些成交是资金主动流入的,哪些成交是资金主动流出。然后,把该时间段主动流入的成交量减去主动流出的成交量,便可以知道该时间段的资金净流入。如果资金净流入为正,表示该品种供不应求;如果资金净流出,则表示该品种供过于求。
读到这里,可能有人会疑问,在实际交易中,有人买有人卖才会成交。成交的单子必然是有多少买量就有多少卖量,资金进出一定是等量的。何来资金流入流出呢?其实严格来说,每一个买单必然对应一个相应的卖单,资金流入和资金流出一定是相等的。如果我们想要计算出哪些成交的单子是主动性买入的,哪些单子是主动性卖出的,只能用一个折中的方法,利用bar数据,根据成交量和价格来实现。
四、资金流向计算方法
资金流向的变化准确对应着实时的市场行为,通过整合bar数据,实时计算资金净流向。关于计算资金主动性流向有两种算法: 第一种,如果当前单子的成交价是以对手价或超价成交的,买入成交价 >= 卖一价,代表买家更愿意以较高的价格完成交易,即计入资金主动性流入。 第二种,如果当前成交价格 > 上次成交价格,那么可以理解为,当前的成交量主动推升了价格的上涨,即计入资金主动性流入。
以上述第二种算法为例:
某个品种在 10:00 的收盘价是 3450,在 11:00 的收盘价是3455,那么我们就把 10:00 ~ 11:00 的成交量计入资金主动性流入。反之则计入资金主动性流出。而本文是在第二种方法的基础上,加入了价格波动幅度这个因素,通过前后bar收盘价对比,把上涨或下跌的bar的成交量 * 波动幅度计入到一个序列,然后根据该序列进一步计算资金的主动性流入比率。
五、交易逻辑
本文从“量”的角度来刻画期货市场的资金流向,通过实时分析bar数据,建立判断短期价格走向的交易模型。一般的情况下,资金流向及价格走势可以分为四种基本状况: 价格上升,同时单位时间内资金主动性净流入:这种情况下属于强势,未来价格继续上升概率更大; 股价上升,同时单位时间内资金主动性净流出:这种情况下属于中强势,未来价格继续上升的速度大幅减弱; 股价下跌,同时单位时间内资金主动性净流入:这种情况下属于弱势,未来价格继续下跌概率更大; 股价下跌,同时单位时间内资金主动性净流出:这种情况下属于中弱势,未来价格继续下跌的速度大幅减弱;
主要变量,如下: 前期低点(ll) 前期高点(hh) 主动性买入(barIn) 主动性卖出(barOut) 主动流入资金与主动流出资金的比值(barRatio) 开仓阈值(openValve) 当前持仓(myAmount) 上根K线收盘价(close)
出入场条件 一个好的量化交易策略,不仅需要稳定的收益,而且能够控制风险,在小概率时间出现时,避免出现较大亏损。在这里我们使用跟踪主动性资金流向策略,借助短期价格预测对商品期货行情方向进行分析,从而达到高收益、低风险的效果。 策略的步骤如下图: 多头开仓:如果当前无持仓,并且barRatio > openValve,买入开仓; 空头开仓:如果当前无持仓,并且barRatio < 1 / openValve,卖出开仓; 多头平仓:如果当前持有多仓,并且close < ll,卖出平仓; 空头平仓:如果当前持有空仓,并且close > hh,买入平仓;
六、编写策略源码
获取并计算数据 function data() { var self = {}; var barVol = []; var bars = _C(exchange.GetRecords); //获取bar数据 if (bars.length < len * 2) { //控制bar数据数组的长度 return; } for (var i = len; i > 0; i--) { var barSub_1 = bars[bars.length - (i + 1)].Close - bars[bars.length - (i + 2)].Close; //计算当前收盘价与上个bar收盘价的价差 if (barSub_1 > 0) { //如果价格涨了,就在数组里面添加正数 barVol.push(bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low)); } else if (barSub_1 < 0) { //如果价格跌了,就在数组里面添加负数 barVol.push(-bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low)); } } if (barVol.length > len) { barVol.shift(); //释放多余的数据 } self.barIn = 0; self.barOut = 0; for (var v = 0; v < barVol.length; v++) { if (barVol[v] > 0) { self.barIn += barVol[v]; //合并全部主动流入的资金 } else { self.barOut -= barVol[v]; //合并全部主动流出的资金 } } self.barRatio = self.barIn / Math.abs(self.barOut); //计算主动流入资金与主动流出资金的比值 bars.pop(); //删除未结束的bar数据 self.close = bars[bars.length - 1].Close; //获取上根K线的收盘价 self.hh = TA.Highest(bars, hgLen, 'High'); //获取前高 self.ll = TA.Lowest(bars, hgLen, 'Low'); //获取前低 return self; }
通过发明者量化API中的GetRecords方法,直接获取bar数据。包含最高价、最低价、开盘价、收盘价、成交量、标准时间戳。如果最新的成交价大于上次的成交价,那么就把最新的成交量 * (最高价 - 最低价)计入主动性买入;如果最新的成交价小于上次的成交价,那么就把最新的成交量 * (最高价 - 最低价)计入主动性卖出;
获取持仓数据 function positions(name) { var self = {}; var mp = _C(exchange.GetPosition); //获取持仓 if (mp.length == 0) { self.amount = 0; } for (var i = 0; i < mp.length; i++) { //持仓数据处理 if (mp[i].ContractType == name) { if (mp[i].Type == PD_LONG || mp[i].Type == PD_LONG_YD) { self.amount = mp[i].Amount; } else if (mp[i].Type == PD_SHORT || mp[i].Type == PD_SHORT_YD) { self.amount = -mp[i].Amount; } self.profit = mp[i].Profit; } else { self.amount = 0; } } return self; }
通过发明者量化API中的GetPosition方法获取基础持仓数据,并对这些基础数据进一步处理,如果当前持有多单,那么就返回正持仓数量;如果当前持有空单,那么就返回负持仓数量。这样做的目的是方便计算开平仓逻辑。
下单交易 function trade() { var myData = data(); //执行data函数 if (!myData) { return; } var mp = positions(contractType); //获取持仓信息 var myAmount = mp.amount; //获取持仓数量 var myProfit = mp.profit; //获取持仓浮动盈亏 if (myAmount > 0 && myData.close < myData.ll) { p.Cover(contractType, unit); //多头平仓 } if (myAmount < 0 && myData.close > myData.hh) { p.Cover(contractType, unit); //空头平仓 } if (myAmount == 0) { if (myData.barRatio > openValve) { p.OpenLong(contractType, unit); //多头开仓 } else if (myData.barRatio < 1 / openValve) { p.OpenShort(contractType, unit); //空头开仓 } } }
七、策略特点
特点:
核心参数少:模型设计思路清晰,核心参数只有3个。可优化空间很小,可以有效避免过度拟合。 较强的普适性:策略逻辑简单,具有高普适性,除农产品外适应大部分品种,可以进行多品种组合。
改进:
加入持仓量条件:单向(股票)市场资金流向可以根据价格涨跌、成交量等因素来界定资金的流入或流出。 但是,由于该策略并没有加入持仓量这个条件,使得统计主动性资金流向可能会失真。
加入标准差条件:仅仅依靠资金流向来作开仓条件,可能会出现频繁的虚假信号,造成频繁开平仓。通过统计指定时间内的资金净流出的平均值,上下加上标准差,来过滤虚假信号。
完整策略源码: /*backtest start: 2016-01-01 09:00:00 end: 2019-12-31 15:00:00 period: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ var p = $.NewPositionManager(); //调用商品期货交易类库 //持仓数据处理 function positions(name) { var self = {}; var mp = _C(exchange.GetPosition); //获取持仓 if (mp.length == 0) { self.amount = 0; } for (var i = 0; i < mp.length; i++) { //持仓数据处理 if (mp[i].ContractType == name) { if (mp[i].Type == PD_LONG || mp[i].Type == PD_LONG_YD) { self.amount = mp[i].Amount; } else if (mp[i].Type == PD_SHORT || mp[i].Type == PD_SHORT_YD) { self.amount = -mp[i].Amount; } self.profit = mp[i].Profit; } else { self.amount = 0; } } return self; } //行情数据处理函数 function data() { var self = {}; var barVol = []; var bars = _C(exchange.GetRecords); //获取bar数据 if (bars.length < len * 2) { //控制bar数据数组的长度 return; } for (var i = len; i > 0; i--) { var barSub_1 = bars[bars.length - (i + 1)].Close - bars[bars.length - (i + 2)].Close; //计算当前收盘价与上个bar收盘价的价差 if (barSub_1 > 0) { //如果价格涨了,就在数组里面添加正数 barVol.push(bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low)); } else if (barSub_1 < 0) { //如果价格跌了,就在数组里面添加负数 barVol.push(-bars[bars.length - (i + 1)].Volume * (bars[bars.length - (i + 1)].High - bars[bars.length - (i + 1)].Low)); } } if (barVol.length > len) { barVol.shift(); //释放多余的数据 } self.barIn = 0; self.barOut = 0; for (var v = 0; v < barVol.length; v++) { if (barVol[v] > 0) { self.barIn += barVol[v]; //合并全部主动流入的资金 } else { self.barOut -= barVol[v]; //合并全部主动流出的资金 } } self.barRatio = self.barIn / Math.abs(self.barOut); //计算主动流入资金与主动流出资金的比值 bars.pop(); //删除未结束的bar数据 self.close = bars[bars.length - 1].Close; //获取上根K线的收盘价 self.hh = TA.Highest(bars, hgLen, 'High'); //获取前高 self.ll = TA.Lowest(bars, hgLen, 'Low'); //获取前低 return self; } //交易函数 function trade() { var myData = data(); //执行data函数 if (!myData) { return; } var mp = positions(contractType); //获取持仓信息 var myAmount = mp.amount; //获取持仓数量 var myProfit = mp.profit; //获取持仓浮动盈亏 if (myAmount > 0 && myData.close < myData.ll) { p.Cover(contractType, unit); //多头平仓 } if (myAmount < 0 && myData.close > myData.hh) { p.Cover(contractType, unit); //空头平仓 } if (myAmount == 0) { if (myData.barRatio > openValve) { p.OpenLong(contractType, unit); //多头开仓 } else if (myData.barRatio < 1 / openValve) { p.OpenShort(contractType, unit); //空头开仓 } } } //程序主入口,从这里启动 function main() { while (true) { //进入循环 if (exchange.IO("status")) { //如果是开市时间 _C(exchange.SetContractType, contractType); //订阅合约 trade(); //执行trade函数 } } }
策略地址: https://www.fmz.com/strategy/87698
八、策略回测
策略配置: 回测绩效:
九、总结
本篇通过建模,利用BotVS量化交易平台提供的商品期货bar数据,通过收集数据、相关分析、预测技术、建立净资金流向模型。利用时间序列分析,对未来商品期货价格进行预测,并设计出商品期货量化交易策略。
需要注意的是:本文所指的资金流向是资金主动性流向,是市场上买卖双方对垒力量的强弱,而不是指资金的进场或离场。通过分析市场上买卖双方行为,判断未来价格,不具有短线参考意义。
区块链
2020-02-17 12:11:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一种最重要的共识,“钱”
世界上所有的商业系统都是为了赚钱,钱是价值的度量这是这个文明系统中最重要的共识,甚至包括某些非商业系统在某种程度上也是为了赚钱,只要你愿意逻辑下去所有的业务系统都是为了赚钱。挖矿造币只解决的是钱的发行问题,解决的是钱的发行必须绑定生产力的问题。某国家发行的币的性质决定了B国不可能使用A国的币,因为AB国是平等的竞争关系而不是从属关系,别人可以随意增发制造竞争优势。区块链挖矿造币不解决支付问题且解决支付问题不是区块链造币的目标。
观察到两种造币力量
力量就是“能”、“力”、“能力”和“量”、“度量”
1, 传统造币力量:
现行的法币系统是PoW的(司法、行政、军队、执法等是传统的PoW力量)。
2, 新兴造币力量:
PoW区块链挖矿造币,挖矿是新兴的PoW力量,只有力量才能提供信用,PoW挖矿之所以能成功是因为它没有改变本质只是换一种证明力量的形式。
挖矿可以消耗掉生产资料和人的能力,这就是实实在在的价值,消耗能力证明了生产能力,消耗的越多证明生产力越高生产的越多,耗能是区块链造币的最重要的价值,因为只有耗能才能成功构建共识,不耗能不可能成功构建出共识,不耗能不可能得到信用。只有PoW才能成功改造最重要的那个共识——“钱”共识,只有消耗才能提高生产力,在挖矿还没消耗掉总生产力的一半开启文明新纪元之前挖矿最大的价值就是可以增加消耗,消耗越多越好,反正不生产就没法消耗,反正消耗了至少证明了生产了。
如果我们一直都在浪费一半的口罩生产力,如果1个馒头就能吃饱但我们一直都生产两个馒头销毁一个的话应对今天的疫情就会更加从容一些。
既不属于传统也不属于新兴的虚假的造币力量,比如POS:
POS这种属于空气币,因为它没有证明生产力,如果对比传统系统的话POS不仅没有证明生产力而且降低效率,PoS等其它共识形式之所以会失败就是因为它直接改变了本质试图凭空制造信用就像是试图制造永动机试图改变物理规律。POS等不产能不耗能是切切实实的(传)(销)。
社会运行的方法和表层驱动力,“ 赚钱 ”
世界上所有的商业系统都是为了赚钱,钱是价值的度量这是这个文明系统中最重要的共识,甚至包括某些非商业系统在某种程度上也是为了赚钱,只要你愿意逻辑下去追根溯源的话所有的业务系统都是为了赚钱。既然业务系统是为了赚钱,当然效率第一,怎么样能提高赚钱的效率怎么样来,这决定了除了造币系统之外的业务系统都不可能使用区块链技术构建自己的业务系统因为区块链低效,因为区块链降低了业务系统赚钱的效率。
BTC和ETH让大家都赚到了钱:研发、设计、制造、生产、运输、分销、二手交易、建厂、发电、运维……每个环节都是实体大家都赚钱。反例,比如硬盘币耗电太少不算PoW,当初硬盘币鼓吹者以为是优势,结果矿场不欢迎、电厂不欢迎、矿池不欢迎、矿工不欢迎、几乎所有人都不欢迎导致大家赚不到钱证明了硬盘挖矿不是个好协议。如果要问大家都赚到钱的话那钱从哪来的?从数字货币宏利中赚钱,数字货币有上涨的趋势,有取代现有法币成为全球范围内的法币的趋势,判断是否成为全球货币的标准是数字货币的市值是否超过了A大国或B大国任何中的一个的市值,或者用黄金的市值来判断:数字化货币还需要增长40倍才能超越黄金。
区块链无法成功改造支付业
世界空间是巨大的,其中的活动是分散的并行进行的,隔壁城市马路上的人的活动不会影响你我的活动,小区花园里的花开与卧室的灯亮无关,世界是并行的分散的,服务于世界上的活动的计算机系统当然也是分散的并行的。而区块链是个时序系统,是有严格的先后顺序的(这决定了它必须发生在一个一次只能通过一个问题单元的狭小的空间),区块链时序系统只是用来构建共识用的。社会运行方法中只有一个最重要的共识就是度量价值的“钱”,钱度量一切,其它一切业务系统只需建立和钱的转化就行了,基于区块链技术改造造币系统之外的业务系统降低赚钱的效率导致它根本就不可能成功,非造币系统外的其它系统不需要改造自己领域内的逻辑,因为已有的逻辑是比区块链更好的,使用区块链技术是倒退,区块链造币但不负责支付,挖矿造币解决的是钱的发行问题,解决的是钱的发行必须绑定生产力的问题。
区块链无法成功改造支付业,但可以改造银行
判断是否成为全球货币的标准是数字货币的市值是否超过了A大国或B大国任何中的一个的市值,或者用黄金的市值来判断:数字货币还需要增长40倍才能超越黄金。世界上的活动是并行的,支付系统当然也是并行的,高效的支付系统必须巨头信用。随着数字货币市值的增高,承担支付任务的银行业必将改变,要么接入造币系统为造币系统提供支付服务,要么被为造币系统服务的新兴银行取代。
下载开源矿工
区块链
2020-02-07 12:19:00