如何在私有链上编写,部署与以太坊私有链最大进行交互

区块链学习(2) mac智能合约部署到以太坊私有链并交互(mac版)
我的图书馆
区块链学习(2) mac智能合约部署到以太坊私有链并交互(mac版)
合约代码编写
合约代码是用的solidity语言写的。solidity语言跟java语言类似,所以会java的来写solidity,还是很方便的。这里我把和都列出来了,然后找了一个例子直接拿来用了,一个简单的乘法。有更多需求的请自行查阅文档。
新建一个文件test.sol,在文件中如下编写:
pragma solidity ^0.4.0;
contract test {
/// @notice Will multiply `a` by 7.
function multiply(uint a) returns(uint d) {
return a * 7;
合约代码的编译
编译问题搞了很久,网上有说用solc --bin test.sol,暂时还不知道生成二进制码后怎么玩。也有说将test.sol文件中代码压缩(即将换行符和空格去掉),生成一串字符串source,然后在eth环境中调用eth.complie.solidity(source),但geth从1.6版本之后就将此命令删除了,所以会报
Error: The method eth_compileSolidity does not exist/is not available
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at &anonymous&:1:112345
我现在的做法是,使用Remix在线工具编译。具体做法是:
1. 在浏览器中打开Remix工具,网址为:;
2. 点击左上角+,新生成一个文件test.sol;
3. 将之前在本地写的test.sol中的代码拷贝到此文件中,如图所示
4. 点击compile -& start to compile,下面会有一些警告,不用管它,然后点击Details按钮,拷贝json数据
json数据形式如下:
[{"constant":false,"inputs":[],"name":"getStr","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]1
此json格式的东东就是我们编译后的数据了。
部署合约代码到私有链
注意:在这一步之前,一定要创建私有链,并且假设你已经进入到Geth JS控制台了。
具体部署过程如下:
获取bin信息,即上述获取的json格式的数据
& abi = [{"constant":false,"inputs":[],"name":"getStr","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
constant: false,
inputs: [],
name: "getStr",
outputs: [{
type: "string"
payable: false,
stateMutability: "nonpayable",
type: "function"
constant: false,
inputs: [{
name: "a",
type: "uint256"
name: "multiply",
outputs: [{
name: "d",
type: "uint256"
payable: false,
stateMutability: "nonpayable",
type: "function"
//创建合约。
& multiplyContract = eth.contract(abi)
constant: false,
inputs: [],
name: "getStr",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
accounts: ["0x099dc9e414a9faf0e478204ace0f67", "0xc13b5f0f22c1f05a1b96d"],
blockNumber: 58,
coinbase: "0x099dc9e414a9faf0e478204ace0f67",
compile: {
lll: function(),
serpent: function(),
solidity: function()
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: ,
hashrate: 0,
mining: false,
pendingTransactions: [],
protocolVersion: "0x3f",
syncing: false,
call: function(),
contract: function(abi),
estimateGas: function(),
filter: function(options, callback, filterCreationErrorCallback),
getAccounts: function(callback),
getBalance: function(),
getBlock: function(),
getBlockNumber: function(callback),
getBlockTransactionCount: function(),
getBlockUncleCount: function(),
getCode: function(),
getCoinbase: function(callback),
getCompilers: function(),
getGasPrice: function(callback),
getHashrate: function(callback),
getMining: function(callback),
getPendingTransactions: function(callback),
getProtocolVersion: function(callback),
getRawTransaction: function(),
getRawTransactionFromBlock: function(),
getStorageAt: function(),
getSyncing: function(callback),
getTransaction: function(),
getTransactionCount: function(),
getTransactionFromBlock: function(),
getTransactionReceipt: function(),
getUncle: function(),
getWork: function(),
iban: function(iban),
icapNamereg: function(),
isSyncing: function(callback),
namereg: function(),
resend: function(),
sendIBANTransaction: function(),
sendRawTransaction: function(),
sendTransaction: function(),
sign: function(),
signTransaction: function(),
submitTransaction: function(),
submitWork: function()
at: function(address, callback),
getData: function(),
new: function()
//解锁账户
& personal.unlockAccount(eth.accounts[0])
Unlock account 0x099dc9e414a9faf0e478204ace0f67
Passphrase:
//部署合约。data为上述编译得到的数据,在下面截图可以看到
& multiply = multiplyContract.new({from:eth.coinbase,data:"0x01ac63ffffffffc9e4ed63c0df575bbb565b5ba100dbb0f35b565b7feba7ae32f8a7d822f631e49ec067bd3ca718ea68acf864b7bff16afdfd"})
INFO [03-09|17:06:17] Submitted contract creation
fullhash=0x2caf080fff22adde98e0a4b711edde8cf15a592744 contract=0x800e7b3e2DcC1d87b
constant: false,
inputs: [],
name: "getStr",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
address: undefined,
transactionHash: "0x2caf080fff22adde98e0a4b711edde8cf15a592744"
//我们知道部署合约的过程实际也是由创建合约的账户发送的一笔交易(即eth.coinbase账户)。需要挖矿进行确认。
& miner.start();admin.sleepBlocks(1);miner.stop();
true123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
至此合约已经存在于区块链中,可以查看区块信息获取合约的地址和交易hash。
与合约交互
//获取合约对象
& MyContract = eth.contract(abi)
constant: false,
inputs: [],
name: "getStr",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
accounts: ["0x099dc9e414a9faf0e478204ace0f67", "0xc13b5f0f22c1f05a1b96d"],
blockNumber: 60,
coinbase: "0x099dc9e414a9faf0e478204ace0f67",
compile: {
lll: function(),
serpent: function(),
solidity: function()
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: ,
hashrate: 0,
mining: false,
pendingTransactions: [],
protocolVersion: "0x3f",
syncing: false,
call: function(),
contract: function(abi),
estimateGas: function(),
filter: function(options, callback, filterCreationErrorCallback),
getAccounts: function(callback),
getBalance: function(),
getBlock: function(),
getBlockNumber: function(callback),
getBlockTransactionCount: function(),
getBlockUncleCount: function(),
getCode: function(),
getCoinbase: function(callback),
getCompilers: function(),
getGasPrice: function(callback),
getHashrate: function(callback),
getMining: function(callback),
getPendingTransactions: function(callback),
getProtocolVersion: function(callback),
getRawTransaction: function(),
getRawTransactionFromBlock: function(),
getStorageAt: function(),
getSyncing: function(callback),
getTransaction: function(),
getTransactionCount: function(),
getTransactionFromBlock: function(),
getTransactionReceipt: function(),
getUncle: function(),
getWork: function(),
iban: function(iban),
icapNamereg: function(),
isSyncing: function(callback),
namereg: function(),
resend: function(),
sendIBANTransaction: function(),
sendRawTransaction: function(),
sendTransaction: function(),
sign: function(),
signTransaction: function(),
submitTransaction: function(),
submitWork: function()
at: function(address, callback),
getData: function(),
new: function()
//实例化合约
& myContract = MyContract.at(multiply.address)
constant: false,
inputs: [],
name: "getStr",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
payable: false,
stateMutability: "nonpayable",
type: "function"
address: undefined,
transactionHash: null,
allEvents: function(),
getStr: function(),
multiply: function()
//调用合约
& myContract.multiply.call(5)
喜欢该文的人也喜欢开发(一)搭建基于以太坊的私有链环境
通过本文所述方法和项目中的脚本,我们可以快速的搭建好自己的私有链进行区块链开发,本文基于以太坊技术进行搭建,分两个部分,一个是Ubuntu下搭建方法,另一个是Windwos下搭建方法,关于以太坊相关的基础知识,可以看我原先发表的一些文章,地址如下:
Ubuntu下安装Geth客户端
之所以采用Ubuntu,是因为以太坊的官方对Ubuntu支持的很好,是在各个系统中安装最简单。
Geth官方安装指南:
https://github.com/ethereum/-ethereum/wiki/Building-Ethereum
进入ubuntu命令行,执行如下命令
sudo apt-get update
sudo apt-get installsoftware-properties-common
sudo add-apt-repository -yppa:ethereum/ethereum
sudo add-apt-repository -yppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install ethereum
系统联网执行后,即完成了安装以太坊客户端,其中包括geth,bootnode, evm, disasm, rlpdump,ethtest
此时如果输入Geth命令,会出现启动以太坊启动的画面
安装Windows下Geth客户端
Windows必须64位系统,从官方网站下载编译好的win64客户端,解压缩即可运行,下载地址如下:
https://github.com/ethereum/go-ethereum/releases/
下载后,只有一个Geth.exe的文件。
安装图像化客户端Mist,依然是从官方地址下载编译好的客户端即可,下载地址:
https://github.com/ethereum/mist/releases/
下载解压缩后,Ethereum-Wallet即为以太坊图形化界面。
准备创世块文件
配置自己的创世块是为了区分公有链,同一个网络中,创世块必须是一样的,否则无法联通,此方法在windows和Ubuntu下通用。
新建文件piccgenesis.json,输入如下内容并保存
"nonce":"0x0042",
"mixhash":"0x0000",
"difficulty": "0x4000",
"alloc": {},
"coinbase":"0x0000",
"timestamp": "0x00",
"parentHash":"0x0000",
"extraData": "PICC GenesisBlock",
"gasLimit":"0xffffffff"
解释一下各个参数的作用:
与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。.
nonce就是一个64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。
difficulty
设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度
用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。
矿工的账号,随便填
设置创世块的时间戳
parentHash
上一个区块的hash值,因为是创世块,所以这个值是0
附加信息,随便填,可以填你的个性信息
该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。
启动私有链节点
启动Geth即可以启动以太坊的区块链,为了构建私有链 ,需要在Geth启动时加入一些参数,Geth参数含义如下:
区块链的标示,随便填写,用于标示目前网络的名字
指定创世块文件的位置,并创建初始块
设置当前区块链网络数据存放的位置
网络监听端口
启动rpc通信,可以进行智能合约的部署和调试
设置允许连接的rpc的客户端,一般为db,eth,net,web3
设置当前区块链的网络ID,用于区分不同的网络,是一个数字
启动命令行模式,可以在Geth中执行命令
在Ubuntu启动区块链节点
在Ubuntu下,首先切换到打算运行的目录,目录下应该有配置好的piccgenesis.json文件,执行如下命令
basepath=$(cd `dirname $0`; pwd)
获取当前的目录
--datadir "$basepath/chain" init piccgenesis.json
创建数据存放地址并初始化创世块
geth --identity"PICCetherum"
--rpccorsdomain "*" --datadir "$basepath/chain" --port "30303"
--rpcapi "db,eth,net,web3"--networkid 95518 console
启动后界面如下,光标停留在最后的命令行上,可以执行以太坊命令。
I:43.680087 ethdb/database.go:82]Alloted 128MB cache and 1024 file handles to /home/lihe/桌面/chain/chaindata
I:43.726008ethdb/database.go:169] closed db:/home/lihe/桌面/chain/chaindata
I:43.728913 ethdb/database.go:82]Alloted 128MB cache and 1024 file handles to /home/lihe/桌面/chain/chaindata
I:43.908795 ethdb/database.go:82]Alloted 16MB cache and 16 file handles to /home/lihe/桌面/chain/dapp
I:43.969506 core/genesis.go:92]Genesis block already in chain. Writing canonical number
I:43.980337 eth/backend.go:274]Successfully wrote custom genesis block:6e92f8b23bcdfdf34dc813cfaf1d84b71beacd63a2df10fe23a660
I:43.980618 eth/backend.go:184]Protocol Versions: [63 62], Network Id: 95518
I:43.981567core/blockchain.go:204] Last header: #81 […] TD=
I:43.981645core/blockchain.go:205] Last block: #81 […] TD=
I:43.981677core/blockchain.go:206] Fast block: #81 […] TD=
I:43.p/server.go:313]Starting Server
I:45.p/discover/udp.go:217] Listening,enode://c61c27f91caaf499be813e29c9f986e2eac62d47e02b13a8e51776c1caeaed26ceda7ac48a83a60113ff@[::]:30303
I:45.835853 node/node.go:366]HTTP endpoint opened: http://localhost:8545
I:45.p/server.go:556]Listening on [::]:30303
I:45.849731 node/node.go:296] IPCendpoint opened: /home/lihe/桌面/chain/geth.ipc
Welcome to the Geth
instance:Geth/v1.5.0-unstable/linux/go1.5.1/PICCetherum
coinbase:0xb2b974b07ef0b52e07cde1
at block: 81 (Tue, 05 Jul :25CST)
datadir: /home/lihe/桌面/chain
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
可以看到Listening on [::]:30303和Welcome to the Geth JavaScript console!的提示,说明已经启动成功
注意:如果想将Ubuntu作为永久区块链节点使用,当使用nohup命令时,Geth启动参数console必须去掉,否则Geth会自动停止。
在windows启动区块链节点
进入Windows下Geth的目录 ,放置配置好的piccgenesis.json文件,执行如下命令:
--datadir "%cd%\chain" init piccgenesis.json
创建数据存放地址并初始化创世块
geth--identity "PICCetherum" --rpc--rpccorsdomain "*" --datadir "%cd%\chain" --port"30303"
--rpcapi"db,eth,net,web3" --networkid 95518 console
当看到Listening on [::]:30303和Welcome to the Geth JavaScript console!的提示,说明已经启动成功
使用节点创建账号
启动节点成功后,会进入Geth的命令行模式,输入如下命令
personal.newAccount()
系统会提示你输入账号密码,并确认,最后会显示一个新生成的账号。
启动Windows下私有链图形节点
首先按上面的步骤启动Geth并创建了账号,然后解压缩Ethereum-Wallet,运行Ethereum-Wallet.exe,即启动成功,如果区块链正常的话,会在右上角显示“PRIVATE-NET”,点击“LAUNCH APPLICATION”进入图形界面即可。
连接其他节点
首先要知道自己的节点信息,在Geth命令行界面下输入命令,注意大小写
admin.nodeInfo
系统会显示
enode:"enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eeceefcad17c161aa93d61bdbfb28ed152c143c7eb501db58bcb62d742@0.0.0.0:30303“
enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eeceefcad17c161aa93d61bdbfb28ed152c143c7eb501db58bcb62d742@0.0.0.0:30303
就是自己节点的信息,注意要把“0.0.0.0“换成你自己的IP。将这个信息发送给其他节点,在其他节点的命令行中输入:
admin.addPeer(‘enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eeceefcad17c161aa93d61bdbfb28ed152c143c7eb501db58bcb62d742@192.168.1.101:30303’)
如果添加成功,输入admin.peers会显示出新添加的节点。
使用节点进行挖矿
在Geth命令行界面下,输入miner.start()即启动挖矿,挖矿后,会不停刷屏,输入miner.stop()即停止,不用管刷屏导致的命令不全,命令会正常执行。
到这一步,已经组建一个私有链的网络,可以像其他区块链一样不停的扩充这个网络,下一篇文章,我会介绍如何在私有链上编写、调试和部署智能合约。
参考文章:
以太坊私有链创建及智能合约的部署和交互
部署本机私有链
区块链说白了就是一个个块链接起来的一个链表结果,所以要在本机生成一个自己的私有链首先要做的就是自己先创建一个块作为第一个将要生成的区块链的第一个区块(区块链叫做创世块),所以先生成一个...
通过以太坊搭建私有链(来发行个自己的加密货币吧)
安装go-ethereum
地址:https://github.com/ethereum/go-ethereum
brew tap ethereum/ethereum
brew install...
【区块链】Android通过Geth RPC接口实现接入以太坊私有链
Android通过Geth RPC接口实现接入以太坊私有链环境:mac os & android studio一、启动私有链搭建方法见 here启动并设定RPC端口:geth --identity &...
go-ethereum 私有链搭建指南
以太坊客户端
以太坊客户端用于接入以太坊网络,进行账户管理、交易、挖矿、智能合约相关的操作。目前有多种语言实现的客户端,常用的有 ...
摸索以太坊区块链技术几个月了。最近打算逐步的把自己学到的东西和大家分享一下。
在阅读本文之前,希望大家能对区块链的概念能有所了解。这样操作过程中的环节理解更深入。下面开始进入准备。
因为本次是wi...
原文地址:https://www.cnblogs.com/Evsward/p/eth-rpc.html上一篇文章介绍了以太坊的基础知识,我们了解了web3.js的调用方式是通过以太坊RPC技术,本篇文...
最近在研究区块链。打算先搭建一个测试环境开始运行。这里记录整个搭建过程,供后来人参考。 整体上,分为三个步骤,安装相关软件,初始化系统,建立集群,以及最后一步,挖矿。 我们采用的是以太坊,相对其他区块...
1.下载Geth.exe并安装官网地址: https://ethereum.github.io/go-ethereum/downloads/ (另附百度网盘地址:链接: https://pan.bai...
没有更多推荐了,!!!!以太坊私有链创建及智能合约的部署和交互
我的图书馆
!!!!以太坊私有链创建及智能合约的部署和交互
部署本机私有链
区块链说白了就是一个个块链接起来的一个链表结果,所以要在本机生成一个自己的私有链首先要做的就是自己先创建一个块作为第一个将要生成的区块链的第一个区块(区块链叫做创世块),所以先生成一个json文件genesis.json,内容为创世块的内容(也是每个区块的包含的基本内容):
&&&&&&&& "nonce":"0x0042",
&&&&&&&& "difficulty":"0x020000",
&&&&&&&& "mixhash":"0x0000",
&&&&&&&& "coinbase":"0x0000",
&&&&&&&& "timestamp":"0x00",
&&&&&&&& "parentHash":"0x0000",
&&&&&&&& "extraData":"0x11bbe8db4e347b4e8c937c1ced33adb3db69cbdb7a38e1e50b1b82fa",
&&&&&&&& "gasLimit":"0x4c4b40",
&&&&&&&& "alloc":{}
mixhash:与nonce配合用于挖矿,由上一个区块的一部分生成的hash。
nonce: nonce就是一个64位随机数,用于挖矿。
difficulty: 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度
alloc: 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。
coinbase: 矿工的账号,随便填
timestamp: 设置创世块的时间戳
parentHash: 上一个区块的hash值,因为是创世块,所以这个值是0
extraData: 附加信息,随便填,可以填你的个性信息
gasLimit: 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以可以填最大。
创世块我们就这样创建好了。然后创建一个data文件夹用来存储区块数据和账号信息。本机创建私有链要确保安装以太坊的客户端。
这一切准备工作完成后我们就可以开始初始化创世块及启动我们自己的私有链。
初始化创世块
创建脚本start_init.bat:
geth --identity "超神链"--datadir "%cd%\data" init genesis.json
说明:identity 区块标示,名称
init 表示初始化区块,后面就是创世块的配置
datadir 表示数据存放的位置
创建私有链启动脚本startup.dat:
geth --identity "超神链"--datadir data --networkid 123456 --rpc --rpcaddr="0.0.0.0"--rpccorsdomain "*" --port "30303" --rpcapi"db,eth,net,web3" --nodiscover console
说明:networkid 表示启动私有链的网络ID,已其他节点相连是网络IP要一致。
&&&&&&&& & rpc 开启rpc通信,可进行智能合约部署和调用。
&&&&&&&& & rpcaddr 区块链提供了对外RPC接口,默认是localhost,这个设置为可以IP访问。
&&&&&&&& & Rpccorsdomain 表示任何链接都可以连接到此节点。
&&&&&&&& & Port 该节点对外开放端口。
&&&&&&&& &&Rpcapi 可以连接的客户端。
&&&&&&&& & console:启动命令行模式,可以在Geth中执行命令。
其他的一些启动配置:
&&&&&&&& & Bootnodes:设置要连接的节点,后面跟其他节点的信息。如:--bootnodesenode://bfdb56ea443efa5b255a5bddb080ad2d34b6630deffeee60e2e6a3b9c305ae780b@10.132.97.29:30303console
&&&&&&&& & 所有前期准备做好以后分布启动初始化及启动脚本。启动成功后会进入ethereum的javascript控制台。如下:
创建新账号
&&&&&& personal.newAccount()
或者 personal.newAccount("123456")
查看节点信息
&&&&&& admin.nodeInfo
开始挖矿 miner.start(1)
停止挖矿 miner.stop()
查看当前矿工账号
&&&&&& eth.coinbase默认为第一个账户
修改矿工账号
&&&&&& miner.setEtherbase(eth.accounts[1])
查看账户信息
&&&&&& eth.accounts[0]
查看账户余额
&&&&&& eth.getBalance(eth.accounts[0])
或者 web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
&&&&&& personal.unlockAccount(eth.accounts[0])
使用账户资金前都需要先解锁账号
转账eth.sendTransaction({from:eth.accounts[0],to:"0x587e57afe970ff445d9",value:web3.toWei(3,"ether")})
使用 txpool.status
可以看到交易状态
查看区块数据
&&&&&& eth.blockNumber
&&&&& eth.getTransaction("0x0c59fcbe9ef59bd7146edc8ff5ec37fea6710adcab825")
&&&&&& eth.getBlock(1)通过区块号查看区块
部署智能合约
合约部署需要挖矿才能成功,我们新开一个窗口用与挖矿,新开一个控制台,输入命令:geth attach 连接到控制台,执行miner.start(1),开始挖矿。
这里在网上找了个代币的只能合约,可以进行充值、转账和查询,issue 函数可以向充值以太到合约账户,transfer 函数可以向其他账号发送token,getBalance 函数可以获取某个账号的token余额,代码如下:
pragma solidity ^0.4.2;
contract Token {
&&&&&&&& &&&
&&&&&&&& &&& mapping (address =& uint)
&&&&&&&& &&& event Issue(address account, uint amount);
&&&&&&&& &&& event Transfer(address from, address to,uint amount);
&&&&&&&& &&& function Token() {
&&&&&&&& &&&&&&& issuer = msg.
&&&&&&&& &&& }
&&&&&&&& &&& function issue(address account, uintamount) {
&&&&&&&& &&&&&&& if (msg.sender != issuer)
&&&&&&&& &&&&&&& balances[account] +=
&&&&&&&& &&& }
&&&&&&&& &&& function transfer(address to, uint amount){
&&&&&&&& &&&&&&& if (balances[msg.sender] & amount)
&&&&&&&& &&&&&&& balances[msg.sender] -=
&&&&&&&& &&&&&&& balances[to] +=
&&&&&&&& &&&&&&& Transfer(msg.sender, to, amount);
&&&&&&&& &&& }
&&&&&&&& &&& function getBalance(address account)constant returns (uint) {
&&&&&&&& &&&&&&& return balances[account];
&&&&&&&& &&& }
&&&&&&&& }
智能合约的部署需要编译,这里用在线编译:
修改编译好的gas和对象名称:
varbrowser_untitled_sol_tokenContract =web3.eth.contract([{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"name":"issue","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Transfer","type":"event"}]);
var token =browser_untitled_sol_tokenContract.new(
&&&& from: web3.eth.accounts[0],
&&&& data:'0x0b000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5bf3ffffffffb063a9059cbb63f8b2cb4f5bbb803573ffffffffffffffffffffffffffffffffffffffffb005bb803573ffffffffffffffffffffffffffffffffffffffff5b005bb803573ffffffffffffffffffffffffffffffffffffffff5c565bffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373fffffffffffffffffffffffffffffffffffffffffd5b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff80fd5b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1673fffffffffffffffffffffffffffffffffffffffffddf252ad1be2c89b69c2b068fc378daa952ba7f163c4adf523b3ef808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffffa15b3ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff5baaafe007aac892e6dba9d032f540a11ff427d26ccbea2f0029',
&&&& gas: '4300000'
&& }, function (e, contract){
&&& console.log(e, contract);
&&& if (typeof contract.address !=='undefined') {
&&&&&&&& console.log('Contract mined! address:' + contract.address + ' transactionHash: ' + contract.transactionHash);
将编译好的代码拷贝直接放到控制台即可。如果出现Error: account is locked undefined错误的话, 则使用personal.unlockAccount(eth.accounts[0],'password')命令将用户解锁。Password为你创建账号的密码。一段时间后geth窗口就会出现Contract mined! address..., 表明合约代码发布成功。
智能合约的调用
合约部署成功后,在控制台可以直接调用。
控制输入token,放回该合约的信息:
这里重点就是address表示的是合约的地址,你会发现这个和账号的信息结果一样,其实你也可以把这个合约地址看做是一个账号地址,后面我们外部调用到的就是这个合约地址。
控制台调用
personal.unlockAccount(eth.accounts[0])
token.issue.sendTransaction(eth.accounts[0],100, {from: eth.accounts[0]});
miner.start(1)
miner.stop()
发送 token
token.transfer(eth.accounts[1], 30, {from:eth.accounts[0]})
miner.start(1)
miner.stop()
token.getBalance()
控制台调用就不多说,和java对象调用一样,直接调用即可。
外部接口与智能合约交互
以太坊对外提供的有很多接口JSON RPC接口,web3接口,这里我们用JSON RPC接口。
合约交互的原理
合约的交互都是一次交易,而我们要做的就是把要调用的方法和参数按照api规定的以参数的形式向区块请求一次交易,ethereum接收到我们的请求后通过解析传递的参数来执行相关的合约代码。
RPC接口给我们提供了俩个方法:eth_sendTransaction和eth_call。
eth_sendTransaction
Createsnew message call transaction or a contract creation, if the data field containscode.
Parameters
Object&- The transaction objectfrom:&DATA, 20 Bytes - The address the transaction is send from.to:&DATA, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.gas:&QUANTITY&- (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.gasPrice:&QUANTITY&- (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gasvalue:&QUANTITY&- (optional) Integer of the value send with this transactiondata:&DATA&- The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see& nonce:&QUANTITY&- (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.可以看到,如果我们创建的为合约时,我们只需要from,to(文档上写的是可选的,但是实际操作中没有to为null的话合约不能正常执行,建议还是加上,这个值就是前面我们部署合约后生成的合约address),data。Data的属性的值具体可以看Contract ABI。这里大概说下:
Data的值相对来说不是固定的,具体怎么生成与合约的参数类型,参数数量都有关联。这里我们以部署的token合约的三个方法为例:
充值issue (address account, uintamount)
这个方法有俩个参数,address充值账号,uint充值数量。
根据Contract ABI,data值应该为方法名的sha3的前8个字节+参数的64字节,不够前面补充为0。
这里方法名并不是issue (address account, uint amount)而是issue(address,uint256)的sha3值。
我们往第一个账号充值10,这里的数据不是以太币,而是我们自己创建的代币。
将10转换为16进制为
那么data的数据为:
0xfdf57ece821fdf7eb000a
那么最后我们调用eth_sendTransaction方法传递参数JSON对象为:
&&& from:0xfdf57ece821fdf7eb,
to:0x7fe0cef1918b9abb3a3,
data: 0xfdf57ece821fdf7eb000a
返回:此交易的hash值,此时该交易还没有执行,只是创建,还需要矿工通过挖矿才能完成。
调用接口方法:
JsonRpcHttpClient client = newJsonRpcHttpClient(new URL(“http://127.0.0.1:8545”));
Object result = client.invoke(methodName,params, Object.class);
通过控制台查看第一个账号已有代币:
执行调用接口代码。返回交易hash值:
0xc3fea680faa5f9f8d24bc095
此时控制台输入:
说明此交易等待矿工处理。
查看此时交易状态:
发现这个交易中blockNumber还是null,因为此次交易还处于挂起状态,需要生成一个新的区块才能行。
可以看到此次等待交易为1.
现在开启挖矿。生成新的区块后我们停止挖矿,再来看看第一个账号此时的代币金额:
代币增加了10个。
我们再来看下此时的交易状态:
来看下此次的交易详情:
区块数据已经出来了,至此此次充值成功。
交易和充值一样,需要注意的是代币转出账号为from属性的值,代币转入账号为data属性里的值,to对应的是合约地址。
Executes anew message call immediately without creating a transaction on the block chain.
Parameters
Object&- The transaction call objectfrom:&DATA, 20 Bytes - (optional) The address the transaction is sent from.to:&DATA, 20 Bytes - The address the transaction is directed to.gas:&QUANTITY&- (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.gasPrice:&QUANTITY&- (optional) Integer of the gasPrice used for each paid gasvalue:&QUANTITY&- (optional) Integer of the value send with this transactiondata:&DATA&- (optional) Hash of the method signature and encoded parameters. For details seeQUANTITY|TAG&- integer block number, or the string&"latest",&"earliest"&or&"pending", see the&这个方法返回一条信息给我们,相当于数据库的查询功能,参数也是三个,from,to,data,数据格式都是一样的。
查询getBalance(address account)
查询方法hash码:
查询我们上一步充值的账号,那么传递的参数data为:
0xf8b2cb4ffdf57ece821fdf7eb
eth_call方法最后参数为:
&&&&&& from: 0xfdf57ece821fdf7eb,
to:0x7fe0cef1918b9abb3a3,
data:0xf8b2cb4ffdf57ece821fdf7eb
注意,这个方法需要俩参数,除了一个JSONobject外,还有一个字符串参数,这俩可以为“”或者"latest",&"earliest"&or&"pending"
调用接口返回一个16进制字符串:
0x0071就是该账号的代币数量,转换为十进制为:113,与控制查询一致。
这就是一个智能合约的交互过程。是不是很简单啊。
喜欢该文的人也喜欢}

我要回帖

更多关于 搭建以太坊私有链 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信