ether环境搭建(一)
因为公司继续开发,使用的操作比较简明的 centos7.4 Linux环境.主要做一个发布以太坊代币的系统
第一章,生产环境的安装
1. 需要安装
rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
2. 因为eth基于golang 所以首先安装golang语言编译器
yum install golang
3. 下载以太坊源码(因为在外国服务器所以可以使用git直接clone github上的源码)
git@github.com:ethereum/go-ethereum.git //// https://github.com/ethereum/go-ethereum.git
4. 下载完完成后需要制作生产环境!!!
make (在clone下来的源码根目录)
5. 静悄悄的等待上一步编译完成。会出现build文件进入到 build/bin
cd build/bin (同样是在源码目录进入)
6. 上面几步完成,eth的生产环境基本就完成了。这一步是启动 geth – —–看完再复制最下面的命令拿去粘贴!!!
(这条命令不要直接复制,需要把 rpcaddr 的接口调用设置成内网ip;切记是内网ip—–你节点服务器的内网ip就行,至于原理慢慢体会,不多讲了 如果外网的话在你把这条命令的打出去以后你的环境就是别人的后花园了——随时会被盗。)
(因为数据比较大,,,,大概在150G左右。一定要找好存储位置 –datadir 后面的参数是文件存储位置 )
(其他的 后面几个参数呢,自己去看吧。https://www.cnblogs.com/tinyxiong/p/7918706.html)
./geth --rpc --rpcaddr "172.31.95.198" --syncmode "fast" --maxpeers 9999 --maxpendpeers 100 --cache 2048 --datadir "/app/chain" --rpccorsdomain "*" --rpcport "8899" --rpcapi "db,eth,net,web3,personal" --networkid 1 console
6.0.0.0.0.0.0 上面的那个命令— 加强版
(上面那条命令可以有一个和 python 一样的console控制台–但是当你的22远程关闭时这条进程也就被随即杀死了。所以我找了N多的方法只有这一条可以开启系统服务的命令—–把上面的命令包含在中间, 把控制台所有的输出写在后面的log文件内——-文件位置自定义)(每次重启服务记得重新挂载)
nohup ./geth --datadir "/app/chain" --syncmode "fast" --rpc --rpcaddr "172.31.186.212" --rpcport 8899 --rpcapi "eth,net,personal,web3,miner" --maxpeers 150 2>>/app/chain/geth.log &
ps -ef | grep geth 这条命令是检验上面命令是否正常挂载服务的命令。
kill -9 123456(杀死挂载的geth,,,数字就是你所查到的挂载id)
7。 上面的命令如果运行正常的话会出现—Welcome to the Geth JavaScript console!
然后就是漫长的节点数据同步!(100M带宽大约需要48个小时左右,也许更快)
如果以下命令返回的结果 ‘result’ 不是0的时候代表可以查到余额,节点同步完成并在持续同步中!
curl -i -X POST -H 'Content-type':'application/json' --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x4962FFC9f3b706B69744bF4BD16f7Af3eEfD125a", "latest"],"id":1}' http://172.31.22.34:8899
返回结果正常的话::::如下:
HTTP/1.1 200 OK Content-Type: application/json Date: Thu, 06 Dec 2018 07:02:59 GMT Content-Length: 52 {"jsonrpc":"2.0","id":1,"result":"0x6f983ffc99acc"}
下面分享几条 数据同步完成后 在控制台中查看和操作的命令。(创建智能合约的时候会用到下面的某些命令)
personal.listAccounts 查看用户列表
personal.newAccount("a87654321") 新增用户-------双引号内写密码。
web3.fromWei(eth.getBalance(eth.accounts[0]), "ether") 查看默认用户余额---默认用户就是第一个在节点上建立的用户。
web3.fromWei(eth.getBalance('0xc2b9201b5c372985c00988ddb287c3aafe77d663'),"ether")查看指定用户余额
web3.fromWei(web3.eth.gasPrice) 查看当前环境的gas也就是油费and矿工费
miner.start(1)开始用默认用户挖矿miner.stop() 结束挖矿 ---这两条命令知道就行,你买的服务器基本是挖不到的。
personal.unlockAccount('0xc2b9201b5c372985c00988ddb287c3aafe77d663', "ml123454321ml", 200) 解锁账号(‘账号’,‘密码’,解锁时间-单位s)-----这条命令划重点(只要涉及资金转账就得解锁账户,解锁时间尽可能地小
eth.sendTransaction({from: "0x95140bf555c71912bb6c756369d839e5be6dabce", to: "0x4962ffc9f3b706b69744bf4bd16f7af3eefd125a", value: web3.toWei(0.01, “ether”)})
转账命令–转的是eth。。。参数就不介绍了
第二章 智能合约的发布
–需要登陆网址的 必须找个window的国外服务器操作。(****必须的必****当然自己会搭建vpn的除外****)
(这一章呢,合约等信息是需要重复使用的,而且不能有任何差异的,建议编译的时候在文本文档里保存一下。利于回头寻找)
(合约代码在本章结束!)
1。 编译智能合约!
https://ethereum.github.io/browser-solidity/#optimize=false&version=soljson-v0.4.23+commit.124ca40d.js(这个网址是编译合约用的—– 在编译合约之前最好要把合约内的注释都清理一下)
Details 按钮点击之后,找到 WEB3DEPLOY,就是编译好的智能合约 abi就是abi内容 要全部复制。abi为json格式。可以找个在线格式化代码压缩为字符串。
2.在控制台内输入定义abi
var abi = (上面编译好的abi字符串,敲回车。)
3.需要解锁用户(因为这里合约用到的是默认用户(节点第一个用户))
personal.unlockAccount(‘0xc2b9201b5c372985c00988ddb287c3aafe77d663’, “ml123454321ml”, 200) ;
4. 在编辑php的编辑器内把内容编辑好,放到控制台直接敲回车就行,
以该合约为例 WEB3DEPLOY 内变量需要自己定义
var initialSupply = /* var of type uint256 here */ ; //这个是发行数量。根据下面的小数设置进行设置比如发行1000万,小数后18位。 那么久在10000000后面加18个0; var tokenName = /* var of type string here */ ;//币种名称 var decimalUnits = /* var of type uint8 here */ ;//小数后几位。比如18 var tokenSymbol = /* var of type string here */ ;//币种缩写名称 var centralMinter = /* var of type address here */ ;//代币归属人--就是把所有的币发送到那个账户里面去.(这里说一下 这个合约的内容强制发到默认账户,也就是当前节点的第一个账户里面。)
**********************
(因为合约的内容就上面是是需要定义的,下面的是不需要更改的那些我就不解释了)
5.如果你的默认账号里面有足够的金额供发币使用,会返回一个has就是正在发币的has。你可以复制这个has到 https://etherscan.io/(国外网址)去查询进度(发币的速度据你当时的油费价格而定,正常的速度大约在5min左右), 如果成功之后,你就成功了一半了。
(合约的发布速度,在于你公布合约是的油费价格,,成功与否,在于你的默认账户余额是否充足——-尽量保持账户余额的充足, 否则因为给的邮费少所产生的错误,余额是不返回的。 但是多给了会把多余部分返回到你的账户的。)
6.发币之后是需要验证合约的。https://etherscan.io/(因为长城的限制,这里就必须在境外windows服务器上面进行了),
1. 在服务器的浏览器你会发现神奇的这个网站是可以注册用户的。
2.刚发现这个网址支持中文里!!!!福利啊。点击搜索框最后面的那个语言切换,,切换到中文
3.点击输入框左边的 ‘登陆‘
4.注册一个新的账号。(不解释了)
5.登陆
6.点击 左侧’My Address‘ 下的 ’ Watch List‘
7.点击 Add New Address
8.找到’ETH Address’ 类似字样的填入你发币的默认账号;添加就行。(因为更新,可能会隔一段时间不一样 不过大致的也逃过这么一套流程)
9.点击那个账号,跳转到详情页。
10. ‘code’栏目下有个源代码验证
//以下代码是合约(代币)内容。
contract owned { address public owner; function owned() { owner = msg.sender; } modifier onlyOwner { if (msg.sender != owner) throw; _; } /* 管理者的权限可以转移 */ function transferOwnership(address newOwner) onlyOwner { owner = newOwner; } } /* 注意“contract MyToken is owned”,这类似于C++中的派生类的概念 */ contract MyToken is owned{ /* Public variables of the token */ string public standard = 'Token 0.1'; string public name; string public symbol; uint8 public decimals; uint256 public totalSupply; uint256 public sellPrice; uint256 public buyPrice; uint minBalanceForAccounts; //threshold amount /* This creates an array with all balances */ mapping(address => uint256) public balanceOf; mapping(address => bool) public frozenAccount; /* This generates a public event on the blockchain that will notify clients */ event Transfer(address indexed from, address indexed to, uint256 value); event FrozenFunds(address target, bool frozen); /* Initializes contract with initial supply tokens to the creator of the contract */ function MyToken( uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol, address centralMinter ) { if (centralMinter != 0) owner = msg.sender; balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens totalSupply = initialSupply; // Update total supply name = tokenName; // Set the name for display purposes symbol = tokenSymbol; // Set the symbol for display purposes decimals = decimalUnits; // Amount of decimals for display purposes } /* 代币转移的函数 */ function transfer(address _to, uint256 _value) { if (frozenAccount[msg.sender]) throw; if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows if (msg.sender.balance < minBalanceForAccounts) sell((minBalanceForAccounts - msg.sender.balance) / sellPrice); if (_to.balance < minBalanceForAccounts) _to.send(sell((minBalanceForAccounts - _to.balance) / sellPrice)); balanceOf[msg.sender] -= _value; // Subtract from the sender balanceOf[_to] += _value; // Add the same to the recipient Transfer(msg.sender, _to, _value); // Notify anyone listening that this transfer took place } /* 货币增发的函数 */ function mintToken(address target, uint256 mintedAmount) onlyOwner { balanceOf[target] += mintedAmount; totalSupply += mintedAmount; Transfer(0, owner, mintedAmount); Transfer(owner, target, mintedAmount); } /* 冻结账户的函数 */ function freezeAccount(address target, bool freeze) onlyOwner { frozenAccount[target] = freeze; FrozenFunds(target, freeze); } /* 设置代币买卖价格的函数 */ function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner { sellPrice = newSellPrice; buyPrice = newBuyPrice; } /* 从合约购买货币的函数 */ function buy() returns(uint amount){ amount = msg.value / buyPrice; // calculates the amount if (balanceOf[this] < amount) throw; // checks if it has enough to sell balanceOf[msg.sender] += amount; // adds the amount to buyer's balance balanceOf[this] -= amount; // subtracts amount from seller's balance Transfer(this, msg.sender, amount); // execute an event reflecting the change return amount; // ends function and returns } /* 向合约出售货币的函数 */ function sell(uint amount) returns(uint revenue){ if (balanceOf[msg.sender] < amount) throw; // checks if the sender has enough to sell balanceOf[this] += amount; // adds the amount to owner's balance balanceOf[msg.sender] -= amount; // subtracts the amount from seller's balance revenue = amount * sellPrice; // calculate the revenue msg.sender.send(revenue); // sends ether to the seller Transfer(msg.sender, this, amount); // executes an event reflecting on the change return revenue; // ends function and returns } /* 设置自动补充gas的阈值信息 */ function setMinBalance(uint minimumBalanceInFinney) onlyOwner { minBalanceForAccounts = minimumBalanceInFinney * 1 finney; } }