以太坊智能合约开发入门

1、进入以太坊开发控制台(开发环境):
geth console --datadir "~/electrumx/ethdev" --dev 2>>eth.log
以太坊智能合约开发入门_第1张图片

通过tail -f eth.log查看日志:
以太坊智能合约开发入门_第2张图片

2、查看当前有哪些账户
eth.accounts

默认会有一个coinbase账户(挖矿账户),默认挖矿会挖到这个账户里。

3、创建一个新的账号
personal.newAccount('密码')
以太坊智能合约开发入门_第3张图片
我们这里除了coinbase账户,又创建了两个账户

4、可以把账户赋值给某一个变量,同时查询账户中的余额
以太坊智能合约开发入门_第4张图片

可以看到新加的两个账户中的以太币都是0.但coinbase账户默认已经有了余额。

5、在geth控制台中启动挖矿:
miner.start()
以太坊智能合约开发入门_第5张图片

执行挖矿返回的是null,日志中输出开始挖矿,并提交了挖矿的工作量,但同时也有提示区块处理失败,错误信息显示等待交易。(在geth1.7.3之后,挖矿的工作量确认需要有交易产生的时候才能确认),我用到的geth是1.8.3
以太坊智能合约开发入门_第6张图片

使用miner.stop()停止挖矿


对比了挖矿前后,coinbase账户里面的余额并没有变化。

6、那我们来尝试发起一笔交易看看会发生什么

从coinbase用户向user1转账
eth.sendTransaction({from: user1,to: user2,value: web3.toWei(3,"ether")})
交易地址:0xba9419f284c4e473597363a37b4e6fb399dac5f291b7682c638a5f9f872354bf
输出日志

如果出现账户锁定的提示,需要先解锁账户
personal.unlockAccount(user1, "123456")
以太坊智能合约开发入门_第7张图片

从user1向user2转账

7、再次查看以太币转移后的user2账户余额
但是发现user2的账户还是为0.这是因为没有矿工来挖矿处理。根据区块链的概念,我们知道,每次交易的确认,其实都是需要挖矿的,也就是被其他矿工共识确认,然后才能加入区块链的账本中。

好,我们执行“miner.start()”开始挖矿,
以太坊智能合约开发入门_第8张图片

注意,前面挖矿操作因为没有交易,没有成功,这次有交易的情况下挖矿miner.start()虽然返回的是null,但日志中出现了挖矿的记录。

再次查看user1中的余额,3以太币到账

不过奇怪的是转账并没有使coinbase里面的余额减少,挖矿似乎也没有增加。

eth.blockNumber变为1了
以太坊智能合约开发入门_第9张图片

试试把挖矿地址设置成user2
以太坊智能合约开发入门_第10张图片

再增加一个账户


从user1向user3转2个以太币
以太坊智能合约开发入门_第11张图片

解锁账户
以太坊智能合约开发入门_第12张图片



交易号:0xad59d8ec919c253e3246e2eb0fe7d6c8cb8011553a6138cfe2957a16f47a865e

再次查看各个账户余额情况


user3收到了2以太币,不过user1里面不足1以太币,而user2原本是0,现在多出了21000,注意前面我们已经把旷工地址设成了user2,所以挖矿所得计入了user2的账户中,而这个挖矿所得正好是user1转给user3所支付的gas费用(如果把user1和user2中的相加正好是1以太币)。

再做一次测试,user3转1以太币给user1


交易号:0x4016fe195db95b1b303ecf14d6cad24ca8b2e707bb5ffd8be9ed55e28656e598

执行转账后余额

以太坊智能合约开发入门_第13张图片

日志中出现的挖矿记录
以太坊智能合约开发入门_第14张图片

以上操作都是在挖矿开启miner.start()开启的状态下执行的。

如果停掉挖矿的话,转账是不能成功的,如果在挖矿停掉的情况下发生了转账,则需要在挖矿开启之后才能到账。

停掉挖矿后,user1再转1以太币给user3


日志可见提交了交易,但并没有产生挖矿的操作,用户账户余额也未发生变化。当前区块数:

为什么是3,自此我们执行了4次交易,分别是:
1、coinbase_user转账3以太币给user1
交易号:0xba9419f284c4e473597363a37b4e6fb399dac5f291b7682c638a5f9f872354bf
2、user1转账2以太币给user3
交易号:0xad59d8ec919c253e3246e2eb0fe7d6c8cb8011553a6138cfe2957a16f47a865e
3、user3转账1以太币给user1
交易号:0x4016fe195db95b1b303ecf14d6cad24ca8b2e707bb5ffd8be9ed55e28656e598
4、user1转账给1以太币给user3(该笔转账在挖矿停掉后执行,还未被确认)
交易号:0xd06a72f2fdf0a81623491788fa78ce680187019e6e2ab4b9d704a22560afde6b

我们再重新开启挖矿看看会发生什么?

以太坊智能合约开发入门_第15张图片

挖矿重新开启后并没有变化,从日志中看出还需要再有交易发生才会处理,那我们再尝试第五笔转账交易

第五笔交易,按第四笔交易的结果,user3应该会接收到user11以太币的转账,所以user3的账户应该是大于1以太币,我们如果再让user3转账1以太币给user1,则第四笔和第五笔交易产生的gas费用应该是42000加上user2本身有的42000,user2应该是84000

以太坊智能合约开发入门_第16张图片

但实际操作过程中,user3因为还没接收到user1的转账,余额是不足1以太币的,出现了gas和余额不足的问题。尝试把toWei中的ether单位换成Mwei

以太坊智能合约开发入门_第17张图片

第5笔交易

交易号:0xe657e5b4a53dc72371837486b68edb9dce35d9ed3e20f9e893a2068dcbd604e6

以太坊智能合约开发入门_第18张图片

但交易执行后,并没有预想那样执行,出现了Block sealing failed err=unauthorized的错误提示,不能正常执行挖矿。换成coinbase_user也不行。

输入exit退出后,重新进入又恢复正常

geth console --datadir "~/electrumx/ethdev" --dev 2>>eth.log

查看区块数为4

但我们之前转账有5笔,我们根据交易号来查询下交易信息

1、coinbase_user转账3以太币给user1
交易号:0xba9419f284c4e473597363a37b4e6fb399dac5f291b7682c638a5f9f872354bf
以太坊智能合约开发入门_第19张图片
2、user1转账2以太币给user3
交易号:0xad59d8ec919c253e3246e2eb0fe7d6c8cb8011553a6138cfe2957a16f47a865e
以太坊智能合约开发入门_第20张图片
3、user3转账1以太币给user1
交易号:0x4016fe195db95b1b303ecf14d6cad24ca8b2e707bb5ffd8be9ed55e28656e598
以太坊智能合约开发入门_第21张图片
4、user1转账给1以太币给user3
交易号:0xd06a72f2fdf0a81623491788fa78ce680187019e6e2ab4b9d704a22560afde6b
以太坊智能合约开发入门_第22张图片
5、user3转账1 Mwei给user1
交易号:0xe657e5b4a53dc72371837486b68edb9dce35d9ed3e20f9e893a2068dcbd604e6
以太坊智能合约开发入门_第23张图片
可以看到在之前在出现Block sealing failed err=unauthorized的错误提示重新进入geth之后,第4笔和第5笔已经生效了。

各个账户余额的情况
以太坊智能合约开发入门_第24张图片
这里user2的余额没有变化,估计是因为出现Block sealing failed err=unauthorized重启之前把挖矿账号改成了coinbase_user.所以看到user2中余额并没有变化。在实际测试中,为了看到比较好的效果,建议通过miner.setEtherbase()改成普通用户比较好看到实际效果。

测试智能合约:

在geth中编写一个智能合约:
pragma solidity ^0.4.0;

contract test {  
    function multiply(uint a) public returns(uint d) {  
        return a * 7;   
    }   
}  

在geth中执行如下:
source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"

然后编译该合约:

contract = eth.compile.solidity(source).test

编译后的结果如下:

以太坊智能合约开发入门_第25张图片

出现错误,查询之后得知,在geth1.6之后此方法被删除了。现在的做法,使用Remix在线工具编译。具体做法是:
1. 在浏览器中打开Remix工具,网址为: https://ethereum.github.io/browser-solidity 或者 http://remix.ethereum.org/
2. 点击左上角+,新生成一个文件test.sol;
3. 将之前在本地写的test.sol中的代码拷贝到此文件中,如图所示
以太坊智能合约开发入门_第26张图片

点击compile -> start to compile,下面会有一些警告,不用管它,然后点击Details按钮,拷贝json数据
以太坊智能合约开发入门_第27张图片

json数据如下:

[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"type":"function","stateMutability":"nonpayable"}]

contract code:
0x6060604052346000575b60a4806100176000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603c575b6000565b3460005760546004808035906020019091905050606a565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a72305820fc29182ab23ed8e9069c7ad64027ee1118135406673bd20c7dd58fab3b9593890029

部署合约到私有链:

abi = [{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"type":"function","stateMutability":"nonpayable"}]
以太坊智能合约开发入门_第28张图片

创建合约:
multiplyContract = web3.eth.contract(abi)
以太坊智能合约开发入门_第29张图片

获得合约实例(data后为前面获取的contract code):
multiply=multiplyContract.new({from:user1,data:"0x6060604052346000575b60a4806100176000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603c575b6000565b3460005760546004808035906020019091905050606a565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a72305820fc29182ab23ed8e9069c7ad64027ee1118135406673bd20c7dd58fab3b9593890029"})

执行前先解锁user1
以太坊智能合约开发入门_第30张图片

注意:部署合约的过程实际也是由创建合约的账户发送的一笔交易,需要挖矿进行确认

与合约交互:
获取合约对象
MyContract = eth.contract(abi)
以太坊智能合约开发入门_第31张图片

实例化合约:
myContract = MyContract.at(multiply.address)
以太坊智能合约开发入门_第32张图片

调用合约:
myContract.multiply.call(5)

不过得到的结果是0,正确应该是35。暂时未知原因。


继续解决昨天未解决的问题。为了更加直观,新增了一个新的用户user4作为挖矿账户。
以太坊智能合约开发入门_第33张图片

并且在挖矿停止情况下尝试部署合约

在Browser-solidity测试和检查合约代码:
http://remix.ethereum.org/

新建test.sol
以太坊智能合约开发入门_第34张图片

在Setting标签下可以查看当前的solidity的版本,并且要和代码框中的版本一致。并对之前合约代码做了一些修改。
pragma solidity 0.4.23;

contract test {  
    function multiply(uint a) public returns(uint d) {  
        return a * 100;   
    }   
}  
以太坊智能合约开发入门_第35张图片
点击下拉框,可以选择不同的版本,包括还未成熟的最新构建版本,或者是之前的版本等。 个人强烈建议,尽量选择release版本,如下图所示的这些:
以太坊智能合约开发入门_第36张图片

点击Create创建合约
以太坊智能合约开发入门_第37张图片

点击Create可以在Browser-solidity中创建并调用所创建的智能合约。

点击Details查看创建详情,可以看到实际创建所消耗的Gas。

transaction cost    102687 gas 
execution cost  37487 gas

输入数字,点击multiply(multiply是合约中定义的函数名),就可以进行合约的调用了。同样调用也会消耗gas,在详情页可以看到具体gas消耗数量

以太坊智能合约开发入门_第38张图片

Compile标签 & 编译合约

切换到Compile标签,点击Publish on Swarm
以太坊智能合约开发入门_第39张图片

提示成功之后,在左侧多出swarm菜单栏,可以看到合约编译结果
以太坊智能合约开发入门_第40张图片


点击Detail按钮,找到WEB3DEPLOY
以太坊智能合约开发入门_第41张图片

将 Browser-solidity编译后的合约部署到Geth
直接复制WEB3DEPLOY的代码到Geth console执行

from代表合约由哪个账户生成,哪个账户生成,则生成所需的gas就需要该账户承担,默认为eth.accounts[0],这里为了方便看到实际效果,from: web3.eth.accounts[0], 改成from: user1,
以太坊智能合约开发入门_第42张图片
解锁user1账户

发送部署合约的交易
以太坊智能合约开发入门_第43张图片

输入test可以看到合约的一些信息

以太坊智能合约开发入门_第44张图片
交易号:0x1a893bbccf44258417439b7e670ba8247eefb1f2cc4e0ef162ba2aa0609ec435

查看本地交易池中待确认的交易
以太坊智能合约开发入门_第45张图片

查看待确认交易的详情
以太坊智能合约开发入门_第46张图片
由于交易还未确认,所以所属区块为null,blockNumber: null。

调用合约
通过test.multiply.call调用:

出现TypeError: Cannot access member 'call' of undefined的错误,是因为我们没有挖矿,之前提到过,如果停止挖矿,是不能进行转帐和智能合约的部署。

重新启动挖矿,等待一段时间,调用合约,就可以输出正确的值了。
不过在实际操作过程中,又出现了区块处理错误的提示,导致一直不成功。(暂时不知道这个问题出现的原因是什么)。只要从一开始开启了挖矿的话就不会出现这个问题。

关掉geth console重新进入之后,会自动处理刚才的智能合约交易
以太坊智能合约开发入门_第47张图片
查看之前未确认的交易详情:
交易号:0x1a893bbccf44258417439b7e670ba8247eefb1f2cc4e0ef162ba2aa0609ec435
以太坊智能合约开发入门_第48张图片
已经处理,在第十二区块上。

以太坊智能合约开发入门_第49张图片
确认挖矿开起的情况下,将挖矿账户设为了user4,继续执行前面合约的操作测试。


挖矿操作开启的时候,创建和实例化合约的时候会自动被挖矿确认,可以看到日志提示在第十三号区块成功创建。

调用合约
user1最初的余额为1000000000000418000,现在为1000000000000212626,差额205374,我这里实验过程中是创建了两次,平均下来每次102687gas,和前面创建细节里面transaction cost 102687 gas正好一致。这个钱到哪里去了呢?挖矿账户因为设置成了user4,我们可以看到在user4里正好增加了102687,不过还有102687应该是到了coinbase_user账户,因为之前出现问题,我重新进入geth console是用的coinbase_user做的第一个挖矿账户。
同样,我们调用合约,成功执行。


部分参考:
https://www.jianshu.com/p/91d775d20599


你可能感兴趣的:(区块链开发,以太坊,ethereum,智能合约,区块链,快速开发入门)