在本教程中,咱們使用 node.js,因此咱們首先從安裝依賴關係開始。node
$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3
複製代碼
而後建立文件 tx.js
,請求依賴關係。git
var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
var util = require('ethereumjs-util');
var tx = require('ethereumjs-tx');
複製代碼
首先咱們從理解一個私鑰開始。以太坊經過公鑰加密進行受權。具體來講,用橢圓曲線數字加密算法,經過 secp256k1 標準生成公鑰。除了有一些限制外,私鑰只是一個隨機的 256 位的數。例如:github
var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
複製代碼
經過私鑰導出相應的公鑰:web
var publicKey = util.bufferToHex(util.privateToPublic(privateKey));
複製代碼
若是你輸出公鑰,能夠看到下面的 16 進制數:算法
0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27
複製代碼
與私鑰相關聯的以太坊地址是用相應公鑰進行 SHA3-256 (Keccak) 哈希運算後獲得的後 160 位。npm
var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
//0x53ae893e4b22d707943299a8d0c844df0e3d5557
複製代碼
正如你看到的,多個私鑰能夠有相同的地址。一個以太坊帳戶與一個地址相關聯,並且每一個地址都有如下屬性:api
nonce
:輸出交易的次數,從 0 開始bash
balance
:帳戶中的以太幣數網絡
storageRoot
:與帳戶存儲相關聯的哈希值ide
codehash
:控制帳戶的代碼的哈希,若是它是空的,那麼就是一個正常帳戶,可以經過私鑰訪問的,不然,它就是一個智能合約,其交互受到代碼的控制
接下來咱們看一下交易,交易有 6 個輸入域:
nonce
:輸出交易的次數,從 0 開始
gasPrice
:交易中花費的單位 Gas 的價格
gasLimit
:處理交易容許花費的最大 Gas 量
to
:交易發送到的帳戶,若是是空,交易就會建立合約
value
:發送的以太幣的量
data
:能夠是任意的消息或合約函數調用或建立合約的代碼
一個發送 1000wei 以太而且留下消息 0Xc0de 的交易能夠被構造以下:
var rawTx = {
nonce: web3.toHex(0),
gasPrice: web3.toHex(20000000000),
gasLimit: web3.toHex(100000),
to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
value: web3.toHex(1000),
data: '0xc0de'
};
複製代碼
注意, from
地址並無指定,在私鑰簽署後,它會從簽名中提取。簽署交易:
var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');
var transaction = new tx(rawTx);
transaction.sign(p);
複製代碼
而後交易就能夠發送到網絡上,並且能經過一個 256 位的交易 ID 進行追蹤。這個交易能夠在 Etherscan 中查看。交易 ID 是交易的哈希值
console.log(util.bufferToHex(transaction.hash(true)));
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
複製代碼
接下來,咱們看一下指什麼構成了函數調用的數據。以這次合約交易數據爲例:
console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
複製代碼
爲了知道調用的是哪一個函數,必須提早知道合約的全部的函數,才能建立哈希表。前 32 位 a9059cbb
是函數哈希的前 32 位。在當前狀況下,函數爲 transfer(address _to, uint256 _value)
,它的哈希爲:
console.log(web3.sha3('transfer(address,uint256)'));
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
複製代碼
接下來是參數,每一個 256 位,因此當前狀況下 address 是:
0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e
複製代碼
uint256 是:
0x000000000000000000000000000000000000000000000000d02ab486cedbffff
複製代碼
接下來,如上所述,經過省略 to
域,能夠創建一個合約。可是如何肯定合約地址呢?以此交易爲例:
console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
//0x950041c1599529a9f64cf2be59ffb86072f00111
複製代碼
合約地址是發送者地址哈希值的後 160 位,並且 nonce
能夠提早肯定。對於這個交易來講,發送者和 nonce
能夠在下列代碼中發現:
var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
console.log(contractTx.from);
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
console.log(contractTx.nonce);
//0
複製代碼
因此合約地址是:
console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
//0x950041c1599529a9f64cf2be59ffb86072f00111
複製代碼
如今咱們算是搞清楚了這些十六進制數的含義!
以太坊和智能合約具備打破許多行業的巨大潛力。線上有許多資源,你能夠在下面找到幾個更多關於以太坊的教程!
以太坊主站 www.ethereum.org/
以太坊的其中一個客戶端 Mist 的 GitHub Repo github.com/ethereum/mi…
Solidity solidity.readthedocs.io/en/latest/
Web3 api github.com/ethereum/wi…
社區討論 www.reddit.com/r/ethereum/
若是你有任何關於此文的問題,你能夠在咱們 GitHub nightlyHacks repo 中提出。
原文連接: medium.com/@codetracti…
做者: CodeTract
翻譯&校對: 劉豔安 & 阿劍
稿源:以太坊愛好者(ethfans.org/posts/insid…)