概述
本文讲解了如何通过以太坊私链来进行转账。在学习以太坊实战之前,请先根据我写的这篇文章搭建好以太坊的私有链。
基于以太坊私链模拟转账
进入控制台
先按上一篇文章开启一个节点,可以先通过命令:miner.stop()停止挖矿。再按以下命令进入控制台:
geth --datadir "./db" attach ipc:./db/geth.ipc
- 1
1. 新建账户
为了完成转账,我们首先需要创建两个账号,如下:
- 创建第一个账户
> personal.newAccount("hover")
"0x8663aca6d67330041e3218de54e3123bcea9e866"
>
personal.newAccount函数的参数是账户的密码。执行成功后会返回账户的公钥,生成的账户文件在keystore文件夹下,此时工作目录geth的目录结构如下:
├── db
│ ├── geth
│ │ ├── chaindata
│ │ │ ├── 000002.ldb
│ │ │ ├── 000003.log
│ │ │ ├── CURRENT
│ │ │ ├── CURRENT.bak
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000004
│ │ ├── lightchaindata
│ │ │ ├── 000001.log
│ │ │ ├── CURRENT
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000000
│ │ ├── LOCK
│ │ ├── nodekey
│ │ ├── nodes
│ │ │ ├── 000001.log
│ │ │ ├── CURRENT
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000000
│ │ └── transactions.rlp
│ ├── geth.ipc
│ └── keystore
│ └── UTC--2018-08-26T03-56-48.638581930Z--8663aca6d67330041e3218de54e3123bcea9e866
其中账户信息在keystore文件夹下。
- 创建第2个账户
> personal.newAccount("123")
"0x96c275557213349816d57c4b482378eef1552150"
再看一下keystore下的目录结构:
└── keystore
│ ├── UTC--2018-08-26T03-56-48.638581930Z--8663aca6d67330041e3218de54e3123bcea9e866
│ └── UTC--2018-08-26T04-02-57.501956829Z--96c275557213349816d57c4b482378eef1552150
查看一下目前账户的情况:
> eth.accounts
["0x8663aca6d67330041e3218de54e3123bcea9e866", "0x96c275557213349816d57c4b482378eef1552150"]
好了,现在我们已经有了两个账户。
2.查看余额
要完成转账首先需要有余额,我先查看一下目前账户的余额情况:
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
0
> balance = web3.fromWei(eth.getBalance(eth.accounts[1]), "ether")
0
eth.accounts[index]会按传入的索引返回已有的账户。eth.getBalance(address)会返回账户的余额,余额以wei为单位。传入的参数是账户的公钥,web3.fromWei单位转换,在这个例子中是将wei转换成ether。
通过以上例子我们看到两个账户的余额都是0,我们需要通过挖矿开获取以太币,下面来挖矿。
3.挖矿
在挖矿前,我们需要设置挖矿的奖励地址。
* 设置奖励地址
> miner.setEtherbase(eth.accounts[0])
true
- 查看是否设置成功
> eth.coinbase
"0x8663aca6d67330041e3218de54e3123bcea9e866"
> eth.accounts
["0x8663aca6d67330041e3218de54e3123bcea9e866", "0x96c275557213349816d57c4b482378eef1552150"]
eth.coinbase是设置的奖励地址。从以上命令,我们可以看到,已经设置成功了。
- 开始挖矿
miner.start(1)
start的参数是线程数,我这里设置的是1。此时要是attach到某个节点上,那么可以该节点上看到对应的输出:
...
INFO [08-26|15:36:22.591] Successfully sealed new block number=31 hash=14416f…bf92ab elapsed=550.351ms
INFO [08-26|15:36:22.592] ? block reached canonical chain number=26 hash=034961…db0845
INFO [08-26|15:36:22.592] ? mined potential block number=31 hash=14416f…bf92ab
INFO [08-26|15:36:22.592] Commit new mining work number=32 uncles=0 txs=0 gas=0 fees=0 elapsed=116.351µs
INFO [08-26|15:36:23.070] Successfully sealed new block number=32 hash=ea42ae…74e5a4 elapsed=477.569ms
INFO [08-26|15:36:23.070] ? block reached canonical chain number=27 hash=9d3a02…ea355a
INFO [08-26|15:36:23.070] ? mined potential block number=32 hash=ea42ae…74e5a4
INFO [08-26|15:36:23.070] Commit new mining work number=33 uncles=0 txs=0 gas=0 fees=0 elapsed=119.824µs
INFO [08-26|15:36:23.548] Successfully sealed new block number=33 hash=7e4983…8995f0 elapsed=478.359ms
INFO [08-26|15:36:23.549] ? block reached canonical chain number=28 hash=8d8380…e21886
INFO [08-26|15:36:23.549] ? mined potential block
...
- 停止挖矿
miner.stop()
- 查看现在的余额
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
415
4.解锁账号
在开始转账之前需要先解锁账号,否则会报错。
> personal.unlockAccount(eth.accounts[0], "123", 900)
true
其中的第1个参数是:账户。第2个参数是:密码。第3个参数是:解锁的持续时间。
5. 交易:转账
>eth.sendTransaction({from: eth.accounts[0], to : eth.accounts[1], value: web3.toWei(10, "ether")})
"0x4edf43809d4c5603a2dfd8496ddb056d1725ffd80e8afaf95132447f19168548"
当交易发送到区块链后,会返回一个交易的hash,此时的交易正在矿工的交易池中等待被打包。可以查看交易池中等待被打包的交易:
> txpool.status
{
pending: 1,
queued: 0
}
有一个交易被pending,还没有被处理。可以查看pending交易的详情:
> txpool.inspect.pending
{
0xDaE3d4234AD88421Bb4Dd5033143d25d8760DbfA: {
0: "0xFF50D7746384D7e5a8769EA5501B2f894C241a14: 10000000000000000000 wei + 90000 gas × 18000000000 wei"
}
}
6. 再次挖矿,让交易被处理
要让交易被处理,就必须要挖矿。我们启动挖矿,然后等待挖到一个区块链后就停止:
> miner.start(1); admin.sleepBlocks(1); miner.stop();
true
再查看未被处理的交易情况:
> txpool.inspect.pending
{}
可以看到,已经没有未被处理的交易。
查看余额:确认交易成功
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")
410
> balance = web3.fromWei(eth.getBalance(eth.accounts[1]), "ether")
10
可以看到,交易已经成功,成功的把10个以太币从账户0,转移到账户1。但这里的数量好像不对?
415-10=405,应该剩下405,怎么剩下410呢?
原因是,这里的coinbase账号是account[0],而每个区块生成的(挖矿成功)的奖励是5,所以这里是405+5=410。
这说明,我们的转账成功了。
查看交易详情
把刚才发起交易时返回的交易hash值传入eth.getTransaction函数,即可得到交易的详情。
> eth.getTransaction("0x4edf43809d4c5603a2dfd8496ddb056d1725ffd80e8afaf95132447f19168548")
{
blockHash: "0xf232c92c07bbb7c1728567515ade844190b975d481c1e9017d0fa7dc445d76c4",
blockNumber: 108,
from: "0xdae3d4234ad88421bb4dd5033143d25d8760dbfa",
gas: 90000,
gasPrice: 18000000000,
hash: "0x4edf43809d4c5603a2dfd8496ddb056d1725ffd80e8afaf95132447f19168548",
input: "0x",
nonce: 0,
r: "0x10dec63e3844284d2568e68c233ddbdfedf287783e8db03749e38da632acf109",
s: "0x53ff6bc3821140a1711d98e26a4d3ca161af341605543f3ee8377a28032b70d7",
to: "0xff50d7746384d7e5a8769ea5501b2f894c241a14",
transactionIndex: 0,
v: "0x4c",
value: 10000000000000000000
}
查看区块详情
从交易的详情中可以得到区块号,通过eth.getBlock函数,可以获取到某个区块号的区块的详细信息。
> eth.getBlock(108)
{
difficulty: 131834,
extraData: "0xd98301080e846765746888676f312e31302e318664617277696e",
gasLimit: 3864853197,
gasUsed: 21000,
hash: "0xf232c92c07bbb7c1728567515ade844190b975d481c1e9017d0fa7dc445d76c4",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0xdae3d4234ad88421bb4dd5033143d25d8760dbfa",
mixHash: "0x7e58396f67a9e4cc706d29c54544492caa6b44b04b4cb7e9e62e6f6642333be3",
nonce: "0x6bde023f861f3089",
number: 108,
parentHash: "0x43832c74e796c1b22675419ddfc66374e2aa283174d864fb6fd5179ef4419a01",
receiptsRoot: "0xb1e76317cdac9eed95b9e30439dc4020f130f2b5d66b8c31d07906a0aef096a7",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 652,
stateRoot: "0x30866579a619eaa4e0894d99e4fbbc1f1877f8ff9182e528b71ee02921ac766b",
timestamp: 1535269782,
totalDifficulty: 14391713,
transactions: ["0x4edf43809d4c5603a2dfd8496ddb056d1725ffd80e8afaf95132447f19168548"],
transactionsRoot: "0x7adf91188514ae548ca69b6b25c8e66c757340009630c39a8d4af60c0aecaf13",
uncles: []
}
获取创世块的信息
> eth.getBlock(0)
{
difficulty: 1,
extraData: "0x777573686f756865",
gasLimit: 4294967295,
gasUsed: 0,
hash: "0x8c0faf797027b7e1f0fc0528ef73ec4b7cf2c9d19f358c19a0d770506737fa8e",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x0000000000000000000000000000000000000000",
mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
nonce: "0x0000000000000001",
number: 0,
parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 513,
stateRoot: "0x614bf1b5ff99d2d78f80b391f520819f5cc0d873c822944a9497b9aabae5b159",
timestamp: 0,
totalDifficulty: 1,
transactions: [],
transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: []
}
总结
本文描述了如何通过以太坊私有链的命令来发起交易,查看区块信息,执行交易等操作。并结合一个转账的场景进行了模拟使用。