本文实现以下目标:
- 搭建一条以太坊私链
- 用企业级开发方式开发、部署一个项目
- 分析truffle执行过程
- 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_ID Chain(s) 1 Ethereum mainnet 2 Morden (disused), Expanse mainnet 3 Ropsten 4 Rinkeby 30 Rootstock mainnet 31 Rootstock testnet 42 Kovan 61 Ethereum Classic mainnet 62 Ethereum Classic testnet 1337 Geth 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这个目录。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。