以太坊搭建联盟链详细教程

虫洞社区签约作者介绍

风逝 区块链 云旗天下

安装以太坊geth客户端

需要先安装go环境
安装教程

下载以太坊源码
github.com/ethereum/go-ethereum

进入 go-ethereum 目录

cd go-ethereum
make geth

然后执行make all, 顺便安装一下其他一些命令。

创建组织

在桌面创建两个文件夹,a,b 两个文件夹,代表两个组织
在两个文件夹内分别创建两个文件,genesis.json
文件内容

{
    "config": {
          "chainId": 15,
          "homesteadBlock": 0,
          "eip155Block": 0,
          "eip158Block": 0
      },
      "coinbase" : "0x0000000000000000000000000000000000000000",
      "difficulty" : "0x40000",
      "extraData" : "",
      "gasLimit" : "0xffffffff",
      "nonce" : "0x0000000000000042",
      "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
      "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
      "timestamp" : "0x00",
      "alloc": { }
}

创建创世区块

进入a文件夹,执行命令
$ geth --datadir ./data-init1/ init genesis.json
如果不在a 文件夹内,genesis.json 指定其相应的路径也可.
data-init1 目录专门用来存放节点数据,执行完会发现在该目录多出两个目录,一个为geth,一个为keystore,其中geth里面存放数据相关信息,keystore 里面存放加密过的的私钥文件,执行完后打印日志如下:

INFO [09-06|18:01:44.713] Maximum peer count                       ETH=25 LES=0 total=25
INFO [09-06|18:01:44.726] Allocated cache and file handles         database=/Users/qianjianeng/Desktop/a/data-init1/geth/chaindata cache=16 handles=16
INFO [09-06|18:01:44.732] Writing custom genesis block
INFO [09-06|18:01:44.732] Persisted trie from memory database      nodes=0 size=0.00B time=187.096μs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-06|18:01:44.733] Successfully wrote genesis state         database=chaindata                                              hash=a0e580…a5e82e
INFO [09-06|18:01:44.733] Allocated cache and file handles         database=/Users/qianjianeng/Desktop/a/data-init1/geth/lightchaindata cache=16 handles=16
INFO [09-06|18:01:44.736] Writing custom genesis block
INFO [09-06|18:01:44.736] Persisted trie from memory database      nodes=0 size=0.00B time=2.156μs   gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-06|18:01:44.737] Successfully wrote genesis state         database=lightchaindata                                              hash=a0e580…a5e82e

进入b 目录,执行相同命令
$ geth --datadir ./data-init2/ init genesis.json

启动控制台

启动 a 组织
进入到 a 目录
$ geth --datadir ./data-init1/ --networkid 22 --nodiscover console

networkid : 1-4系统内部使用 大于5即可
nodiscover: 此参数确保geth不去寻找peers节点,主要是为了控制联盟链接入的节点.
这里我们需要注意的是在启动第一个节点时并没有指定port参数,因此此处采用了默认的port,
也就是30303。以下为执行时打印的日志,并进入控制台。通过日志我们也可以发现端口为
30303。

以下是部分日志

INFO [09-06|18:16:44.901] Regenerated local transaction journal    transactions=0 accounts=0
INFO [09-06|18:16:44.903] Starting P2P networking
INFO [09-06|18:16:44.906] RLPx listener up                         self="enode://251a655c56c514f5c4f81f2d08916622c0fff5f0b906ee82be0d976b255a7987c[email protected][::]:30303?discport=0"
INFO [09-06|18:16:44.911] IPC endpoint opened                      url=/Users/qianjianeng/Desktop/a/data-init1/geth.ipc
INFO [09-06|18:16:44.984] Mapped network port                      proto=tcp extport=30303 intport=30303 interface=NAT-PMP(192.168.31.1)
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.12-stable/darwin-amd64/go1.10.3
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

如果出现 Welcome to the Geth JavaScript console!, 则说明网络启动成功

新开一个终端,进入b目录,启动 b 组织
geth --datadir ./data-init2/ --port 30306 --networkid 22 --nodiscover console
注意,同一台电脑,a 组织已经占用30303端口,所以 b 需要换一个端口

到这里,两个组织网络都已经启动成功

###geth网络启动参数介绍
--nodiscover
使用此选项可确保未手动添加您的人员无法发现您的节点。否则,如果您的节点具有相同的创世纪文件和网络ID,则可能无意中将您的节点添加到陌生人的区块链中。
--maxpeers 0
如果您不希望任何其他人连接到您的测试链,请使用maxpeers 0。或者,如果您确切知道要连接到节点的对等端数,则可以调整此数字。
--rpc
这将在您的节点上启用RPC接口。这通常在Geth中默认启用。
--rpcapi "db,eth,net,web3"
这决定了允许通过RPC访问哪些API。默认情况下,Geth通过RPC启用web3接口。
重要提示:请注意,通过RPC / IPC接口提供API将使每个人都可以访问可以访问此接口的API(例如dapp)。请注意您启用的API。默认情况下,geth通过IPC接口启用所有API,并通过RPC接口启用db,eth,net和web3 API。
--rpcport "8080"
将8000更改为网络上打开的任何端口。geth的默认值是8080。
--rpccorsdomain "http://chriseth.github.io/browser-solidity/"
这决定了哪些URL可以连接到您的节点以执行RPC客户端任务。要非常小心,并键入一个特定的URL而不是通配符(*),它允许任何URL连接到您的RP C实例。
--datadir "/home/TestChain1"
这是您的私人链数据将存储在的数据目录中(在nubits。下选择一个与您的公共以太坊链文件夹分开的位置)。
--port "30303"
这是“网络侦听端口”,您将使用它手动连接其他对等端。
--identity "TestnetMainNode"
这将为您的节点设置一个标识,以便在对等列表中更容易识别它。以下是这些身份如何在网络上显示的示例。

控制台操作

进入以太坊 Javascript Console 后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。

常用命令有:

  • personal.newAccount():创建账户;
  • personal.unlockAccount():解锁账户;
  • eth.accounts:枚举系统中的账户;
  • eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的聪,1 ether = 10^18 Wei);
  • eth.blockNumber:列出区块总数;
  • eth.getTransaction():获取交易;
  • eth.getBlock():获取区块;
  • miner.start():开始挖矿;
  • miner.stop():停止挖矿;
  • eth.coinbase:挖矿奖励的账户
  • web3.fromWei():Wei 换算成以太币;
  • web3.toWei():以太币换算成 Wei;
  • txpool.status:交易池中的状态;
  • admin.addPeer():连接到其他节点;

????????添加coinbase???????? 账户

在a节点上创建一个账户
查看a节点上所有账户

> personal.listAccounts
[]

当前为空
创建一个账户,密码是123456

> personal.newAccount("123456")
"0x0aab8ad7444c1fc908707a063297520cb10414e8"

再次查看,已经有了一个账户

> personal.listAccounts
["0x0aab8ad7444c1fc908707a063297520cb10414e8"]

在b节点也创建一个账户

> personal.newAccount("123456")
"0x406133cb63002afa6cbc43a388e8eeb4c479dfaa"

在a节点查看coinbase账户
coinbase 即节点挖矿奖励所在的账户

> eth.coinbase
INFO [09-06|18:50:56.130] Etherbase automatically configured       address=0x0AAB8Ad7444C1FC908707A063297520Cb10414E8
"0x0aab8ad7444c1fc908707a063297520cb10414e8"

coinbase账户 默认就是节点里面的第一个账户,现在每个节点都只有一个账户,都分别为coinbase账户。

修改coinbase 账户
在a节点再创建一个账户

> personal.newAccount("123456")
"0xb99db142c26690d98dc3ea1c1f10e114603c0ec0"

把a节点的coinbase账户修改为第二个账户

> miner.setEtherbase("0xb99db142c26690d98dc3ea1c1f10e114603c0ec0")
true

再次查看coinbase

> eth.coinbase
"0xb99db142c26690d98dc3ea1c1f10e114603c0ec0"

更改成功

查看节点所有的账户详情

> personal.listWallets
[{
    accounts: [{
        address: "0x0aab8ad7444c1fc908707a063297520cb10414e8",
        url: "keystore:///Users/qianjianeng/Desktop/a/data-init1/keystore/UTC--2018-09-06×××0-46-59.613429718Z--0aab8ad7444c1fc908707a063297520cb10414e8"
    }],
    status: "Locked",
    url: "keystore:///Users/qianjianeng/Desktop/a/data-init1/keystore/UTC--2018-09-06×××0-46-59.613429718Z--0aab8ad7444c1fc908707a063297520cb10414e8"
}, {
    accounts: [{
        address: "0xb99db142c26690d98dc3ea1c1f10e114603c0ec0",
        url: "keystore:///Users/qianjianeng/Desktop/a/data-init1/keystore/UTC--2018-09-06×××0-55-08.643545883Z--b99db142c26690d98dc3ea1c1f10e114603c0ec0"
    }],
    status: "Locked",
    url: "keystore:///Users/qianjianeng/Desktop/a/data-init1/keystore/UTC--2018-09-06×××0-55-08.643545883Z--b99db142c26690d98dc3ea1c1f10e114603c0ec0"
}]

联盟链互通

上面分别是在两个节点上进行的操作,下面我们需要把两个节点之间建立起链接。首先,我们执 行以下命令查看以下节点的peers的情况。

> admin.peers []

发现节点并没有链接上任何其他节点,这也是我们的nodiscover参数发挥了效果。下面就通过分享enode地址的方式来让两个节点建立链接。

查看a节点信息

> admin.nodeInfo.enode
"enode://251a655c56c514f5c4f81f2d08916622c0fff5f0b906ee82be0d976b255a7987c[email protected][::]:30303?discport=0"

通过上面命令,我们获得了节点a的encode信息。这是geth用来连接到不同节点的enode信息,

在这些不同的节点它们能够分享交易和成功挖掘信息。
查看b节点信息

> admin.nodeInfo.enode
"enode://a16a449053ef07d7088527b46951a6439ddcacf88d4f28dc3862141dd64f5ddba[email protected][::]:30306?discport=0"

然后在a节点添加b,
a节点执行命令

> admin.addPeer("enode://a16a449053ef07d7088527b46951a6439ddcacf88d4f28dc3862141dd64f5ddba[email protected][::]:30306?discport=0")

在a节点添加b即可,无需在b节点添加a

返回true即为添加成功
再次执行命令admin.peers验证

> admin.peers
[{
    caps: ["eth/63"],
    id: "ec9aa0351cbe060366410a9c7403c4d1b76de704127a8c58dd3ad5c21e199c4bc75ab567c1ffba33bb983baefd954f9f647d4e0fb1043613fb43b18dd60824be",
    name: "Geth/v1.8.12-stable/darwin-amd64/go1.10.3",
    network: {
      inbound: false,
      localAddress: "[::1]:64810",
      remoteAddress: "[::1]:30306",
      static: true,
      trusted: false
    },
    protocols: {
      eth: {
        difficulty: 262144,
        head: "0xa0e580c6769ac3dd80894b2a256164a76b796839d2eb7f799ef6b9850ea5e82e",
        version: 63
      }
    }
}]

出现其他节点的信息,表明节点连接成功

查看节点连接数
web3.net.peerCount

以太坊单位

单位 ----------------wei值-----------Wei
wei ---------------- 1 ------------1 wei
Kwei (babbage)------1e3 wei---------1,000
Mwei (lovelace)-----1e6 wei---------1,000,000
Gwei (shannon)------1e9 wei --------1,000,000,000
microether (szabo)--1e12 wei--------1,000,000,000,000
milliether (finney)-1e15 wei--------1,000,000,000,000,000
ether---------------1e18 wei--------1,000,000,000,000,000,000

最常用的就是wei和ether,客户端显示一般都是ether,转账交易时都需要将ether转换成wei
1 eth = 1e18 wei

// wei转换为ether
> web3.fromWei(‘22000000000000‘, ‘ether‘);
"0.000022"

// ether转换为wei
> web3.toWei(‘1‘,‘ether‘)
"1000000000000000000"

查询余额

查询旷工地址余额及查询指定地址余额

> eth.getBalance(eth.coinbase)
> eth.getBalance("0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5")

挖矿

> miner.start()

> miner.start()
INFO [09-06|22:46:00.911] Updated mining threads                   threads=0
INFO [09-06|22:46:00.911] Transaction pool price threshold updated price=18000000000
INFO [09-06|22:46:00.911] Starting mining operation
null
> INFO [09-06|22:46:00.912] Commit new mining work                   number=1 txs=0 uncles=0 elapsed=1.046ms
INFO [09-06|22:46:09.002] Successfully sealed new block            number=1 hash=300302…5db299
INFO [09-06|22:46:09.006] ???? mined potential block                  number=1 hash=300302…5db299
INFO [09-06|22:46:09.007] Commit new mining work                   number=2 txs=0 uncles=0 elapsed=874.759μs
INFO [09-06|22:46:09.608] Successfully sealed new block            number=2 hash=186735…3546a7

查看b节点控制台可以看出,节点a在挖矿,节点b在同步数据

停止挖矿
> miner.stop()

再次查看余额

> eth.getBalance(eth.coinbase)
135000000000000000000

两个节点也可以同时挖矿

在节点a查询节点b地址的余额

 > eth.getBalance("0x7af1b2e3ccea944c64b5cd60ecc8dc9c998a211f")
145000000000000000000

节点a也能查询到节点b地址的信息和余额,说明节点a和节点b的数据是完全同步的

交易转账

现在我们从节点a的coinbase账户发送一笔交易到节点b的一个新钱包。
转账前需要先解锁账户

> personal.unlockAccount(eth.coinbase)
Unlock account 0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5
Passphrase:
true

转账完成后再次查询余额

> eth.sendTransaction({from: eth.coinbase, to: ‘0x5048b919c2ef522b1313944718ffe0ce84e4e4b4‘, value: 1000000000000000000})
INFO [09-07|10:45:46.443] Submitted transaction                    fullhash=0x706537c56d005b42432ac3b3d4691621efbd35894c924d7dcc3961c155c67217 recipient=0x5048B919c2ef522b1313944718FfE0cE84E4E4b4
"0x706537c56d005b42432ac3b3d4691621efbd35894c924d7dcc3961c155c67217"
> eth.getBalance("0x5048b919c2ef522b1313944718ffe0ce84e4e4b4")
0

发现余额是0,因为还没有矿工对交易进行挖矿打包。

执行挖矿
miner.start()

再次查询

> eth.getBalance("0x5048b919c2ef522b1313944718ffe0ce84e4e4b4")
1000000000000000000

一个eth 已经到账。

带gas参数的转账命令

eth.sendTransaction({from: eth.coinbase, to: "0xa8d003b95ed969e68db9eb077ad333a3df10450a", gas:1000, ‘gasPrice‘: web3.toWei(300, ‘gwei‘), "value": "1"})

智能合约

写一个简单的智能合约

pragma solidity ^0.4.24;
contract Sample {
    uint public value;
    function Sample(uint v){
        value=v;
    }
    function set(uint v){
        value=v;
    }
    function get() constant returns (uint){
        return value;
    }
}

http://remix.ethereum.org/上编译得到
ABI和合约的二进制代码

点击右上角的 start to complie 之后,在点击下方的details
在bitecode里面的object 拿到合约的二进制代码,然后在前面补上0x.
然后在下一栏拿到ABI文件,复制得到的ABI文件带有空格,可用json工具(http://www.bejson.com/jsonviewernew)把空格去掉

将abi代码去除空格后

[{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"v","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

然后在节点a输入

>abi=[{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"v","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
[{
    constant: true,
    inputs: [],
    name: "value",
    outputs: [{
        name: "",
        type: "uint256"
    }],
    payable: false,
    stateMutability: "view",
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "v",
        type: "uint256"
    }],
    name: "set",
    outputs: [],
    payable: false,
    stateMutability: "nonpayable",
    type: "function"
}, {
    constant: true,
    inputs: [],
    name: "get",
    outputs: [{
        name: "",
        type: "uint256"
    }],
    payable: false,
    stateMutability: "view",
    type: "function"
}, {
    inputs: [{
        name: "v",
        type: "uint256"
    }],
    payable: false,
    stateMutability: "nonpayable",
    type: "constructor"
}]

在输入

> sample=eth.contract(abi)
{
  abi: [{
      constant: true,
      inputs: [],
      name: "value",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
  }],
  eth: {
    accounts: ["0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5"],
    blockNumber: 79,
    coinbase: "0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5",
    compile: {
      lll: function(),
      serpent: function(),
      solidity: function()
    },
    defaultAccount: undefined,
    defaultBlock: "latest",
    gasPrice: 18000000000,
    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()
}

然后再输入二进制合约代码

> SampleHEX="0x608060405234801561001057600080fd5b50604051602080610114833981016040525160005560e1806100336000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f2458114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a7230582084151f58c02538f867209172d079a7bc65c934502439ff9607bcfb0c1f097f000029"
"0x608060405234801561001057600080fd5b50604051602080610114833981016040525160005560e1806100336000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f2458114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a7230582084151f58c02538f867209172d079a7bc65c934502439ff9607bcfb0c1f097f000029"

把合约部署到链上

> personal.unlockAccount(eth.coinbase)
Unlock account 0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5
Passphrase:
true
> thesample=sample.new(1,{from:eth.accounts[0],data:SampleHEX,gas:3000000})
INFO [09-09|18:30:33.352] Submitted contract creation              fullhash=0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16 contract=0x7D423D420C8a63D86c1116ef71ba2F5d405a7714
{
  abi: [{
      constant: true,
      inputs: [],
      name: "value",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
  }],
  address: undefined,
  transactionHash: "0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16"
}

合约中最重要的两个信息是合约地址和合约hash,上面的contract就是合约地址,也可以通过下面的交易细节获取到合约地址

挖一会矿miner.start()后停止miner.stop(),根据合约hash查看交易细节

> samplerecpt=eth.getTransactionReceipt("0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16")
{
  blockHash: "0x54bb9756e7310deff7192a6184833e76d2b203334093aac97b773a8d11081705",
  blockNumber: 80,
  contractAddress: "0x7d423d420c8a63d86c1116ef71ba2f5d405a7714",
  cumulativeGasUsed: 134093,
  from: "0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5",
  gasUsed: 134093,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0xe88933bb56dd158847b0cf443b896be470f0ebd1d44d2e78bac023b1a3ff77d3",
  to: null,
  transactionHash: "0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16",
  transactionIndex: 0
}

拷贝合约地址并命名,就可以拿到合约并执行合约的方法

> samplecontract=sample.at("0x7D423D420C8a63D86c1116ef71ba2F5d405a7714")
{
  abi: [{
      constant: true,
      inputs: [],
      name: "value",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
  }],
  address: "0x7D423D420C8a63D86c1116ef71ba2F5d405a7714",
  transactionHash: null,
  allEvents: function(),
  get: function(),
  set: function(),
  value: function()
}

查看合约get方法

> samplecontract.get.call()
1

调用合约set方法,如果账户已经锁定,就先解锁
调用set方法后,还需要挖矿才能生效

> samplecontract.set.sendTransaction(5, {from:eth.accounts[0], gas:3000000})
INFO [09-09|18:41:44.003] Submitted transaction                    fullhash=0x282aa828d5df526b20775d696b0df8c5ad1caf88adb972d7bad796ba35977fa4 recipient=0x7D423D420C8a63D86c1116ef71ba2F5d405a7714
"0x282aa828d5df526b20775d696b0df8c5ad1caf88adb972d7bad796ba35977fa4"

然后挖矿,查看结果

> samplecontract.get.call()
5

在节点b查看节点a中部署的合约
进入节点b的终端

> samplerecpt=eth.getTransactionReceipt("0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16")
{
  blockHash: "0x54bb9756e7310deff7192a6184833e76d2b203334093aac97b773a8d11081705",
  blockNumber: 80,
  contractAddress: "0x7d423d420c8a63d86c1116ef71ba2f5d405a7714",
  cumulativeGasUsed: 134093,
  from: "0x635b3b3a6b3b9840edb9531ec91193bbf15f12f5",
  gasUsed: 134093,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0xe88933bb56dd158847b0cf443b896be470f0ebd1d44d2e78bac023b1a3ff77d3",
  to: null,
  transactionHash: "0xd507ca17f199c014a153c08b221107e01c6365c7d10eb609bdad99535de7dd16",
  transactionIndex: 0
}

在节点b中通过合约地址获取合约,并调用合约方法

> abi=[{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"v","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

> sample=eth.contract(abi)

  • 通过合约地址获取二进制文件
> SampleHex=eth.getCode("0x7D423D420C8a63D86c1116ef71ba2F5d405a7714")
"0x60806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f2458114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a7230582084151f58c02538f867209172d079a7bc65c934502439ff9607bcfb0c1f097f000029"
  • 通过合约地址获取到合约对象

    > sampleContract=sample.at("0x7D423D420C8a63D86c1116ef71ba2F5d405a7714")
    {
    abi: [{
      constant: true,
      inputs: [],
      name: "value",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
    }, {
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
    }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
    }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
    }],
    address: "0x7D423D420C8a63D86c1116ef71ba2F5d405a7714",
    transactionHash: null,
    allEvents: function(),
    get: function(),
    set: function(),
    value: function()
    }
  • 调用合约方法
    > sampleContract.get.call()
    5

加入区块链开发学习交流群,请添加微信:Xhole1024
虫洞社区:https://www.uzanapp.com/

原文地址:http://blog.51cto.com/13980151/2178791

时间: 2024-10-07 05:47:40

以太坊搭建联盟链详细教程的相关文章

GitHub+Hexo 搭建个人网站详细教程

原文链接 GitHub+Hexo 搭建个人网站详细教程 前言: 随着互联网浪潮的翻腾,国内外涌现出越来越多优秀的社交网站让用户分享信息更加便捷.然后,如果你是一个不甘寂寞的程序猿(媛),是否也想要搭建一个属于自己的个人网站,如果你曾经或者现在正有这样的想法,请跟随这篇文章发挥你的Geek精神,让你快速拥有自己的博客网站,写文章记录生活,享受这种从0到1的过程. 你见过的最棒的个人博客界面是什么样的? 什么是Hexo ? Hexo是一款基于Node.js的静态博客框架,依赖少易于安装使用,可以方便

搭建SVN服务器详细教程

搭建SVN服务器详细教程 本教程会从最基本的下载安装到上传代码,下载代码这条线来详细讲述如何完成SVN服务器的搭建 下载并安装VisualSVN server 下载并安装TortoiseSVN 导入项目 创建用户组和用户 设置权限 检出项目 下载并安装VisualSVN server 下载VisualSVN server 下载地址:https://www.visualsvn.com/server/download/ 下载完成后是这样的 安装VisualSVN server` Location是指

搭建基于以太坊的私有链环境

零.概述 版本号:Ubuntu-16.04 ethereum-1.6.0-stable go - 1.7.4 一.Ubuntu下安装geth sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install ethereum 二.创建初始化文件 vim genesis.json {    

以太坊-windows-私有链-搭建(非源码)

初 接触以太坊,只安装,不讲道理: 1.win10系统,64位 2.以太坊钱包 3.以太坊geth客户端 geth 和 钱包可以到ethfans.org的资料库里下载,那里提供国内镜像和官网地址. 钱包工具:https://ethfans.org/wikis/Ethereum-Wallet-Mirror geth :https://ethfans.org/wikis/Ethereum-Geth-Mirror 首先,安装geth,选择安装目录d:\blockchain,安装完成之后,该文件夹下回出

EOS和以太坊那个区块链平台更好?

显然,你已经听说过两个最受欢迎的智能合约区块链,但想知道EOS与以太坊之中哪个更好?或许你想比较一下两种技术?好吧,你来对了地方,因为我要告诉你你需要知道的一切! 在这个EOS vs Ethereum指南中,我将首先解释每个项目的基础知识,然后概述每个区块链的执行情况.这将包括交易时间,交易费用和可扩展性等内容. 之后,我将简要介绍如何在没有第三方的情况下验证交易.这将包括以太坊使用的工作量证明(Proof of Work)与EOS使用的股份授权证明(Delegated Proof of Sta

F3D系统开发以太坊Fomo3D区块链模式

Fomo3D(F3D)以太坊ETH底层技术系统开发空气-陳洋1 5 0 1*3 1 5 1*7 4 0电T微.现代经济体系正在朝着分布式.点对点.网络化的结构进行演化.分布式账本技术吸收了现代密码学.安全通讯.可信计算.对等网络和博弈论的研究成果,尝试构建一个分布式.防篡改.异构多活和灵活定制的计算架构,以求支撑数字经济时代的业务需求.分布式账本技术还处于它的早期阶段,我们可以将其视为一种"组合式创新"(Combinatorial Innovation),运用创新经济学的理论研究它的应

阿里云搭建LAMP环境详细教程

一.云服务器的选择 随着大数据时代的到来,为了满足更为复杂的运算和用户更为苛刻的需求,云计算应运而生,随之而来的就是云服务器.过去的服务器成本较高,运算模式较为单一,资源利用率不高,而云服务器的出现刚好弥补了这一缺陷.现在市场上云服务器品牌众多,但凡有一定资本的公司都推出了自己的云服务器,如百度云主机,腾讯云,阿里云等等.各大品牌的云服务器提供的功能大同小异,可根据自己的喜好随意选择,在这里我只以自己选择的阿里云作为主体,主要是阿里云有针对在校学生的优惠政策,其它的没用过,暂不评论. 那么首先,

创建移动端网页百度联盟广告位详细教程

如图: 打开百度联盟后台,进入合作管理,代码位管理,可以创建代码位,下面展示的是已经创建好的代码位. 创建代码位 如果是只想展示图文形式的广告,则在样式设置中勾选图文广告,其他取消勾选 创建好的图文广告样式如图: 如果想要设置在新闻图片列表中偶尔插入一个广告位的形式,可以选择自定义比例: 应该只有20:6以上的比例才可以设置特色样式,选择股东图片数,启用,填充行数和列数即是一行显示几个广告,一共显示几行,如果只想显示一个,则可以这里设置1,1 ,并切记选择按父容器宽度. 实现效果如图: 信息流以

2018年以太坊智能合约开发语言Solidity最佳IDEs

Solidity是一种以智能合约为导向的编程语言.这是一种只有四年的年轻语言,旨在帮助开发基于以太坊数字货币的智能合约. 理解它官方文档应该是学习Solidity的最佳来源:solidity.readthedocs.io 想在以太坊的网络上建立自己的加密货币吗?想拥有自己的初始代码产品吗?以下是您今天可以使用的最佳Solidity IDE. Remix IDE Remix IDE是基于浏览器的,并且集成了编译器.没有服务器端组件. 官网: https://remix.ethereum.orggi