以太坊私链搭建、truffle项目开发

本文实现以下目标:

  1. 搭建一条以太坊私链
  2. 用企业级开发方式开发、部署一个项目
  3. 分析truffle执行过程
  4. solidity、web3等的一些说明

Token ERC20标准

contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

整个区块链的所有数据都存储在一个levelDB的数据库中,其物理文件存储在:~/Library/Ethereum/geth/chaindata/ 下。

搭建以太坊私链

1、创建目录eth

mkdir eth

2、编写创世区块,放入eth目录下。

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

其中,alloc用来预设账号和账号的以太币数量,此处不预设,需要的时候再创建。

  • [ ] 注意
gasLimit要修改大点,不然部署智能合约的时候,合约需要消耗的gas超过这个limit会发生失败。

chainId是EIP155里定义的发送交易到哪种链的方式,(EIP是以太坊改进建议)。这里设置为10,truffle.js里的network_id也得是10,不然交易的时候会报invalid sender的错误。

CHAIN_IDChain(s)
1Ethereum mainnet
2Morden (disused), Expanse mainnet
3Ropsten
4Rinkeby
30Rootstock mainnet
31Rootstock testnet
42Kovan
61Ethereum Classic mainnet
62Ethereum Classic testnet
1337Geth private chains (default)

3、创建创世块

geth --datadir "./" init genesis.json

--datadir是指定区块链数据和账户的存储目录。\
这句话的作用是:\
创建2个数据库chaindata和lightchaindata,并把genesis.json的数据分别写入这两个leveldb中。

4、启动以太坊,日志写入文件,同时进入js交互控制台。

geth --datadir "./" --rpc --rpccorsdomain="*"  console 2>>00.glog

rpccorsdomain是允许chrome插件MetaMask,remix等跨域访问web3接口。

现在这条私链上没有账户没有交易。

5、在启动矿工进行挖矿之前我们必须创建至少一个账户,并将其设为ether base账户,这样矿工挖矿所得的以太币将自动存入我们设置的账户。
因为部署合约需要消耗以太币,这里在私链上通过挖矿获得以太币。

创建账户(账户是一对密钥)

personal.newAccount(“your account passwd”)

输出了一个账户地址:

0xad30387c05b527a85f45186c2b8aab5e1af2f227

这个账户的私钥文件就存储在$datadir/keystore文件夹下。

6、将这个账户设置为矿工etherbase

miner.setEtherbase(eth.accounts[0])  

设置之后,一旦启动挖矿,则挖矿收益就打入这个账户,所以设置之后这个账户也叫coinbase。

以上私链搭建完成。

MetaMask导入账户

MetaMask以太钱包,导入在geth控制台创建的那个账号,然后用这个账户去领养宠物。

首先登录MetaMask,然后点击右上角用户那里->点击导入账户->选择json file类型->选择浏览到keystore下对应账户文件->输入这个账户的密码。

完成上述步骤,就导入了geth新建的账户。

关于MetaMask和账户的关系理解:

MetaMask就是以太钱包。

  • [x] 这个钱包的私钥文件就仅仅存储在你自己的设备上,丢失了就没了。
  • [x] 你的密码就是这个钱包的私钥的加密签名。
  • [x] 钱包地址就是公钥。

账户就是一对公私钥(各为256位的数字),用地址(去掉公钥前12字节,剩余160位,用16进制编码是40个字符)表示。

在MetaMask上建的账户和geth里建的账户,都是典型的外部拥有账户(参见以太坊基础概念专题);

你也可以根据账户的提示词、私钥文件导入其他账户到同一钱包(注意导入的账户要和选择的链网络<公链、私链、测试链等>匹配,也就是该链里先有此账户才能导入,否则只能先创建,可以在钱包界面上创建也可以在geth里用命令创建)。

项目开发

这里用truffle+私链的方式演示企业级项目开发。

项目源码公布在:
https://github.com/m3shine/et...

创建项目

项目所需工具、概念和项目结构描述参见我的另一篇专栏文章:
https://segmentfault.com/a/11...

此项目包含以下功能

  • [x] 领养宠物(仅展示)
  • [x] 发行币(token)

领养宠物

发行币(token)

发行总量为20亿的傻币,代号SB。

首先需要一个合约,其次明确创建合约需要消耗的是gas(以以太币支付),而不是消耗SB。

基于以太坊的币(token)要和以太币区分开。

通过truffle向以太坊私链部署合约

1、在用truffle向私链部署合约前,需要解锁账户。而一个账户被创建时以太坊默认是将其锁住的。

解锁账户

personal.unlockAccount(eth.accounts[0], "you account passwd", 15000)

第三个参数是解锁时间——单位秒。

这里的accounts[0]就是我们搭建私链的时候创建的第一个账户。

2、确保以太坊私链启动中,并有矿工在挖矿(出块)

查看是否有pending的交易,应该没有,有的话会阻塞交易。

txpool.status
miner.start()

3、部署智能合约

在移植之前,

  • [ ] 首先需要有一个账户并设为矿工地址(默认第一个账户就是矿工地址);
  • [ ] 其次需要解锁账户;
  • [ ] 再次需要账户里有钱(eth);
  • [ ] 最后需要有矿工在出块(挖矿)才能完成移植。

cd到truffle工程目录下,执行:

truffle migrate --reset --network development

--network development是根据truffle.js文件里定义的网络使用的:

networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "10" // 这里的id必须与创世区块genesis里的chainId一样。
    }
  }

--reset

使用reset可以重新执行所有(默认只执行新增而未执行的)migration脚本,但在真实网络里这样做不切实际,因为每次执行都需要消耗gas。\
在区块链中,每个部署都是一个交易,每个交易都是不可逆的。这种架构背后的全部理念是允许我们添加/升级合约并仅重新部署受影响的合同。\
想象一下我们已经升级了一个合约如TokenSB.sol,要怎样部署这个合约而不重新部署其他合约?我们就需要新建一个部署脚本,放在migrations目录下,再执行

truffle migrate

这时将从这个最新的部署脚本开始执行。

看一下移植的输出:

Compiling ./contracts/TokenSB.sol...
Writing artifacts to ./build/contracts

Using network 'development'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714
  Migrations: 0x7b8d3f0ce869c8ffbfaff027a7a21fab6f0e179c
Saving successful migration to network...
  ... 0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6
Saving artifacts...
Running migration: 2_deploy_contract.js
  Replacing TokenSB...
  ... 0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057
  TokenSB: 0xb90598a717180f21a13432d5cc7f1823267c9a95
Saving successful migration to network...
  ... 0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d
Saving artifacts...

这是发生了4笔交易,其中两笔是“合约创建”交易,创建了2个合约(对应生成2个合约账户),另外两笔交易是通过矿工账户支付gas给Migration合约账户来改变它的状态,具体改变了什么状态?在Migraion.sol里的setCompleted函数用来更新部署次数,每执行一个migrate脚本次数加1,改变的这个状态就是最新的部署次数!

upgraded.setCompleted(last_completed_migration);

4笔交易:\
0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714\
0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6\
0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057\
0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d

2个合约账户:\
0x7b8d3f0ce869c8ffbfaff027a7a21fab6f0e179c\
0xb90598a717180f21a13432d5cc7f1823267c9a95

geth日志里对应打印出:

INFO [04-09|16:47:03] Submitted contract creation              fullhash=0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714 contract=0x7b8D3F0CE869c8fFBFAfF027a7a21fAB6F0e179c
INFO [04-09|16:47:03] Commit new mining work                   number=11 txs=1 uncles=0 elapsed=2.004s
INFO [04-09|16:47:04] Successfully sealed new block            number=11 hash=fd0e4e…3955ff
INFO [04-09|16:47:04] ? block reached canonical chain          number=6  hash=76cc1a…87326d
INFO [04-09|16:47:04] ? mined potential block                  number=11 hash=fd0e4e…3955ff
INFO [04-09|16:47:04] Commit new mining work                   number=12 txs=0 uncles=0 elapsed=107.73µs
INFO [04-09|16:47:04] Submitted transaction                    fullhash=0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6 recipient=0x7b8D3F0CE869c8fFBFAfF027a7a21fAB6F0e179c
INFO [04-09|16:47:04] Successfully sealed new block            number=12 hash=e3408a…076693
INFO [04-09|16:47:04] ? block reached canonical chain          number=7  hash=5ce86f…e788a4
INFO [04-09|16:47:04] ? mined potential block                  number=12 hash=e3408a…076693
INFO [04-09|16:47:04] Commit new mining work                   number=13 txs=1 uncles=0 elapsed=323.85µs
INFO [04-09|16:47:05] Successfully sealed new block            number=13 hash=c7d419…3bb02a
INFO [04-09|16:47:05] ? block reached canonical chain          number=8  hash=043c14…6b2ee9
INFO [04-09|16:47:05] ? mined potential block                  number=13 hash=c7d419…3bb02a
INFO [04-09|16:47:05] Commit new mining work                   number=14 txs=0 uncles=0 elapsed=179.885µs
INFO [04-09|16:47:05] Successfully sealed new block            number=14 hash=940098…434280
INFO [04-09|16:47:05] Mining too far in the future             wait=2s
INFO [04-09|16:47:05] ? block reached canonical chain          number=9  hash=09c495…d093d3
INFO [04-09|16:47:05] ? mined potential block                  number=14 hash=940098…434280
INFO [04-09|16:47:05] Submitted contract creation              fullhash=0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057 contract=0xb90598a717180F21a13432d5Cc7F1823267c9a95
INFO [04-09|16:47:07] Commit new mining work                   number=15 txs=1 uncles=0 elapsed=2.005s
INFO [04-09|16:47:08] Successfully sealed new block            number=15 hash=fea615…3d68a2
INFO [04-09|16:47:08] ? block reached canonical chain          number=10 hash=f93cfa…2ed290
INFO [04-09|16:47:08] ? mined potential block                  number=15 hash=fea615…3d68a2
INFO [04-09|16:47:08] Commit new mining work                   number=16 txs=0 uncles=0 elapsed=177.032µs
INFO [04-09|16:47:08] Submitted transaction                    fullhash=0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d recipient=0x7b8D3F0CE869c8fFBFAfF027a7a21fAB6F0e179c
INFO [04-09|16:47:08] Successfully sealed new block            number=16 hash=cfb2b3…b8a7fe
INFO [04-09|16:47:08] ? block reached canonical chain          number=11 hash=fd0e4e…3955ff
INFO [04-09|16:47:08] ? mined potential block                  number=16 hash=cfb2b3…b8a7fe
INFO [04-09|16:47:08] Commit new mining work                   number=17 txs=1 uncles=0 elapsed=290.833µs
INFO [04-09|16:47:09] Successfully sealed new block            number=17 hash=159ff9…f3508d

可知:

有交易的区块分别是:
11、13、15、17

> eth.getBlock(11)
{
  difficulty: 131712,
  extraData: "0xd883010800846765746887676f312e392e338664617277696e",
  gasLimit: 4249054591,
  gasUsed: 269607,
  hash: "0xfd0e4e6be5425ce319155cfcbe793f2e6d3d52b2d23fd07f3ecfd94a363955ff",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  mixHash: "0x49a4b5f7caec56999e58755a60227433f29c5c58b0076432d3d62345151de06c",
  nonce: "0x6a24f90831c7d1f1",
  number: 11,
  parentHash: "0xf93cfaec78ecff5cad537060110ec2125950afd420b6ba126eccb1c8812ed290",
  receiptsRoot: "0xa12b62901dd69f911d94598790f5cd56cd691ccebca50198b50ab64d8a6ebf5b",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 1453,
  stateRoot: "0x89cd5db1f0ca7692e47401e957f4dce8ee9e8aaac0a4354493029a9134573aaa",
  timestamp: 1523263623,
  totalDifficulty: 1576384,
  transactions: ["0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714"],
  transactionsRoot: "0xe2a4c28a0c2d74022067bb9aec2a0d3c558c12c415032ab1943ec6ad8d991e06",
  uncles: []
}

> eth.getBlock(13)
{
  difficulty: 131840,
  extraData: "0xd883010800846765746887676f312e392e338664617277696e",
  gasLimit: 4240760105,
  gasUsed: 41981,
  hash: "0xc7d419560c21a331d5e5e61a086c49932d4f45f4404208e40fed4af1123bb02a",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  mixHash: "0xf8a970b3d32b998083dd3c39e8ccc7b08a31a4b8c784f707981ea89b266038fb",
  nonce: "0x4adb44428e6e46a5",
  number: 13,
  parentHash: "0xe3408acd7715d948e601463d3cb7ce2e233ca3822015a24a2ba2dfe35f076693",
  receiptsRoot: "0x1ced6b6f323a6d3c8854348bf48831c1279e67ba5a942d354b4f865e42da0eb6",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 679,
  stateRoot: "0x11c52848f9358e3c440a29cd704bcee363693a2582680688e21ee2b334aa9c4d",
  timestamp: 1523263625,
  totalDifficulty: 1840000,
  transactions: ["0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6"],
  transactionsRoot: "0x99f487f4989fda3411587062d0c0d8b77c8384786ed8611c600f8a8adc878d22",
  uncles: []
}

> eth.getBlock(15)
{
  difficulty: 131968,
  extraData: "0xd883010800846765746887676f312e392e338664617277696e",
  gasLimit: 4232481478,
  gasUsed: 1155362,
  hash: "0xfea615d7f14b9eea5557ee7db714865a662b8f2638303dad31a2b01d1c3d68a2",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  mixHash: "0x6d445e0680455e1b426eac12486bd44d48885d47db9fcf9ef3e37d1cfdce6aa5",
  nonce: "0x343cce18fe3e47df",
  number: 15,
  parentHash: "0x940098cd10e8ffd179b11c719896aed6efd518c89bfec83917f9d78faa434280",
  receiptsRoot: "0xe0619e0df84cf66deb0332cdd5b636c360ad4c6b2efa6960206dd16e67ac64fd",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 4929,
  stateRoot: "0xb3ede09e46d4e16d7ac1693fa6ccc7f81d6a5a37160f39b2e6e29dee76ed4175",
  timestamp: 1523263627,
  totalDifficulty: 2103872,
  transactions: ["0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057"],
  transactionsRoot: "0xec03b0be1484e3cac495ef585ac0e9fd63e662ef466bdc717e0e8c1acdb8fbfb",
  uncles: []
}

> eth.getBlock(17)
{
  difficulty: 132096,
  extraData: "0xd883010800846765746887676f312e392e338664617277696e",
  gasLimit: 4224220643,
  gasUsed: 26981,
  hash: "0x159ff93dc61a32249f7f6c82fd0db65b8b45e33f416a29a047b2368edaf3508d",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  mixHash: "0xf5eda18e9417084bc0e8dcee5a1d05d9c5ef37108427d8265ac4000b7efc9261",
  nonce: "0x0c5e1f26c990f4d2",
  number: 17,
  parentHash: "0xcfb2b3cdda47aa0e7cb785f008613424402709ab6bdf759ea644a85af6b8a7fe",
  receiptsRoot: "0xcabd0eff6a0d339c032b7f9cb5a9f8211ab94c1626c698eff51930d07e103a57",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 679,
  stateRoot: "0xa7c3e91886e55c296c8f0f3566bdf7fe37c09ec3e1a9a74c7583a76a18442d9e",
  timestamp: 1523263629,
  totalDifficulty: 2368000,
  transactions: ["0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d"],
  transactionsRoot: "0x37ae7f0819cc599fc1edd798dccc5298d7aad92314a1e3fce4703e4516ffc9e2",
  uncles: []
}

4笔交易分别是:

> eth.getTransaction('0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714')
{
  blockHash: "0xfd0e4e6be5425ce319155cfcbe793f2e6d3d52b2d23fd07f3ecfd94a363955ff",
  blockNumber: 11,
  from: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  gas: 6721975,
  gasPrice: 100000000000,
  hash: "0x751b8cc80859a4c9fa39aa27b6ee2e89fcbe49713ed3f5fb8f788a886878b714",
  input: "0x6060604052341561000f57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102db8061005e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100a05780638da5cb5b146100c9578063fdacd5761461011e575b600080fd5b341561007257600080fd5b61009e600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610141565b005b34156100ab57600080fd5b6100b3610224565b6040518082815260200191505060405180910390f35b34156100d457600080fd5b6100dc61022a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561012957600080fd5b61013f600480803590602001909190505061024f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610220578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b151561020b57600080fd5b6102c65a03f1151561021c57600080fd5b5050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102ac57806001819055505b505600a165627a7a723058200d2898098cb3b0615d05013d7ff7cf6e54eaff6b98e66e9e5a864778b9c6c69d0029",
  nonce: 0,
  r: "0xd9bfae2f413b63cb615d423773f6a48c2898f695be6e13060f9fe43af6a33231",
  s: "0x1a3c02f7f90dc7acd2a75f2ff7018fcb92981815fa9b590c9b9e9bc142ccb5b5",
  to: null,
  transactionIndex: 0,
  v: "0x38",
  value: 0
}

> eth.getTransaction('0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6')
{
  blockHash: "0xc7d419560c21a331d5e5e61a086c49932d4f45f4404208e40fed4af1123bb02a",
  blockNumber: 13,
  from: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  gas: 6721975,
  gasPrice: 100000000000,
  hash: "0x4b6ac5acc4b6965a6463db905eb33019d48ff64ccf3e1cf19d6020dbf0d8f2b6",
  input: "0xfdacd5760000000000000000000000000000000000000000000000000000000000000001",
  nonce: 1,
  r: "0xe8666b647d772228051922ccd2bbec8d6fb1622716e5484e1a500d9b9de98120",
  s: "0x35fbdb3a0a700f7a1cdf793ab5a6643131660dc64bc8d867a267fdd6cf8e1317",
  to: "0x7b8d3f0ce869c8ffbfaff027a7a21fab6f0e179c",
  transactionIndex: 0,
  v: "0x38",
  value: 0
}

> eth.getTransaction('0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057')
{
  blockHash: "0xfea615d7f14b9eea5557ee7db714865a662b8f2638303dad31a2b01d1c3d68a2",
  blockNumber: 15,
  from: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  gas: 6721975,
  gasPrice: 100000000000,
  hash: "0xda750feafdb742c16bb56c57beb84a21346cabc847af19faa98c3fddb47c4057",
  input: "0x60606040526012600260006101000a81548160ff021916908360ff160217905550341561002b57600080fd5b604051610fed380380610fed83398101604052808051906020019091908051820191906020018051820191905050600260009054906101000a900460ff1660ff16600a0a8302600381905550600354600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600090805190602001906100d39291906100f3565b5080600190805190602001906100ea9291906100f3565b50505050610198565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061013457805160ff1916838001178555610162565b82800160010185558215610162579182015b82811115610161578251825591602001919060010190610146565b5b50905061016f9190610173565b5090565b61019591905b80821115610191576000816000905550600101610179565b5090565b90565b610e46806101a76000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c5578063313ce5671461023e57806342966c681461026d57806370a08231146102a857806379cc6790146102f557806395d89b411461034f578063a9059cbb146103dd578063dd62ed3e1461041f575b600080fd5b34156100bf57600080fd5b6100c761048b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610529565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af6105b6565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105bc565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b6102516106e9565b604051808260ff1660ff16815260200191505060405180910390f35b341561027857600080fd5b61028e60048080359060200190919050506106fc565b604051808215151515815260200191505060405180910390f35b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610800565b6040518082815260200191505060405180910390f35b341561030057600080fd5b610335600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610818565b604051808215151515815260200191505060405180910390f35b341561035a57600080fd5b610362610a32565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a2578082015181840152602081019050610387565b50505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e857600080fd5b61041d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610ad0565b005b341561042a57600080fd5b610475600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610adf565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105215780601f106104f657610100808354040283529160200191610521565b820191906000526020600020905b81548152906001019060200180831161050457829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60035481565b6000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561064957600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506106de848484610b04565b600190509392505050565b600260009054906101000a900460ff1681565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561074c57600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b60046020528060005260406000206000915090505481565b600081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561086857600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156108f357600080fd5b81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ac85780601f10610a9d57610100808354040283529160200191610ac8565b820191906000526020600020905b815481529060010190602001808311610aab57829003601f168201915b505050505081565b610adb338383610b04565b5050565b6005602052816000526040600020602052806000526040600020600091509150505481565b6000808373ffffffffffffffffffffffffffffffffffffffff1614151515610b2b57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610b7957600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401111515610c0757600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401905081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a380600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401141515610e1457fe5b505050505600a165627a7a7230582058fcacc120960c2cf4be32f0b37a1e0be3601914de2acfb57bad06edc4e9f1ed00290000000000000000000000000000000000000000000000000000000077359400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000006e582bbe5b881000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025342000000000000000000000000000000000000000000000000000000000000",
  nonce: 2,
  r: "0xbd3c155041f1385edb2b6321083c43421ceb2ed7129c52ac72693529852ae59f",
  s: "0x73a4c275d28a8c87e710bdd571865054ada56e78c5c65541979da4cc619a097d",
  to: null,
  transactionIndex: 0,
  v: "0x37",
  value: 0
}

> eth.getTransaction('0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d')
{
  blockHash: "0x159ff93dc61a32249f7f6c82fd0db65b8b45e33f416a29a047b2368edaf3508d",
  blockNumber: 17,
  from: "0xad30387c05b527a85f45186c2b8aab5e1af2f227",
  gas: 6721975,
  gasPrice: 100000000000,
  hash: "0x188d17d0ffdbd6ce41e2ca4a37b0e4ae01b909aa148417e48c960d38bd12cd6d",
  input: "0xfdacd5760000000000000000000000000000000000000000000000000000000000000002",
  nonce: 3,
  r: "0x97fbfded3651e150969343f31ac081bc08278c3a2d2c76f70881278f7334b8a0",
  s: "0x2d9a40b70557928d2abe0256f53ce97068db18c4198923e78e550e5f6f1a282e",
  to: "0x7b8d3f0ce869c8ffbfaff027a7a21fab6f0e179c",
  transactionIndex: 0,
  v: "0x38",
  value: 0
}

to为空的两笔交易是2个合约的实际部署。\
to不为空的两笔交易是更改Migration合约的状态,是消息调用类型的交易。

部署完成后,现在这个矿工账户0xad30387c05b527a85f45186c2b8aab5e1af2f227里就有2亿亿SB(这里单位是wei,注意token也是使用的wei,可以转换成ether单位展示)了。为什么是矿工账户?因为是TokenSB构造函数里这句话决定的:

balanceOf[msg.sender] = totalSupply;  

构造函数的创建是由矿工0xad30387c05b527a85f45186c2b8aab5e1af2f227完成的,即msg.sender当时是矿工,这个构造函数只执行一次。

交易在黄皮书里的定义就是一个状态转换函数,我们分析这个状态转换函数究竟做了些什么事情。

1、创建一个外部账户\
personal.newAccount('passwd'),即生成一个公钥私钥对。

2、“合约创建”

创建一个合约账户时使用了很多内在参数:(先不解释了,以后再说)\

sender (s), \
original transactor (o), \
available gas (g), \
gas price (p), \
endowment (v) \
i\
stack (e)

a ≡ B96..255(KEC(RLP((s, σ[s]n − 1))))

合约账户的地址是:仅由创建合约的sender和其nonce构成的RLP编码的Keccak Hash的右起160位。这里的96…255是说KEC的hash值会在这个位数范围内,也即地址位数。\
而之所以是nonce-1,是因为公式里用的是sender当前的nonce,而创建合约账户时的nonce一定是小1的。

运行项目

在truffle工程目录下执行

npm run dev

常见问题

领养的时候实际是发送交易,调用了eth_sendRawTransaction api。

Error: [ethjs-rpc] rpc error with payload {"id":7299823052815,"jsonrpc":"2.0","params":["0xf88605843b9aca0082f65a94c069c6502457c854f669746861712141ad81414080a48588b2c5000000000000000000000000000000000000000000000000000000000000000025a05ca4a04ef943c9383776ee4c39d6479ac739d470571dcfc842ef0bcfe3ec5f999f6b8966b830b7f0e03cd15c3dd660cd19fe5550196084519eed5a20c8880743"],"method":"eth_sendRawTransaction"} Error: invalid sender

解决答案是:truffle.js的network_id和genesis的chainId需要一样。

Solidity

IDE语法支持

  • 在IDE里安装soldity插件用于支持语法高亮。IDEA系列IDE直接搜索solidity安装。
  • Atom的插件安装,在Atom启动的情况下,使用命令安装:

    apm install linter
    apm install linter-solidity

编译器安装方式

  • 在本地安装solcjs这个solidity编译器(这种安装方式最简单)

    可以在js里引用模块、写编译方法,执行js对solidity编译。

    cnpm i -g solc

    也可以在控制台编译.sol文件,使用

    solcjs --abi xxx.sol
  • 或者mac上安装本地编译器(这种安装方式最费劲),编译器集成在solidity包里。

    brew update
    brew upgrade
    brew tap ethereum/ethereum
    brew install solidity
    brew linkapps solidity

    设好solidity/bin环境变量后,控制台编译使用

    solc --abi -o solcoutput xxx.sol
注意:geth1.6.0之后就不再集成solc了,所以geth控制台里已无法再编译合约。

web3

web3是一个js库,在js应用中可以通过以太坊节点提供的http RPC接口与以太坊节点交互。

https://github.com/ethereum/w...

geth --rpc

这个geth命令就是启用了HTTP JSON-RPC(go版节点默认rpc端口是8545,还可以用--rpccorsdomain设置跨域)。

下面是geth console里启用rpc的方法:

admin.startRPC(addr, port)

下面这些方法都有一个额外的默认参数block

  • eth_getBalance
  • eth_getCode
  • eth_getTransactionCount
  • eth_getStorageAt
  • eth_call

参数block可以取值{

  • HEX String - an integer block number
  • String "earliest" for the earliest/genesis block
  • String "latest" - for the latest mined block
  • String "pending" - for the pending state/transactions

}

web3接口可以批量请求,批量请求并不会更快,而主要是确保请求的串行处理。

项目是通过web3.js与以太坊进行交互的,比如通过web3对象获取当前玩家的以太坊账户并进行交易。

 $.getJSON('TokenSB.json', function (data) {
          var TokenArtifact = data;
          App.contracts.Token = TruffleContract(TokenArtifact);
          App.contracts.Token.setProvider(App.web3Provider);
      })

web3初始化

// 这里是判断否已存在web3,比如,如果是用户登录MetaMask连接到本网络,则web3是MetaMask的web3。
// MetaMask创建的账户由MetaMask维护,而导入的账户则每次登录MetaMask都需要重新导入。
// 否则就创建一个web3,这就可能需要自行实现钱包让用户登录了。
if (typeof web3 !== 'undefined') {
    App.web3Provider = web3.currentProvider;
} else {
    App.web3Provider = new web3.providers.HttpProvider('http://localhost:8545');
}

LevelDB

LevelDB只能被一个进程占用,当私链启用的时候,其他进程是不能访问的,比如LevelDB的某种客户端。

可以用以下工具访问本地LevelDB:
https://github.com/liderman/l...
前提是结束私链运行。

以太坊的数据库通过源码可知:
LevelDB实例加载的是$datadir/geth/chaindata这个目录。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值