以太坊互動
區塊鏈中級.以太坊開發
From:JamesZou & 傳智播客研究院 & 傳智播客區塊鏈
一. 賬戶
1. 以太坊賬戶
賬戶分兩種:外部賬戶 和 合約賬戶
1.1 外部賬戶
-
使用者使用的賬戶,包含 地址和私鑰
-
操作
- 檢視餘額
- 可以轉賬交易
- 呼叫合約
-
特點:
- 建立不需要網路,本地生成(錢包生成,自己生成,紙錢包等)
- 被私鑰控制
- 僅有餘額,沒有程式碼
- 可以傳送交易(transaction)
- 每個以太坊網路中都可以使用,但是金額互相獨立,只要符合以太坊網路規則即可
1.2. 合約賬戶
-
由外部賬戶建立的智慧合約例項,部署後返回一個地址,這個地址就是合約賬戶(有金額,有程式碼邏輯)
-
操作:
- 由外部賬戶傳送訊息啟用合約賬戶的程式碼
- 接收轉賬,向外轉賬
- 呼叫其它合約
-
特點
- 擁有 ether 餘額
- 含有執行程式碼
- 程式碼僅在該合約地址發生交易或者收到其他合約傳送的資訊時才會被執行
- 擁有自己的獨立儲存狀態,且可以呼叫其他合約
注意:合約賬戶由外部賬戶或合約程式碼邏輯進行建立,一旦部署成功,只能按照預先寫好的合約邏輯進行業務互動,不存在其他方式直接操作合約賬戶或更改已部署的合約程式碼。
-
合約原始碼與例項
合約是“類”,可以建立很多“例項物件”
let a = new Dog();
let b = new Dog();
2.2 Ropsten
3.轉賬
3.1 對比
-
對比
- 傳統銀行:在不同的網路裡面,同一個賬戶的金額可能不同
銀行 | 開戶人 | 金額 | 取款密碼(儲存在銀行) |
---|---|---|---|
招商銀行 | 華仔 | 10000元 | 123456 |
建設銀行 | 華仔 | 20000元 | 654321 |
農業銀行 | 華仔 | 15000元 | 235677 |
中國銀行 | 華仔 | 30000元 | 876644 |
-
以太坊網路
- 不同的銀行相當於不同的區塊鏈網路, 同一個開戶人在不同銀行的存款是不一樣的。
- 在傳統中心化網路裡面,密碼是儲存在銀行的中心化的伺服器裡面的。
- 不同的區塊鏈網路, 擁有相同的賬戶資訊. 密碼是儲存在使用者端(private key)。
- 不同之處是各個網路無法互相轉賬,而傳統銀行是可以的。
區塊鏈網路 | 賬戶地址 | 金額 | 私鑰(取款用,儲存在使用者端) |
---|---|---|---|
main network | 0xd5a2… | 10000 ether | 0x358b35069… |
Ropsten network | 0xd5a2… | 20000 ether | 0x358b35069… |
kovan network | 0xd5a2… | 15000 ether | 0x358b35069… |
rinkeby network | 0xd5a2… | 30000 ether | 0x358b35069… |
- 演示轉賬
3.2 幾個概念
-
gas(汽油)- 油耗
由於以太坊是公鏈,所有人都可以自由的參與,為了防止垃圾資料充斥網路,所以以太坊上規定每一個操作都是要有成本的,這個成本由
gas
來體現,你要轉賬,部署智慧合約,呼叫智慧合約方法,都要消耗一定數量的gas。單位 : 1 eth = 10 ^18 wei
-
gasprice(汽油價格) - 油價
雖然操作消耗gas,但是最終真正花的還是eth,所以就有一個轉換率的問題,gasprice就是起到一個匯率的作用,它代表的是一個gas值多少eth,gas*gasprice就是最終的手續費,也就是從你賬戶扣除的eth。
這種設計就可以保證使用者在以太坊上的操作的手續費不會隨著eth的價格而發生劇烈的變動(例如:如果eth漲,那麼可以調低gasprice來降低手續費),
-
gaslimit(汽油上限)- 油箱
以太坊規定,每筆交易的gas最少21000,礦工可以調整這個值,所以最終的花費的gas是不確定的,所以以太坊就設定了gaslimit,這個代表的是最多給曠工這麼多gas(防止自己寫的合約裡面有死迴圈),如果最終使用的gas少於這個gaslimit,剩餘的還會返給你的,但是如果你的gaslimit不足以支付這次交易,那就是不會退回的,並且交易也就失敗了,轉賬的額度也是回不來了,所以你轉賬設定的limit一定要大於21000。
3.3 轉賬流程
-
解釋點下確定按鈕的流程:
1.點選submit
2.地址通過get請求發給了伺服器
3.web3.js 創造了一個轉賬 (translation) (什麼是轉賬,轉賬包含什麼資訊)
nonce,to,value,gas,gaslimit,密碼學相關 有privatekey生成
4.為什麼需要等待, 後臺server傳送translation 到rinkeby網路
5.等待挖礦,30秒左右
6.後臺伺服器把成功資訊反饋給前端
3.4 轉賬具體流程
- translation提交給一個node(如何修改node,選擇node?)
- node可能在某個時間內收到很多個translation
- node對translation排序,挖礦
- node算好nonce就會廣播給全網
- 最先算出nonce的node會得到挖礦獎勵
4.區塊時間
4.1 區塊時間原理
- 區塊時間 算 0000 開頭是不科學的. 是簡易演算法.
- 實際演算法是計算一個hash 小於某種特殊值.
- hash值的範圍 0 ~ 1.15x10^77 跟搖色子一樣.
4.2 區塊時間詳解
- blocktime = time to find a solution
-
難度係數
<1000 --> 20s
<10000 --> 5s
<5000 -->17s
<4000 -->15s
二. Solidity
1. Solidity簡介
- 以太坊編寫智慧合約的語言,副檔名 .sol
- 強型別程式語言(變數型別有多種,例如int byte bool struct 等,型別之間轉換時需要強轉)
- 與javascript類似(但是JavaScript是弱型別的語言,一個var關鍵字自動識別資料型別)
- 一堆坑
- api手冊 -》 Solidity中文手冊
2.開發環境
-
Mist錢包 - 不好用,問題較多
-
Remix線上程式設計
- 特點:訪問連結、方便除錯、依賴網路
- 地址:remix.ethereum.org
-
Remix本地環境
-
特點:方便,相對穩定
-
問題:偶爾無法正常載入編譯器,需要完全斷網才能載入
-
安裝
npm install remix-ide -g
-
啟動服務:
remix-ide
-
3.第一個合約
- 智慧合約概覽
每個合約中可包含:
- 狀態變數(State Variables) : 就是成員變數,這個資料是上鍊的。
- 函式(Functions)
- 函式修飾符(Function Modifiers)
- 事件(Events)
- 結構型別(Structs Types)
- 列舉型別(Enum Types)
- mapping(key => value) 如: map[1] = 2
- 便寫一個 接收訊息的方法
pragma solidity ^0.4.25;
contract Inbox{
string public message;
function getMessage() public constant returns(string){
return message;
}
function setMessage(string newMessage) public{
message = newMessage;
}
}
- 語法解析
4.編譯合約
4.1 原理
-
使用remix,由高階語言變成機器語言
- solidity —> bytecode - 機器語言,區塊鏈系統讀取
- solidity —> ABI (application binary interface) - 方便程式設計師呼叫
-
圖示
4.2 bytecode
6080604052610410806100136000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063368b87721461005c578063ce6d41de146100c5578063e21f37ce14610155575b600080fd5b34801561006857600080fd5b506100c3600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101e5565b005b3480156100d157600080fd5b506100da6101ff565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011a5780820151818401526020810190506100ff565b50505050905090810190601f1680156101475780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016157600080fd5b5061016a6102a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101aa57808201518184015260208101905061018f565b50505050905090810190601f1680156101d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101fb92919061033f565b5050565b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102975780601f1061026c57610100808354040283529160200191610297565b820191906000526020600020905b81548152906001019060200180831161027a57829003601f168201915b5050505050905090565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061038057805160ff19168380011785556103ae565b828001600101855582156103ae579182015b828111156103ad578251825591602001919060010190610392565b5b5090506103bb91906103bf565b5090565b6103e191905b808211156103dd5760008160009055506001016103c5565b5090565b905600a165627a7a723058201486092ea8103d4816d5aa6177b30372d94ec850544312021159c20f3b7a505b0029
4.3 abi
-
(application binary interface,應用二進位制介面)
json格式的描述檔案:
[
{
"constant": false,
"inputs": [
{
"name": "newMessage",
"type": "string"
}
],
"name": "setMessage",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getMessage",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "message",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"payable": true,
"stateMutability": "payable",
"type": "constructor"
}
]
4.4 呼叫
以太坊為了方便智慧合約的開發、學習和測試,開啟了幾條全新的區塊鏈,與主網路特性相同,但測試網路中的以太幣價值更低,也更容易得到。這樣不至於在主網路上開發出現 BUG 造成以太幣的損失。
當然我們也可以搭建私有的測試網路,不過區塊鏈的去中心化特點,需要更多的節點執行才能達到理想效果,好在以太坊有公開的測試網路,而我們接入也更容易。
4.4.1 執行環境
-
vm
- account 虛擬賬戶5個,每個賬戶預設100eth。
- 沒挖礦,直接返回結果,便於開發測試
-
網頁環境
- injected web3
- 與metamask結合緊密
-
自定義環境
- web3 provider
- 連結自己本地啟動的區塊鏈環境(truffle,ganache,私有鏈等)
4.4.2 部署合約
-
部署成功後返回合約地址,如:
0x27baf63ea560973e9f8f333a39239967f96c5703
-
部署合約也是一筆交易,只不過不用填寫
to
欄位,且資料輸入
欄位填寫為合約位元組碼。
- 檢視瀏覽器
4.4.3 呼叫合約
-
手動呼叫,我們使用手動呼叫,呼叫合約的操作分為兩種型別
- send:所有改變區塊鏈資料狀態的叫做是send操作,相當於發起一筆交易,特點是花錢,大約10s~30s(礦工確認)返回結果。
- call:所有讀取區塊鏈合約資料的操作成為call操作,它的特點是迅速返回,無需花錢
-
通過web3呼叫
4.4.4 對比總結
對比項 | 函式呼叫call | 函式呼叫 send transaction |
---|---|---|
資料狀態 | 不修改智慧合約的資料 | 修改智慧合約的資料 |
返回值 | 函式可以返回資料 | 函式不能返回資料, 因為函式需要花時間執行 |
執行速度 | 立刻執行 | 需要十幾秒才能執行完畢,返回值是transaction的hash |
成本 | 免費 | 要花錢 錢!!! |
4.5 解構函式
function destroy() {
//解構函式,銷燬當前合約,並把它所有資金髮送到給定的地址
//1.將合約裡的 餘額 轉給 傳入的地址
//2.標記當前合約 為 銷燬狀態
selfdestruct(msg.sender);
}
呼叫之後,合約仍然存在於區塊鏈之上,但是函式無法被呼叫,呼叫會丟擲異常。