1. 程式人生 > >【以太坊系列-006】ethereum solidity智慧合約在geth控制檯上的操作(mapping實踐)

【以太坊系列-006】ethereum solidity智慧合約在geth控制檯上的操作(mapping實踐)

   說明,本文基於已經部署好的etherum環境,在geth控制檯上操作以下命令。文中用到的命令,可以參考該系列的其他文件。

1、解鎖賬號

> personal.unlockAccount(eth.accounts[0], "lyh001", 300) # 300是解鎖時間,0表示沒有限制
> eth.defaultAccount=eth.coinbase; 

# 以上命令如果不執行,部署合約會出現 Error: invalid address

2、合約程式碼

pragma solidity ^0.4.21;

contract Coin{
    address public minter;
    mapping (address=> uint) public balances;

    event LogSend(address from, address to, uint amount);

    constructor () public {
        minter = msg.sender;
    }

    function min(address receiver, uint amount) public {
        if (msg.sender != minter) return ;
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit LogSend(msg.sender, receiver, amount);
    }

}

3、web3deploy程式碼的部署

var counterContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"minter","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"min","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"send","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogSend","type":"event"}]);
var counter = counterContract.new(
   {
     from: web3.eth.accounts[0], 
     data: '0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061044f806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806307546172146100675780631969cfb7146100be57806327e235e31461010b578063d0679d3414610162575b600080fd5b34801561007357600080fd5b5061007c6101af565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100ca57600080fd5b50610109600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506101d4565b005b34801561011757600080fd5b5061014c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610281565b6040518082815260200191505060405180910390f35b34801561016e57600080fd5b506101ad600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610299565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022f5761027d565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b5050565b60016020528060005260406000206000915090505481565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156102e55761041f565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fa343f361112b028dae2501770614271723be1d24c9f64fed2d4bd3ddf1c13e35338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15b50505600a165627a7a72305820d2b4835f6d840b8d0d7ae5d6dde7a8fb98b2bdb91239721f4d80f25a85efe8340029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

4、挖礦

(由於我們的環境沒有預設啟動挖礦功能,所以部署合約的時候,需要手動啟動挖礦)

miner.start(1); admin.sleepBlocks(1); miner.stop();

5、合約地址

合約部署好後,會返回一個合約地址

Contract mined! address: 0xe58069545e3d68d50c6c81dd67500c8e1bdc871a transactionHash: 0x75b840a222092abad73337ce50af77e1657a83fa0b665e5997d05d9de5793eb8

6、獲取餘額

我們可以看看當前賬戶的餘額

counter.balances(web3.eth.accounts[0])

7、存入資料

> counter.min(web3.eth.accounts[1], 2000)
"0xafd8f6b9aa60dc7c8d2dfe9af9a31880216d69b3087c186b4c74fb0d8b78de07"
> counter.min(web3.eth.accounts[0], 500)
"0x77a4419e9df227b5bac626b1527b2e653d96812080ebc55f20cbe3e11eca3632"
值不變
> counter.balances(web3.eth.accounts[0])
> counter.balances(web3.eth.accounts[1])
> eth.getTransaction("0xba10a306a2bdf36e678587592861de733b2302d761443da0d1f9762e1d179d80")

8、檢視待確定交易

> eth.getBlock("pending", true).transactions
> eth.blockNumber 
13

9、啟動挖礦
可以看到資料已經在第14塊中

> miner.start(1); admin.sleepBlocks(1); miner.stop(); 
null
> eth.blockNumber  
16
> eth.getBlock(14)
{
  difficulty: 131072,
  extraData: "0xd883010813846765746888676f312e31302e33856c696e7578",
  gasLimit: 4236618346,
  gasUsed: 87568,
  hash: "0xdfe530638d7684b7e6e4b7b10df4f157e2ee0fe1229db04210fe7cf22b40d1cf",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x168009d76448d7bfc51541442165132ba2cbe10b",
  mixHash: "0xb3fa4463cf9d34bbffbd2f34071f7afdb4d6fe8288bbde11116debea385a51bd",
  nonce: "0x74890e0167bc4221",
  number: 14,
  parentHash: "0x6c095a755cb8154da04fc25e2545dc1babbeb5f7a041b94eb37224fba188414f",
  receiptsRoot: "0x9cd70f3c28c0bfda42495100372d793135beac33f961d2352037096b124aa00a",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 884,
  stateRoot: "0xa7273a2d0a6a6ed8fb76ee8fd0d37a592274d115efedf8c4d84dad11c25b166f",
  timestamp: 1542600787,
  totalDifficulty: 1836288,
  transactions: ["0xafd8f6b9aa60dc7c8d2dfe9af9a31880216d69b3087c186b4c74fb0d8b78de07", "0x77a4419e9df227b5bac626b1527b2e653d96812080ebc55f20cbe3e11eca3632"],
  transactionsRoot: "0xc8be70094149d4f458607b87f17e80a4aec76de2a02ef78490b35503a0880fdb",
  uncles: []
}

10、獲取最新的值
發現值已經變成2000

> counter.balances(web3.eth.accounts[0])
> counter.balances(web3.eth.accounts[1])

11、從 eth.accounts[0] 轉入到 eth.accounts[1]中

> counter.balances(web3.eth.accounts[0])
> counter.balances(web3.eth.accounts[1])
11、從 eth.accounts[0] 轉入到 eth.accounts[1]中
> personal.unlockAccount(eth.accounts[0], "lyh001", 300)
true
> counter.send(web3.eth.accounts[1], 10) 
"0x2f5837a2248596d304ee64b8e15bf2e18a47ef8e56df55384b63dee8cd23a95c"
> counter.balances(web3.eth.accounts[0])
500
> counter.balances(web3.eth.accounts[1])
2000
> miner.start(1); admin.sleepBlocks(1); miner.stop();
null
> counter.balances(web3.eth.accounts[0])
490
> counter.balances(web3.eth.accounts[1])
2010

12、連續轉出超過賬戶的最大值

> counter.balances(eth.accounts[0])
490
> counter.balances(eth.accounts[0])
490
> personal.unlockAccount(eth.accounts[0], "lyh001", 300)
true
> counter.send(eth.accounts[1], 200)
"0xfc2e1912155dcdf5f1fc4ef6d13c77950e924d1dec999fcff05e7733b619af4d"
> counter.send(eth.accounts[1], 200)
"0x8aa7f6548e588d679c3b576df4646157bbc165a45596e70e083bb9f14762ec13"
> counter.send(eth.accounts[1], 200)
"0x01f47a065ad55fac3e18d265d7e097d85e1db7b1b39b45e45c2e058da5ea1dd2"
> counter.balances(eth.accounts[0])
490
> miner.start(1); admin.sleepBlocks(1); miner.stop();
null
> eth.blockNumber
18
> eth.getBlock(18)
{
  difficulty: 131136,
  extraData: "0xd883010813846765746888676f312e31302e33856c696e7578",
  gasLimit: 4220093288,
  gasUsed: 0,
  hash: "0x819e858484f1d816d7da7faa0c8b0116a19bf2cf9a40767995f8b89dd92819b2",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x168009d76448d7bfc51541442165132ba2cbe10b",
  mixHash: "0xa2f29c2827068bdc42e3a10d5509e4fd223fe9b66d16c46fb0784e2c9400db45",
  nonce: "0x675deb25dd84759f",
  number: 18,
  parentHash: "0x6a72c6d0e17f3dd11a15805fac338007cc6b0ad1c3006da9639d6d22b259ddca",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 537,
  stateRoot: "0x4987469c797c881c4e0d2b72ea41de816772654810e02147ab88e8920e6bfc07",
  timestamp: 1542605845,
  totalDifficulty: 2360704,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
> eth.getBlock(17)
{
  difficulty: 131072,
  extraData: "0xd883010813846765746888676f312e31302e33856c696e7578",
  gasLimit: 4224218500,
  gasUsed: 95036,
  hash: "0x6a72c6d0e17f3dd11a15805fac338007cc6b0ad1c3006da9639d6d22b259ddca",
  logsBloom: "0x00000000000000000000000080000000000000000000000000000000000000000000000200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000",
  miner: "0x168009d76448d7bfc51541442165132ba2cbe10b",
  mixHash: "0x22cbde953fc5b73f9121e460e6503cd01a473af600d2aa8d0a13576d3837b58b",
  nonce: "0x055b92e22aed5261",
  number: 17,
  parentHash: "0x327825cead033db4ef904b689babb38aefef3ec07677c7f48ebffae1503c387a",
  receiptsRoot: "0x8da47da388ef2620a0125098244be4e567ee54aec078069c1dfddf0c4cbc5f97",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 1055,
  stateRoot: "0xaff0ca967e1c2e9e597cae0c48864a44f755fd0abca9f0a70ddc1e7f49384340",
  timestamp: 1542605844,
  totalDifficulty: 2229568,
  transactions: ["0xfc2e1912155dcdf5f1fc4ef6d13c77950e924d1dec999fcff05e7733b619af4d", "0x8aa7f6548e588d679c3b576df4646157bbc165a45596e70e083bb9f14762ec13", "0x01f47a065ad55fac3e18d265d7e097d85e1db7b1b39b45e45c2e058da5ea1dd2"],
  transactionsRoot: "0x2a1231ce30db78b339fe39bc519d97eb529fd9a5d1ccabe9f458293a1de63603",
  uncles: []
}
> counter.balances(eth.accounts[0]) 
90

雖然三個交易都在塊中,但是實際上當餘額不夠的時候,資料並沒有修改。

最後剩餘的是90。

13、設定監聽事件

var myEvent = counter.LogSend();
myEvent.watch(function(err, result){
    if (!err){
        console.log(result)
    } else {
        console.log(err);
    }
    myEvent.stopWatching();
});

轉賬:
> personal.unlockAccount(eth.accounts[0], "lyh001", 300)
> counter.send(eth.accounts[1], 1)
> miner.start(1); admin.sleepBlocks(1); miner.stop();
此時,可以看到有相關的交易事件輸出
> counter.balances(eth.accounts[0])

14、通過合約地址,呼叫合約

1) 通過abi和合約地址取得智慧合約的例項

> var abi = [{"constant":true,"inputs":[],"name":"minter","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"min","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"send","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogSend","type":"event"}]
> var address = "0xe58069545e3d68d50c6c81dd67500c8e1bdc871a"
> var metacoin = web3.eth.contract(abi).at(address);

2) 轉賬並查詢餘額

metacoin.balances(web3.eth.accounts[0]) 
> metacoin.balances(web3.eth.accounts[1]) 
> 
> eth.defaultAccount=eth.coinbase;
> personal.unlockAccount(eth.accounts[0], "lyh001", 300)
> metacoin.send(eth.accounts[1], 1)
> miner.start(1); admin.sleepBlocks(1); miner.stop();

最後可以看到餘額變了

3) call與sendTransaction方式

> personal.unlockAccount(eth.accounts[0], "lyh001", 300) 
true
> metacoin.send.sendTransaction(eth.accounts[1], 1, {from:eth.accounts[0]})
"0x9801c14de31cac7e6abafadbaf2f02a5fe3890714f47db879c3effa91e1a9905"
> miner.start(1); admin.sleepBlocks(1); miner.stop();
> metacoin.balances(eth.accounts[0])
86
> metacoin.balances.call(eth.accounts[0])
86