├── .gitignore ├── images └── blockchain.png ├── ethereum ├── images │ ├── ethereum-logo.png │ ├── snapshot-dash.png │ ├── smartSponsor-1.png │ ├── smartSponsor-2.png │ ├── smartSponsor-3.png │ ├── snapshot-contract.png │ └── snapshot-dash-web3-provider.png ├── docker-geth-private-testnet.md ├── browser-solidity-install.md ├── README.md ├── docker-geth-multi-nodes.md ├── monitoring-install.md ├── smart-contracts.md ├── signal-geth-testnet.md └── geth-multi-peer.md ├── hyperledger ├── images │ └── hyperledger-logo.png ├── README.md └── hyperledger-docker.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /images/blockchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/images/blockchain.png -------------------------------------------------------------------------------- /ethereum/images/ethereum-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/ethereum-logo.png -------------------------------------------------------------------------------- /ethereum/images/snapshot-dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/snapshot-dash.png -------------------------------------------------------------------------------- /ethereum/images/smartSponsor-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/smartSponsor-1.png -------------------------------------------------------------------------------- /ethereum/images/smartSponsor-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/smartSponsor-2.png -------------------------------------------------------------------------------- /ethereum/images/smartSponsor-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/smartSponsor-3.png -------------------------------------------------------------------------------- /ethereum/images/snapshot-contract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/snapshot-contract.png -------------------------------------------------------------------------------- /hyperledger/images/hyperledger-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/hyperledger/images/hyperledger-logo.png -------------------------------------------------------------------------------- /ethereum/images/snapshot-dash-web3-provider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/learning-blockchain/HEAD/ethereum/images/snapshot-dash-web3-provider.png -------------------------------------------------------------------------------- /hyperledger/README.md: -------------------------------------------------------------------------------- 1 | # Hyperledger 2 | Hyperledger 專案是 IBM 與 Linux 基金會於 2015 年底共同推動的區塊鏈基礎專案,該專案吸引來自多行業巨頭的參與,並且該專案也很有可能成為未來企業級的區塊鏈技術底層架構基礎,因此該專案被受到高度關注。 3 | 4 | 以 Hyperledger 作為企業對企業(B2B)、企業對消費者(B2C)的一種交易協定,既符合規章制度,又能夠支援各種類型需求的實現。其設計的核心元素是```智能合約(Smart Contracts)```、數位資產、記錄儲存庫、一致性對等網路、安全的加密與分散式總賬本等。此外,區塊鍊主要還涉及行業效能要求、身份認證與私下機密交易等。Hyperledger 基於以上建立一個對等網路的分散式總帳技術交易應用程式,透過建立信任、問責制與透明度,並同時簡化業務流程,把它看成是一個作業系統來互動,因此大大的化簡了成本與複雜性。 5 | 6 | ![hyperledger-logo](images/hyperledger-logo.png) 7 | 8 | ## 其他參考連結 9 | - [hyperledger-py](https://github.com/yeasy/hyperledger-py) 10 | - [hyperledger chaincode_example02](https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/chaincode_example02/chaincode_example02.go) 11 | - [8btc](http://www.8btc.com/hyperledger) 12 | - [Technical Introduction to Hyperledger Fabric](http://www.altoros.com/blog/technical-introduction-to-hyperledger-fabric/) 13 | -------------------------------------------------------------------------------- /ethereum/docker-geth-private-testnet.md: -------------------------------------------------------------------------------- 1 | # 部署 Docker Private Testnet 2 | 本節將說明如何透過 Docker 部署 Go Ethereum private testnet。並利用簡單的指令來進行 Demo。 3 | 4 | ### 事前準備 5 | 準備能夠安裝 Docker 的主機與作業系統,這邊採用 Ubuntu Server 14.04 LTS,主機規格如下: 6 | 7 | | RAM | Disk |CPUs | 8 | |-----|------|-----| 9 | | 4GB | 40GB |2vCPU| 10 | 11 | 首先在主機安裝 Docker Engine 與相關套件,可透過以下指令安裝: 12 | ```sh 13 | $ curl -fsSL "https://get.docker.com/" | sh 14 | ``` 15 | 16 | ### 部署 Ethereum 17 | 目前 Go Ethereum 已經有自己的 Docker image,故這邊只需要執行以下指令抓取: 18 | ```sh 19 | $ docker pull ethereum/client-go 20 | ``` 21 | 22 | 這邊也有撰寫好腳本,可以透過以下方式來建立測試網路: 23 | 24 | 接著手動執行以下指令來啟動 docker-geth 容器: 25 | ```sh 26 | $ git clone https://github.com/kairen/kubereum.git 27 | $ cd kubereum/docker 28 | $ make init && make run_node 29 | ``` 30 | > 這邊可以透過```docker logs -f ```來查看伺服器狀態。 31 | 32 | 接著進入容器內,並透過以下指令來 attach geth: 33 | ```sh 34 | $ make console 35 | ``` 36 | -------------------------------------------------------------------------------- /ethereum/browser-solidity-install.md: -------------------------------------------------------------------------------- 1 | # Browser Solidity 2 | Browser Solidity 是一個 Web-based 的 Solidity 編譯器與 IDE。本節將說明如何安裝於 Linux 與 Docker 中。 3 | 4 | 這邊可以連結官方的 https://ethereum.github.io/browser-solidity 來使用; 該網站會是該專案的最新版本預覽。 5 | 6 | ### Ubuntu Server 手動安裝 7 | 首先安裝 Browser Solidity 要使用到的相關套件: 8 | ```sh 9 | $ sudo apt-get install -y apache2 make g++ git 10 | ``` 11 | 12 | 接著安裝 node.js 平台,來建置 App: 13 | ```sh 14 | $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - 15 | $ sudo apt-get install nodejs 16 | ``` 17 | 18 | 然後透過 git 將專案抓到 local 端,並進入目錄: 19 | ```sh 20 | $ git clone https://github.com/ethereum/browser-solidity.git 21 | $ cd browser-solidity 22 | ``` 23 | 24 | 安裝相依套件與建置應用程式: 25 | ```sh 26 | $ sudo npm install 27 | $ sudo npm run build 28 | ``` 29 | 30 | 完成後,將所以有目錄的資料夾與檔案搬移到 Apache HTTP Server 的網頁根目錄: 31 | ```sh 32 | $ sudo cp ./* /var/www/html/ 33 | ``` 34 | > 完成後就可以開啟網頁了。 35 | 36 | ### Docker 快速安裝 37 | 本節將說明如何透過抓取線上的映像檔來快速執行 Dashboard。只要透過以下指令既可以進行下載映像檔與佈屬: 38 | ```sh 39 | $ docker run -d \ 40 | -p 80:80 \ 41 | --name solidity \ 42 | kairen/solidity 43 | ``` 44 | 45 | ![](images/snapshot-dash.png) 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blockchain 2 | 區塊鏈技術目前受到了許多關注,不僅僅是指儲存交易分類賬本,也指數位貨幣,如比特幣(Bitcoin),但將程式碼與資料封裝成智能合約(Smart Contracts)。本專案將針對現有的開放式原始碼區塊鏈技術進行整理與實作,以證明這些技術的可行性與優勢。 3 | 4 | 區塊鏈(Blockchain)是一個資料結構,它儲存著不斷增長的時間序列資料,如一個賬戶賬簿(Accounting ledger)。區塊鏈資料結構的維護是使用一種分散式(distributed)、對等式網路(peer-to-peer)與去中心主節點的架構。在一個鏈(chain)中的每個區塊(block)會包含表示資料庫中狀態變化的交易(_transactions_); 例如,資金從一個賬戶移轉到另一個賬戶。交易(transactions)是由網路中多個節點進行驗證,並最終被儲存於區塊鏈的區塊(_block_)中 5 | 每個區塊都包含一個簽證雜湊(signed hash)的內容,因此區塊不可能會被隨意的竄改內容 6 | 。它能夠橫跨整個區塊鏈,以確保一個區塊的雜湊值儲存在它後面的區塊中。 7 | 8 | ![Blockchain](images/blockchain.png) 9 | 10 | 區塊鏈的一些關鍵特性,使它能夠吸引應用程式開發者: 11 | * 區塊鏈可以由任何人執行。如果你的應用程式儲存在一個大眾的區塊鏈上的話,該應用程式將不需要提供自己的儲存機制來儲存資料。區塊鏈節點促進儲存與交易手續費,以及偶爾挖掘一些新貨幣。 12 | * 區塊鏈提供一個分散式一致性的解決方案,該特性是很難實現的。 13 | * 區塊鏈提供針對使用者的匿名。一個賬戶 ID 是一個公有金鑰(Public Key),這不一定直接歸屬於一個人。 14 | * "Value" 能夠從一個賬戶轉移到另一個賬戶,能以較小的費用、傳統電匯機制或是實際貨幣。 15 | * 如果區塊鏈是可信任的,即儲存在其中的交易資料是能夠被信任的,但這過程要經過許多節點進行驗證。 16 | 17 | 以下整理陳列一些相關區塊鏈技術專案與平台: 18 | * [Ethereum](https://www.ethereum.org/) 19 | * [Openchain](https://www.openchain.org/) 20 | * [Hyperledger](https://www.hyperledger.org/) 21 | * [Multichain](http://www.multichain.com/) 22 | * [GCOIN](http://g-coin.org/learn.html) 23 | * [Bitcore](https://github.com/bitpay/bitcore) 24 | * [dnschain](https://github.com/okTurtles/dnschain) 25 | * [blockstack](http://blockstack.org) 26 | * [IBM Blockchain](http://www.ibm.com/blockchain/) 27 | * [Ripple](https://ripple.com/) 28 | * [Steller](https://www.stellar.org/about/mandate/) 29 | * [Eris](https://erisindustries.com/) 30 | * [Tendermint](http://tendermint.com/) 31 | * [Chain of Things](http://www.chainofthings.com/) 32 | -------------------------------------------------------------------------------- /ethereum/README.md: -------------------------------------------------------------------------------- 1 | # Ethereum 2 | Ethereum 專案是以區塊鏈原理,並進一步增加容納值、儲存資料,並且能封裝程式碼來建立智能合約(Smart Contracts),形成區塊鏈應用程式,來執行運算任務。類似於比特幣(Bitcoin),Ethereum 也具有一種貨幣,它叫做`乙太幣(Ether)`。乙太幣是開採於儲存在共享一致性的區塊鏈前驗證交易節點。乙太幣可以在賬戶(公有金鑰, Pubilc keys)與智能合約(Smart Contracts)之間進行轉移。 3 | 4 | 智能合約(Smart Contracts)允許匿名當事人簽訂具有約束力的協議,因此每一位參與者對這筆交易都有有充分的透明度。值(Value)能夠在賬戶之間進行轉移,或是在託管內部的智能合約本身轉移。一個合約就只是一些程式碼,因此應用程式僅限於開發者自我的想像力。 5 | 6 | ![ethereum-logo](images/ethereum-logo.png) 7 | 8 | ## 參考資訊 9 | 目前 Ethereum 的程式碼可以從 Git 分支取得,有以下幾個專案: 10 | * [go-ethereum](https://github.com/ethereum/go-ethereum) 11 | * [webthree-umbrella (C++)](https://github.com/ethereum/webthree-umbrella) 12 | * [pyethapp](https://github.com/ethereum/pyethapp) 13 | 14 | 其他相關文章與連結可以參考以下連結: 15 | - [Kubereum](https://github.com/kairen/kubereum) 16 | - [Main Ethereum Wiki](https://github.com/ethereum/wiki/wiki) 17 | - [docker-ethereum](https://github.com/Kunstmaan/docker-ethereum) 18 | - [How to Setup a Local Test Ethereum Blockchain - Private Testnet](http://www.lightrains.com/blog/setup-local-ethereum-blockchain-private-testnet) 19 | - [geth-private-easily-setup-private-ethereum-blockchains-from-the-command-line-and-node](http://www.hiddentao.com/archives/2016/04/04/geth-private-easily-setup-private-ethereum-blockchains-from-the-command-line-and-node/) 20 | - [Setting-up-private-network-or-local-cluster](https://github.com/ethereum/go-ethereum/wiki/Setting-up-private-network-or-local-cluster) 21 | - [A 101 Noob Intro to Programming Smart Contracts on Ethereum](https://medium.com/@ConsenSys/a-101-noob-intro-to-programming-smart-contracts-on-ethereum-695d15c1dab4#.qc8whd5nu) 22 | - [Create a Hello World Contract in ethereum](https://www.google.com.tw/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwjO58fws-nMAhUl2qYKHWw4A1sQFggaMAA&url=https%3A%2F%2Fwww.ethereum.org%2Fgreeter&usg=AFQjCNFv3ONgvzxGY1iysHpaXVNprIO5MA&sig2=hLDWM8HcUXwrKh3Pu1SXNg) 23 | - [Block chain technology, smart contracts and Ethereum](https://developer.ibm.com/clouddataservices/2016/05/19/block-chain-technology-smart-contracts-and-ethereum/) 24 | - [Smart Contracts](http://ether.fund/contracts/?p=2) 25 | - [ethereum-infrastructure](https://github.com/vallard/ethereum-infrastructure) 26 | - [Our thoughts on Ethereum](https://medium.com/@kpcb_edge/our-thoughts-on-ethereum-31520b164e00#.qp554vvrc) 27 | - [JURIX 2015: Setting Up an Ethereum Testnet](http://billmarino2.github.io/general/2015/12/09/JURIX-2015-setting-up-an-ethereum-testnet.html) 28 | -------------------------------------------------------------------------------- /hyperledger/hyperledger-docker.md: -------------------------------------------------------------------------------- 1 | # 部署 Hyperledger 於 Docker 2 | 本文章將說明如何透過 Docker 部署 Hyperledger。並利用簡單的指令來進行交易。 3 | 4 | ## 事前準備 5 | 準備一台 Ubuntu Server 14.04 LTS 主機規格如下: 6 | 7 | | Role | RAM | Disk | CPUs | IP Address | 8 | |------------|-------------|-----------------|------------|------------| 9 | | hyperledger| 4 GB 記憶體 | 40 GB 儲存空間 | 兩核處理器 | 172.16.1.78| 10 | 11 | 然後安裝 Docker Engine 與相關套件,透過以下指令: 12 | ```sh 13 | $ sudo apt-get install -y python-pip git 14 | $ curl -fsSL "https://get.docker.com/" | sh 15 | ``` 16 | 17 | 接著安裝 Docker-compose,透過以下指令安裝: 18 | ```sh 19 | $ sudo pip install --upgrade pip 20 | $ sudo pip install docker-compose 21 | ``` 22 | 23 | ## 安裝 Hyperledger 24 | 安裝前首先下載 Hyperledger compose 專案,透過以下指令: 25 | ```sh 26 | $ git clone https://github.com/yeasy/docker-compose-files.git 27 | $ cd docker-compose-files/hyperledger 28 | ``` 29 | 30 | 執行以下步驟來下載與取代映像檔: 31 | ```sh 32 | $ docker pull openblockchain/baseimage:0.0.9 33 | $ docker pull yeasy/hyperledger:latest 34 | $ docker tag yeasy/hyperledger:latest hyperledger/fabric-baseimage:latest 35 | $ docker pull yeasy/hyperledger-peer:noops 36 | $ docker pull yeasy/hyperledger-peer:pbft 37 | $ docker pull yeasy/hyperledger-membersrvc:latest 38 | ``` 39 | 40 | 接著執行 docker compose 來部署四個節點的 Hyperledger: 41 | ```sh 42 | $ docker-compose up 43 | Attaching to hyperledger_vp0_1, hyperledger_vp3_1, hyperledger_vp1_1, hyperledger_vp2_1 44 | vp0_1 | 07:42:07.870 [crypto] main -> INFO 001 Log level recognized 'info', set to INFO 45 | ... 46 | ``` 47 | 48 | ## 驗證 Hyperledger peer 49 | 進入到第一個 hyperledger 容器裡面,透過以下指令: 50 | ```sh 51 | $ docker exec -ti hyperledger_vp0_1 bash 52 | ``` 53 | 54 | 查看目前所有建立的節點: 55 | ```sh 56 | $ peer node status 57 | 08:09:14.715 [crypto] main -> INFO 001 Log level recognized 'info', set to INFO 58 | 08:09:14.715 [logging] LoggingInit -> DEBU 002 Setting default logging level to DEBUG for command 'node' 59 | 08:09:14.715 [peer] func1 -> INFO 003 Auto detected peer address: 172.17.0.2:30303 60 | 08:09:14.716 [peer] func1 -> INFO 004 Auto detected peer address: 172.17.0.2:30303 61 | 08:09:14.716 [peer] func1 -> INFO 005 Auto detected peer address: 172.17.0.2:30303 62 | status:STARTED 63 | ``` 64 | 65 | 進入到容器後,首先部署一個 chaincode: 66 | ```sh 67 | $ peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 \ 68 | -c '{"Function":"init", "Args": ["kairen","100", "pingyu", "200"]}' 69 | ... 70 | 81a73fa1fabe6e385f3c609cef8915a732ee74179abde55f4ac7addf4e7c35ac4a669a7d9a17b2c9a6b3c28b45565b97dc69f4c8f53381ba13251adf5ac6d23d 71 | ``` 72 | > 上面會取得一組 Key。 73 | 74 | 首先查詢 kairen 的金錢有多少: 75 | ```sh 76 | $ my_key="81a73fa1fabe6e385f3c609cef8915a732ee74179abde55f4ac7addf4e7c35ac4a669a7d9a17b2c9a6b3c28b45565b97dc69f4c8f53381ba13251adf5ac6d23d" 77 | $ peer chaincode query -n ${my_key} \ 78 | -c '{"Function": "query", "Args": ["kairen"]}' 79 | ... 80 | 100 81 | ``` 82 | 83 | 接著執行一個交易,我們讓 kairen 付保護費給 pingyu: 84 | ```sh 85 | $ peer chaincode invoke -n ${my_key} \ 86 | -c '{"Function": "invoke", "Args": ["kairen", "pingyu", "10"]}' 87 | ``` 88 | 89 | 確認完成交易後,可以查看 pingyu: 90 | ```sh 91 | $ peer chaincode query -n ${my_key} \ 92 | -c '{"Function": "query", "Args": ["pingyu"]}' 93 | ``` 94 | -------------------------------------------------------------------------------- /ethereum/docker-geth-multi-nodes.md: -------------------------------------------------------------------------------- 1 | # 部署 Go Ethereum 於 Docker 2 | 本節將說明如何透過 Docker 部署 Go Ethereum。並利用簡單的指令來進行 Demo。 3 | 4 | ### 事前準備 5 | 準備能夠安裝 Docker 的主機與作業系統,這邊採用 Ubuntu Server 14.04 LTS,主機規格如下: 6 | 7 | | RAM | Disk |CPUs | 8 | |-----|------|-----| 9 | | 4GB | 40GB |2vCPU| 10 | 11 | 然後安裝 Docker Engine 與相關套件,透過以下指令: 12 | ```sh 13 | $ curl -fsSL "https://get.docker.com/" | sh 14 | ``` 15 | 16 | ### 安裝 Ethereum 17 | 首先透過以下指令抓取 Go Ethereum 映像檔: 18 | ```sh 19 | $ docker pull ethereum/client-go 20 | ``` 21 | 22 | 然後部署名稱為```ethereum-1```的節點,執行以下指令來部署: 23 | ```sh 24 | $ docker run -it -p 30303:30303 --name ethereum-1 ethereum/client-go console 25 | I0520 10:14:55.442553 ethdb/database.go:82] Alloted 128MB cache and 1024 file handles to /root/.ethereum/chaindata 26 | I0520 10:14:55.524803 ethdb/database.go:169] closed db:/root/.ethereum/chaindata 27 | I0520 10:14:55.524901 cmd/utils/flags.go:601] WARNING: No etherbase set and no accounts found as default 28 | ... 29 | ``` 30 | > 完成後會直接進入 console。 31 | 32 | 在```ethereum-1```節點執行以下指令: 33 | ```sh 34 | > admin.nodeInfo.enode 35 | "enode://c85dc1f295407b70f2c33978c3633a317acef260d306764b625535e2272718bf8331162c073c64727f4301fec712c10e57e14db194474343abc7805bf16bdb88@[::]:30303" 36 | ``` 37 | > 這邊```[::]```可以表示為```127.0.0.1```。 38 | 39 | 確認正常執行後,接著部署```ethereum-2```節點,透過以下指令: 40 | ```sh 41 | $ docker run -it -p 30304:30303 --name ethereum-2 ethereum/client-go console 42 | I0520 10:15:17.050718 ethdb/database.go:82] Alloted 128MB cache and 1024 file handles to /root/.ethereum/chaindata 43 | I0520 10:15:17.061346 ethdb/database.go:169] closed db:/root/.ethereum/chaindata 44 | I0520 10:15:17.061481 cmd/utils/flags.go:601] WARNING: No etherbase set and no accounts found as default 45 | ... 46 | ``` 47 | > 完成後會直接進入 console。 48 | 49 | 在```ethereum-2```節點執行以下指令: 50 | ```sh 51 | > admin.nodeInfo.enode 52 | "enode://d09a99483f260819cd56e8faefd5fad33ea65ac8d7ba062534085c86e14b8b926bd190c67a50272195afbb432d17afc027d78551b9a7494c036bd4366d7f00ff@[::]:30303" 53 | ``` 54 | > 這邊```[::]```可以表示為```127.0.0.1```。 55 | 56 | 透過 docker 指令查詢```ethereum-1``` 網路位址: 57 | ```sh 58 | $ docker inspect -f '{{.NetworkSettings.IPAddress}}' ethereum-1 59 | 172.17.0.2 60 | ``` 61 | 62 | 接著我們要將節點串接起來,在```ethereum-2```節點執行以下指令來連接: 63 | ```sh 64 | > admin.addPeer("enode://c85dc1f295407b70f2c33978c3633a317acef260d306764b625535e2272718bf8331162c073c64727f4301fec712c10e57e14db194474343abc7805bf16bdb88@172.17.0.2:30303") 65 | true 66 | ``` 67 | > 這邊要注意```ethereum-1```的 IP 是否正確。 68 | 69 | 完成後在任一節點確認是否串接成功,透過以下指令查看: 70 | ```sh 71 | > net.listening 72 | true 73 | 74 | > net.peerCount 75 | 1 76 | 77 | > admin.peers 78 | [{ 79 | caps: ["eth/61", "eth/62", "eth/63"], 80 | id: "c85dc1f295407b70f2c33978c3633a317acef260d306764b625535e2272718bf8331162c073c64727f4301fec712c10e57e14db194474343abc7805bf16bdb88", 81 | name: "Geth/v1.4.3-stable/linux/go1.5.1", 82 | network: { 83 | localAddress: "172.17.0.3:53702", 84 | remoteAddress: "172.17.0.2:30303" 85 | }, 86 | protocols: { 87 | eth: { 88 | difficulty: 17179869184, 89 | head: "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", 90 | version: 63 91 | } 92 | } 93 | }] 94 | ``` 95 | > 這邊可以看到 remote 與 local 兩端。 96 | 97 | 透過 admin.nodeInfo 查看節點資訊: 98 | ```sh 99 | > admin.nodeInfo 100 | { 101 | enode: "enode://ba86c458d5f1233c0046675e03318ce6b1b8c30b94b4d35b99ea6ce36c29a9d5175698c31b941ce39a2c986dc6eaf51e4d6fa4441ad8013c22c3a364e43c5fff@[::]:30303", 102 | id: "ba86c458d5f1233c0046675e03318ce6b1b8c30b94b4d35b99ea6ce36c29a9d5175698c31b941ce39a2c986dc6eaf51e4d6fa4441ad8013c22c3a364e43c5fff", 103 | ip: "::", 104 | listenAddr: "[::]:30303", 105 | name: "Geth/v1.4.3-stable/linux/go1.5.1", 106 | ports: { 107 | discovery: 30303, 108 | listener: 30303 109 | }, 110 | protocols: { 111 | eth: { 112 | difficulty: 17179869184, 113 | genesis: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", 114 | head: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", 115 | network: 1 116 | } 117 | } 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /ethereum/monitoring-install.md: -------------------------------------------------------------------------------- 1 | # Ethereum Monitor 安裝 2 | Ethereum 提供了一個 Web-based 的監控儀表板,可以部署該儀表板,並透過 Clinet 端傳送 Ethereum 節點的資訊,來查看整個區塊鏈狀態。本節將說明如何安裝監控儀表板於 Linux 與 Docker 容器中。 3 | 4 | 這邊可以連結官方的 https://ethstats.net/ 來查看主節點網路的狀態。 5 | 6 | ### Ubuntu Server 手動安裝 7 | 本部分說明如何手動安裝 eth-netstats 服務,其中會包含以下兩個部分: 8 | 9 | - [Monitoring site](#monitoring-site) 10 | - [Client side](#client-side) 11 | 12 | #### Monitoring site 13 | 首先安裝 Browser Solidity 要使用到的相關套件: 14 | ```sh 15 | $ sudo apt-get install -y make g++ git 16 | ``` 17 | 18 | 接著安裝 node.js 平台,來建置 App: 19 | ```sh 20 | $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - 21 | $ sudo apt-get install nodejs 22 | ``` 23 | 24 | 然後透過 git 將專案抓到 local 端,並進入目錄: 25 | ```sh 26 | $ git clone https://github.com/cubedro/eth-netstats 27 | $ cd eth-netstats 28 | ``` 29 | 30 | 安裝相依套件與建置應用程式,並啟動服務: 31 | ```sh 32 | $ sudo npm install 33 | $ sudo npm install -g grunt-cli 34 | $ grunt 35 | $ PORT="3000" WS_SECRET="admin" npm start 36 | ``` 37 | > 接著就可以開啟 [eth-netstats](http://localhost:3000)。 38 | 39 | > 在沒有任何 Clinet 節點連上情況下,會是一個空的網頁。 40 | 41 | 撰寫一個腳本`eth-netstats.sh`放置到背景服務執行: 42 | ```sh 43 | #!/bin/bash 44 | # History: 45 | # 2016/05/22 Kyle Bai Release 46 | # 47 | export PORT="3000" 48 | export WS_SECRET="admin" 49 | 50 | echo "Starting private eth-netstats ..." 51 | screen -dmS netstats /usr/bin/npm start 52 | ``` 53 | 54 | 透過以下方式執行: 55 | ```sh 56 | $ chmod u+x eth-netstats.sh 57 | $ ./eth-netstats.sh 58 | Starting private eth-netstats ... 59 | ``` 60 | > 透過`screen -x netstats`取得當前畫面。 61 | 62 | #### Client side 63 | 首先安裝 Browser Solidity 要使用到的相關套件: 64 | ```sh 65 | $ sudo apt-get install -y make g++ git 66 | ``` 67 | 68 | 接著安裝 node.js 平台,來建置 App: 69 | ```sh 70 | $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - 71 | $ sudo apt-get install nodejs 72 | ``` 73 | 74 | 然後透過 git 將專案抓到 local 端,並進入目錄: 75 | ```sh 76 | $ git clone https://github.com/cubedro/eth-net-intelligence-api 77 | $ cd eth-net-intelligence-api 78 | ``` 79 | 80 | 安裝相依套件與建置應用程式: 81 | ```sh 82 | $ sudo npm install && sudo npm install -g pm2 83 | ``` 84 | 85 | 編輯`app.json`設定檔,並修改以下內容: 86 | ```sh 87 | [ 88 | { 89 | "name" : "mynode", 90 | "cwd" : ".", 91 | "script" : "app.js", 92 | "log_date_format" : "YYYY-MM-DD HH:mm Z", 93 | "merge_logs" : false, 94 | "watch" : false, 95 | "exec_interpreter" : "node", 96 | "exec_mode" : "fork_mode", 97 | "env": 98 | { 99 | "NODE_ENV" : "production", 100 | "RPC_HOST" : "localhost", 101 | "RPC_PORT" : "8545", 102 | "INSTANCE_NAME" : "mynode-1", 103 | "WS_SERVER" : "http://localhost:3000", 104 | "WS_SECRET" : "admin", 105 | } 106 | }, 107 | ] 108 | ``` 109 | > * `RPC_HOST`為 ethereum 的 rpc ip address。 110 | 111 | > * `RPC_PORT`為 ethereum 的 rpc port。 112 | 113 | > * `INSTANCE_NAME`為 ethereum 的監控實例名稱。 114 | 115 | > * `WS_SERVER`為 eth-netstats 的 URL。 116 | 117 | > * `WS_SECRET`為 eth-netstats 的 secret。 118 | 119 | 確認完成後,即可啟動服務: 120 | ```sh 121 | $ pm2 start app.json 122 | $ sudo tail -f $HOME/.pm2/logs/mynode-out-0.log 123 | ``` 124 | 125 | ### Docker 快速安裝 126 | 本部分說明如何手動安裝 eth-netstats 服務,其中會包含以下兩個部分: 127 | 128 | - [Docker Monitoring site](#docker-monitoring-site) 129 | - [Docker Client side](#docker-client-side) 130 | 131 | #### Docker Monitoring site 132 | 自動建置的映像檔現在可以在 [DockerHub](https://hub.docker.com/r/kairen/ethstats/) 找到,建議直接執行以下指令來啟動 eth-netstats 容器: 133 | ```sh 134 | $ docker run -d \ 135 | -p 3000:3000 \ 136 | -e WS_SECRET="admin" \ 137 | --name ethstats \ 138 | kairen/ethstats 139 | ``` 140 | > 接著就可以開啟 [eth-netstats](http://localhost:3000)。 141 | 142 | > 在沒有任何 Clinet 節點連上情況下,會是一個空的網頁。 143 | 144 | #### Docker Client side 145 | 自動建置的映像檔現在可以在 [DockerHub](https://hub.docker.com/r/kairen/ethnetintel/) 找到,也推薦透過執行以下指令來啟動 eth-netintel 容器: 146 | ```sh 147 | $ docker run -d \ 148 | -p 30303:30303 \ 149 | -p 30303:30303/udp \ 150 | -e NAME_PREFIX="geth-1" \ 151 | -e WS_SERVER="http://172.17.1.200:3000" \ 152 | -e WS_SECRET="admin" \ 153 | -e RPC_HOST="172.17.1.199" \ 154 | -e RPC_PORT="8545" \ 155 | --name geth-1 \ 156 | kairen/ethnetintel 157 | ``` 158 | > Monitor 與 Client 需要統一`WS_SECRET`。 159 | -------------------------------------------------------------------------------- /ethereum/smart-contracts.md: -------------------------------------------------------------------------------- 1 | # 智能合約(Smart contracts) 2 | 智能合約(Smart Contracts) 是在 Ethereum 區塊鏈中所屬的物件。它們包含程式碼函式以及能夠與其他合約進行互動、做出決策、儲存資料與傳送乙太幣給其他人。合約是由創建者所定義,但是它們的執行與他們所提供的服務,都是由 Ethereum 網路本身提供。它們將存在且可被執行,只要整個網路存在,並且只會因程式中有撰寫自我銷毀的功能才會消失。 3 | 4 | 我可以用合約做什麼呢?只要想像力夠豐富,要做什麼幾乎都沒問題,但以下指南只會是入門,讓我們去實現一些簡單的事情。 5 | 6 | - [Hello World](#hello-world) 7 | - [Smart Sponsor](#smartsponsor) 8 | 9 | ### Hello World 10 | 本節將透過建立一個典型的 "Hello World" 的合約,然後你可以建立自己的加密 token 去存送給任何你喜歡的人。一旦你掌握了,那你將透過群資募款來集資,如果成功了,將提供一個完全透明、民主的組織,將只服從它自己的公民,將永遠不會遠離它的憲法,以及受到審查與關閉。 11 | 12 | (TBD) 13 | 14 | ### Smart Sponsor 15 | 本節將說明一智能合約範例,透過建構一個合約來允許以下賬戶持有人進行互動。 16 | * 一個慈善機構舉行籌款活動,我們稱之為 **thebenefactor**。 17 | * 一個受贊助的 runner 想為慈善機構募款,我們稱之為 **therunner**。 18 | * 其他的人想要贊助 runner,我們稱之為 **thesponsor**。 19 | * 一個 Ethereum 節點,用來開採區塊鏈以驗證交易,我們稱之為 **theminer**。 20 | 21 | 我們的合約(smartSponsor): 22 | * 是由一位 **runner** 透過贊助的執行來為慈善機構募款。 23 | * 當建立合約時,**runner** 會任命為募集錢的捐助者。 24 | * **runner** 則邀情其他人去進行贊助。用戶透過呼叫一個在智能合約上的函式,將乙太幣從 **贊助商的帳戶** 轉移到 **合約**,並保持乙太幣於合約,直到有進一步的通知。 25 | * 在合約的時限期間的所有人都能看到誰是 **捐助者**,有多少的乙太幣被從誰捐(雖然贊助者可以匿名,當然:p)。 26 | 27 | ![flow-1](images/smartSponsor-1.png) 28 | 29 | 那麼有兩件事情可能發生: 30 | * 執行都按計劃進行,以及 **runner** 指示合約轉移到所有資金的捐助者。 31 | 32 | ![flow-2](images/smartSponsor-2.png) 33 | 34 | * 執行由於謀些原因無法承擔,而 runner 指示合約將退還贊助商的抵押。 35 | 36 | ![flow-3](images/smartSponsor-3.png) 37 | 38 | Ethereum 允許智能合約由撰寫 Solidity 語言來定義。Solidity 的合約是類似於 Java 的類別定義。成員變數的儲存採用區塊鍊交易與合約的方法,來詢問合約或改變的其狀態。作為區塊鏈的副本會分散到網路中的所有節點,任何人都可以詢問合約,以從中搜尋公開的訊息。 39 | 40 | 合約有以下幾種方法: 41 | * **```smartSponsor```**:合約的建構子。它初始化合約的狀態。合約的建立者傳入賬戶的位址,有利於合約的 drawdown。 42 | * **```pledge```**:任何人都可以呼叫捐贈乙太幣贊助基金。贊助商提供支援的選擇性訊息 43 | * **```getPot```**:回傳當前儲存在合約的總乙太幣。 44 | * **```refund```**:把贊助商的錢退回給贊助商。只有合約的擁有者才能呼叫這個函式。 45 | * **```drawdown```**:傳送合約的總價值給捐助者賬戶。只有合約的擁有者才能呼叫這個函式。 46 | 47 | 這個想法是使一個合約擁有約束力。他們不能拿回任何資金,除非整個合約被退還。在這種情況下,所有資料都是被公開存取的,這意味著任何人都有存取 Ethereum 區塊鏈,來查看誰建立了合約,誰是捐助者,以及誰透過存取合約程式碼本身保證了每一筆資金。 48 | 49 | 要注意很重要的一點,任何改變合約的狀態(建立、承若、退還或 drawing down)都需要在區塊鏈上建立交易,這意味著這些交易不會被儲存,要直到這些交易的區塊被開採。操作只能讀取到一個現有合約狀態(getPot 或讀取公有成員變數)都不需要進行挖礦。這是一個很重要且微妙的點:寫入操作是很慢的(因為我們要等到採礦完成)。由於這情況合約可能永遠不會被建立到區塊鍊中,因此呼叫方需要提供一些獎勵,來促進礦工去工作。這是被稱為 gas 的 Ethereum 術語,所有的寫入操作都是需要 gas 的支出來改變區塊鍊的狀態。 50 | 51 | 幸運的是我們不需要購買真正的乙太幣,以及參與 Ethereum 網路。我們可以使用相同的軟體,但要配置它運行一個本地測試區塊鏈,以及產生自己的假乙太幣。 52 | 53 | 以下為一個 Solidity 語言的智能合約範例: 54 | ```java 55 | contract smartSponsor { 56 | address public owner; 57 | address public benefactor; 58 | bool public refunded; 59 | bool public complete; 60 | uint public numPledges; 61 | struct Pledge { 62 | uint amount; 63 | address eth_address; 64 | bytes32 message; 65 | } 66 | mapping(uint => Pledge) public pledges; 67 | 68 | // constructor 69 | function smartSponsor(address _benefactor) { 70 | owner = msg.sender; 71 | numPledges = 0; 72 | refunded = false; 73 | complete = false; 74 | benefactor = _benefactor; 75 | } 76 | 77 | // add a new pledge 78 | function pledge(bytes32 _message) payable { 79 | if (msg.value == 0 || complete || refunded) throw; 80 | pledges[numPledges] = Pledge(msg.value, msg.sender, _message); 81 | numPledges++; 82 | } 83 | 84 | function getPot() constant returns (uint) { 85 | return this.balance; 86 | } 87 | 88 | // refund the backers 89 | function refund() { 90 | if (msg.sender != owner || complete || refunded) throw; 91 | for (uint i = 0; i < numPledges; ++i) { 92 | pledges[i].eth_address.send(pledges[i].amount); 93 | } 94 | refunded = true; 95 | complete = true; 96 | } 97 | 98 | // send funds to the contract benefactor 99 | function drawdown() { 100 | if (msg.sender != owner || complete || refunded) throw; 101 | benefactor.send(this.balance); 102 | complete = true; 103 | } 104 | } 105 | ``` 106 | > * 一個```Pledge```結構模型的捐贈,儲存著贊助商的帳戶 ID、承若押金,以及一些訊息字串。 107 | 108 | > * 這個 ```pledges``` 陣列儲存了一個承若方的列表。 109 | 110 | > * 合約中的所有成員變數都是公開的,所以```getters```將自動被建立。 111 | 112 | > * ```throw```被稱為某些函式(functions),用以防止資料被寫入錯誤的資料到該區塊鏈中。 113 | 114 | # 參考連結 115 | * [Our thoughts on Ethereum](https://medium.com/@kpcb_edge/our-thoughts-on-ethereum-31520b164e00#.2q1i88278) 116 | * [Building a smart contract using the command line](https://www.ethereum.org/greeter) 117 | * [Block chain technology, smart contracts and Ethereum](https://developer.ibm.com/clouddataservices/2016/05/19/block-chain-technology-smart-contracts-and-ethereum/) 118 | -------------------------------------------------------------------------------- /ethereum/signal-geth-testnet.md: -------------------------------------------------------------------------------- 1 | # Ubuntu Geth Private Testnet 2 | 本節將說明如何透過 Ubuntu 部署 Go Ethereum。並利用簡單的指令來進行 Demo。 3 | 4 | ### 事前準備 5 | 準備一台 Ubuntu Server 14.04 LTS 主機規格如下: 6 | 7 | | RAM | Disk | CPUs | 8 | |-------------|-----------------|------------| 9 | | 4 GB 記憶體 | 40 GB 儲存空間 | 兩核處理器 | 10 | 11 | ### 安裝 Ethereum 12 | 若要在 Ubuntu 安裝 Ethereum 的話,可以透過以下指令快速安裝: 13 | ```sh 14 | $ sudo apt-get install -y software-properties-common 15 | $ sudo add-apt-repository -y ppa:ethereum/ethereum 16 | $ sudo apt-get update && sudo apt-get install ethereum 17 | ``` 18 | 19 | 完成後即可使用`geth`指令,首先我們先建立一個`custom.json`檔案來定義起源區塊(Genesis Block),內容如下: 20 | ```json 21 | { 22 | "coinbase" : "0x0000000000000000000000000000000000000000", 23 | "difficulty" : "0x40000", 24 | "extraData" : "", 25 | "gasLimit" : "0xffffffff", 26 | "nonce" : "0x0000000000000042", 27 | "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 28 | "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 29 | "timestamp" : "0x00", 30 | "config": { 31 | "chainId": 123, 32 | "homesteadBlock": 0, 33 | "eip155Block": 0, 34 | "eip158Block": 0 35 | }, 36 | "alloc": { } 37 | } 38 | ``` 39 | > 其中以上 Genesis block 欄位說明如下 40 | * **nonce**:一個 64 位元雜湊(Hash),用來證明與結合 mix-hash,即已經在此區塊上進行足夠的運算量:工作證明 (PoF)。mixhash 與 nonce 的組合必須滿足一個在 Yellowpaper, 4.3.4. Block Header Validity, (44) 數學描述的條件。它允許驗證該區塊已經被加密並開採。nonce 是加密的安全已開採驗證工作,這證明沒有任何疑點的計算特定數量已在此 Token 值被消費了。(Yellowpager, 11.5. Mining Proof-of-Work). 41 | 42 | > * **mixhash**:一個 256 位元雜湊(hash)用來證明與結合 nonce,即已經在此區塊上進行足夠的運算量:工作證明 (PoF)。mixhash 與 nonce 的組合必須滿足一個在 Yellowpaper, 4.3.4. Block Header Validity, (44) 數學描述的條件。它允許驗證該區塊已經被加密並開採。 43 | 44 | > * **difficulty**:此區塊相應的 nonce 檢測中應用的難度指標值。它定義了採礦的目標,這可以從先前區塊的難度水平與時間戳記來計算。難度越高,統計上需要更多的計算礦工來發現有效的區塊。此值被用來控制一個區塊鍊(Blockchain)的區塊產生時,保持在目標範圍內的區塊產生頻率。在測試網路(Testnet),我們盡量保持低值。 45 | 46 | > * **alloc**:允許定義一個預先存值的錢包列表。這是一個 Ethereum 特定功能,用來處理售前(Pre-sale)時期的貨幣。若是在測試網路中,由於我們很快就會拿挖到寶,所以可以不用設定。 47 | 48 | > * **timestamp**:在這個區塊開始的一個 Unix time() 純量值。 49 | 這種機制在區塊之間的時間強制一個動態平衡。在過去的兩個區塊之間的一個較小的時間區段增加難度,因此需要額外的計算來找到下一個有效的區塊。如果時間過大,難度與預計時間會在下一個區塊被下降。時間戳記也允許被驗證區塊的順序(Yellowpaper, 4.3.4. (43))。 50 | 51 | > * **parentHash**:整個父區塊標頭的 Keccak 256 位元雜湊(包含它的 mixhash 與 nonce)。指向到父區塊,從而有效的建立區塊的鏈。在起源區塊(Genesis block)下,只有這種情況下,它是 0。 52 | 53 | > * **extraData**:一個自由選擇性參數,但是最大為 32 byte 長的空間,用來保存 ethernity 的智能事情。 54 | 55 | > * **gasLimit**:一個純量值等於當前區塊鏈中每個區塊的氣體(Gas = 表示礦源?)消耗限制。在測試環境設高一點,這樣可以避免限制。P.S. 這不表示我們應該忽略該參數重要性。 56 | 57 | 上面設定完成後,就可以透過以下指令來建立: 58 | ```sh 59 | $ geth init --datadir=data/ custom.json 60 | $ geth --datadir data/ --networkid 123 --nodiscover --maxpeers 0 console 61 | ... 62 | instance: Geth/v1.4.3-stable/linux/go1.5.1 63 | coinbase: 0xf939ee9f8b3da46dc94f49b28bf920809bc1cb46 64 | at block: 67 (Fri, 20 May 2016 19:49:36 UTC) 65 | datadir: data 66 | ``` 67 | > 這邊透過 custom.json 建立 blockchain,並使用 datadir 參數來儲存新建的 blockchain 狀態與數據。 68 | 69 | 當正常進入到 geth console 後,就可以建立第一個 account,並獲取位址: 70 | ```sh 71 | > personal.newAccount(); 72 | Passphrase: 73 | Repeat passphrase: 74 | "0x80ae1f1579924bedc59953f13140cd6c4918b812" 75 | ``` 76 | > 要輸入密碼兩次。 77 | 78 | 接著透過鍵盤輸入```[Ctrl-D]```離開,然後執行以下指令刪除 keystore: 79 | ```sh 80 | $ cd data 81 | $ rm -rf `ls | grep -v keystore` 82 | ``` 83 | 84 | 再次編輯```custom.json```檔,在```alloc```加入以下內容: 85 | ```json 86 | { 87 | "nonce": "0xdeadbeefdeadbeef", 88 | "timestamp": "0x0", 89 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 90 | "extraData": "Custem Ethereum Genesis Block", 91 | "gasLimit": "0x8000000", 92 | "difficulty": "0x400", 93 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", 94 | "coinbase": "0x3333333333333333333333333333333333333333", 95 | "alloc": { 96 | "": { 97 | "balance": "10000000000000000000" 98 | } 99 | } 100 | } 101 | ``` 102 | > 這邊``````為 0x80ae1f1579924bedc59953f13140cd6c4918b812。 103 | 104 | 接著再次執行 geth 指令,來透該賬戶存值: 105 | ```sh 106 | $ geth --datadir data/ --networkid 123 --nodiscover --maxpeers 0 console 107 | ``` 108 | 109 | 成功進入後,可以執行查看賬戶資訊: 110 | ```sh 111 | > personal.listAccounts 112 | ["0x80ae1f1579924bedc59953f13140cd6c4918b812"] 113 | ``` 114 | 115 | 查看 primary 賬戶的錢包狀態: 116 | ```sh 117 | > kairen = eth.accounts[0]; 118 | "0x80ae1f1579924bedc59953f13140cd6c4918b812" 119 | 120 | > web3.fromWei(eth.getBalance(kairen), "ether"); 121 | 10 122 | ``` 123 | 124 | 接著就可以進行採礦了,首先設定要開採的賬戶: 125 | ```sh 126 | > miner.setEtherbase(kairen) 127 | true 128 | ``` 129 | 130 | 當賬戶設定完成後,就可以執行以下指令進行採礦: 131 | ```sh 132 | > miner.start(8) 133 | true 134 | 135 | I0520 20:52:23.637262 miner/worker.go:555] commit new work on block 1 with 0 txs & 0 uncles. Took 252.728µs 136 | I0520 20:52:23.637480 ethash.go:259] Generating DAG for epoch 0 (size 1073739904) (0000000000000000000000000000000000000000000000000000000000000000) 137 | ... 138 | ``` 139 | 140 | 若要停止採礦可以按一次 Enter 直接輸入以下指令: 141 | ```sh 142 | > miner.stop() 143 | true 144 | I0520 20:53:26.935445 miner/worker.go:337] 🔨 Mined stale block (#5 / fba716e0). 145 | I0520 20:53:26.938490 miner/worker.go:337] 🔨 Mined stale block (#6 / d82943d3). 146 | ``` 147 | 148 | 經過一段時間後,我們可以在查看一下賬戶: 149 | ```sh 150 | > web3.fromWei(eth.getBalance(kairen), "ether"); 151 | 102.34375 152 | ``` 153 | > 會發現增加了許多。 154 | 155 | 當成開採區塊後,就可以檢查賬戶的 ether balance 的數值: 156 | ``` 157 | > eth.getBalance(eth.coinbase).toNumber() 158 | 102343750000000000000 159 | ``` 160 | 161 | ### 進行交易 162 | Ethereum 有兩種類型的狀態: 163 | * 一般或外部控制的賬戶 164 | * 合約,即表示程式碼片段,可想成是一個類別(class)。 165 | 166 | 這兩種類型的賬戶都具有 ether balance。 167 | 168 | 首先我們先建立另一個賬戶,並查看所有賬戶列表: 169 | ```sh 170 | > personal.newAccount(); 171 | Passphrase: 172 | Repeat passphrase: 173 | "0x99fa5fcf20495dac5eccebeac33917818236d2db" 174 | 175 | > personal.listAccounts 176 | ["0x80ae1f1579924bedc59953f13140cd6c4918b812", "0x99fa5fcf20495dac5eccebeac33917818236d2db"] 177 | ``` 178 | > 其中```0x80ae1f1579924bedc59953f13140cd6c4918b812```表示 kairen,```0x99fa5fcf20495dac5eccebeac33917818236d2db```表示 pingyu。 179 | 180 | 利用變數定義與查看兩者的錢包: 181 | ```sh 182 | > kairen = eth.accounts[0]; 183 | "0x80ae1f1579924bedc59953f13140cd6c4918b812" 184 | 185 | > web3.fromWei(eth.getBalance(kairen), "ether"); 186 | 102.34375 187 | 188 | > pingyu = eth.accounts[1]; 189 | "0x99fa5fcf20495dac5eccebeac33917818236d2db" 190 | 191 | > web3.fromWei(eth.getBalance(pingyu), "ether"); 192 | 0 193 | ``` 194 | 195 | 在移轉之前,首先要解鎖賬戶: 196 | ```sh 197 | > personal.unlockAccount(kairen) 198 | true 199 | ``` 200 | > 也可以直接透過以下方式輸入密碼```personal.unlockAccount(kairen, "r00tme")```。 201 | 202 | 都確認好解鎖賬戶後,就可以進行 Ether 移轉,透過以下方式進行移轉: 203 | ```sh 204 | > eth.sendTransaction({from: kairen, to: pingyu, value: web3.toWei(100, "ether")}) 205 | I0520 21:17:20.950180 eth/api.go:1180] Tx(0x1712f84c3c22a356620f93410699f8b656098bfa6ffc3a3299ef1f57a0c5d681) to: 0x99fa5fcf20495dac5eccebeac33917818236d2db 206 | "0x1712f84c3c22a356620f93410699f8b656098bfa6ffc3a3299ef1f57a0c5d681" 207 | ``` 208 | 209 | 轉移後,就可以確認正在 Pending 的交易: 210 | ```sh 211 | > txpool.status 212 | { 213 | pending: 1, 214 | queued: 0 215 | } 216 | 217 | > eth.getBlock("pending", true).transactions 218 | [{ 219 | blockHash: "0x1748c022911bfff7e71b0bc7191abc3068531f5a9d57eb6031608f4ff84d1e0b", 220 | blockNumber: 40, 221 | from: "0xbe33553d18ba9d5aa477246bebb6fd05d6834793", 222 | gas: 90000, 223 | gasPrice: 21781760000, 224 | hash: "0x482b043cef3dd612827d722a35e383a7e326277c7df335f889e56ee969813584", 225 | input: "0x", 226 | nonce: 0, 227 | to: "0xa1cc1f3f979d33fca8c5543cad1613fd4834e1ef", 228 | transactionIndex: 0, 229 | value: 10000000000000000000 230 | }] 231 | ``` 232 | > 可以看到這筆交易被存在 blockNumber 為 40 的區塊中。 233 | 234 | 這時候查看 pingyu 的賬戶,會發現依然沒有改變,So sad: 235 | ```sh 236 | > web3.fromWei(eth.getBalance(pingyu), "ether"); 237 | 0 238 | ``` 239 | 240 | 這是因為該交易區塊沒有任何人協助進行運算驗證,因此狀態會一直處於 pending,這時候只要在執行以下指令即可: 241 | ```sh 242 | > miner.start(8) 243 | true 244 | 245 | I0525 06:50:47.885729 miner/worker.go:555] commit new work on block 40 with 1 txs & 2 uncles. Took 861.24µs 246 | I0525 06:50:48.261245 miner/worker.go:337] 🔨 Mined block (#40 / bbaee562). Wait 5 blocks for confirmation 247 | ``` 248 | > 經過一段時間確認交易區塊被開採完畢後,就可以透過```miner.stop()```停止。 249 | 250 | 再次觀察交易狀態,會發現已經完成交易,可以透過以下指令查詢: 251 | ```sh 252 | > txpool.status 253 | { 254 | pending: 0, 255 | queued: 0 256 | } 257 | ``` 258 | 259 | 也可以透過 eth web3 的 API 來查找指定區塊的資訊: 260 | ```sh 261 | > eth.getTransactionFromBlock(40) 262 | { 263 | blockHash: "0xbbaee56226a92a2c99b8981ad102bc29940d5cb4f2949559d269bd618e3930d8", 264 | blockNumber: 40, 265 | from: "0xbe33553d18ba9d5aa477246bebb6fd05d6834793", 266 | gas: 90000, 267 | gasPrice: 20000000000, 268 | hash: "0x482b043cef3dd612827d722a35e383a7e326277c7df335f889e56ee969813584", 269 | input: "0x", 270 | nonce: 0, 271 | to: "0xa1cc1f3f979d33fca8c5543cad1613fd4834e1ef", 272 | transactionIndex: 0, 273 | value: 10000000000000000000 274 | } 275 | ``` 276 | 277 | 接著透過建立一個 Java Script 函式印出所有賬戶 Balance: 278 | ```javascript 279 | function checkAllBalances() { 280 | var i =0; 281 | eth.accounts.forEach( function(e){ 282 | console.log(" eth.accounts["+i+"]: " + e + " \tbalance: " + web3.fromWei(eth.getBalance(e), " ether") + "ether"); i++; 283 | }) 284 | }; 285 | ``` 286 | > 直接輸入即可。 287 | 288 | 然後透過以下方式呼叫函式: 289 | ```sh 290 | > checkAllBalances(); 291 | eth.accounts[0]: 0x80ae1f1579924bedc59953f13140cd6c4918b812 balance: 101.34375 ether 292 | eth.accounts[1]: 0x99fa5fcf20495dac5eccebeac33917818236d2db balance: 10 ether 293 | ``` 294 | 295 | ### 參考連結 296 | - [JavaScript-Console Guide](https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console) 297 | -------------------------------------------------------------------------------- /ethereum/geth-multi-peer.md: -------------------------------------------------------------------------------- 1 | # Ubuntu Multi Geth Instances 2 | 本節將說明如何透過 Ubuntu 部署 Go Ethereum。並利用簡單的指令來進行 Demo。 3 | 4 | ### 事前準備 5 | 本次會使用到兩個節點來建立 Geth Instances,其規格如下: 6 | 7 | | Role | CPUs | RAM | Disk | 8 | |-----------|----------|----------|----------| 9 | | geth-1 | 2vCPU | 4 GB | 40 GB | 10 | | geth-2 | 2vCPU | 4 GB | 40 GB | 11 | 12 | 首先在每個節點安裝 Ethereum 最新版本,可以依照官方透過以下方式快速安裝: 13 | ```sh 14 | $ sudo apt-get install -y software-properties-common 15 | $ sudo add-apt-repository -y ppa:ethereum/ethereum 16 | $ sudo apt-get update && sudo apt-get install ethereum 17 | ``` 18 | 19 | 在每個節點建立一個`private.json`檔案來定義創世區塊(Genesis Block),內容如下: 20 | ``` 21 | { 22 | "coinbase" : "0x0000000000000000000000000000000000000000", 23 | "difficulty" : "0x40000", 24 | "extraData" : "Custem Ethereum Genesis Block", 25 | "gasLimit" : "0xffffffff", 26 | "nonce" : "0x0000000000000042", 27 | "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 28 | "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 29 | "timestamp" : "0x00", 30 | "config": { 31 | "chainId": 123, 32 | "homesteadBlock": 0, 33 | "eip155Block": 0, 34 | "eip158Block": 0 35 | }, 36 | "alloc": { } 37 | } 38 | ``` 39 | 40 | 初始化創世區塊: 41 | ```sh 42 | $ geth init --datadir=data/ private.json 43 | ``` 44 | 45 | 在每個節點新增一名稱為`eth-private.sh`的腳本程式,將用於啟動 geth,並放置背景: 46 | ```sh 47 | #!/bin/bash 48 | # Program: 49 | # This program is a private geth runner. 50 | # History: 51 | # 2016/05/22 Kyle Bai Release 52 | # 53 | echo "Starting private geth" 54 | screen -dmS geth /usr/bin/geth \ 55 | --datadir data/ \ 56 | --networkid 123 \ 57 | --nodiscover \ 58 | --maxpeers 5 \ 59 | --port 30301 \ 60 | --rpc \ 61 | --rpcaddr "0.0.0.0" \ 62 | --rpcport "8545" \ 63 | --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \ 64 | --rpccorsdomain "*" \ 65 | -verbosity 6 66 | ``` 67 | > 更多的參數,請參考 [Command-Line-Options](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)。 68 | 69 | 建立完成後,修改執行權限: 70 | ```sh 71 | $ chmod u+x geth-private.sh 72 | ``` 73 | 74 | ### 建置 Ethereum 環境 75 | 首先進入到`geth-1`節點透過以下方式來啟動: 76 | ```sh 77 | $ ./geth-private.sh 78 | Starting private geth 79 | ``` 80 | > 這時候會透過 screen 執行於背景,我們可以透過```screen -x geth```來進行前景。若要回到背景則透過```[Ctrl-A] + [Ctrl-D]```來 detached。要關閉 screen 則透過 ```[Ctrl-C]```。 81 | 82 | 接著為了確認是否正確啟動,我們可以透過 geth 的 attach 指令來連接 console: 83 | ```sh 84 | $ geth attach ipc:data/geth.ipc 85 | ``` 86 | > 也可以透過 HTTP 方式 attach,```geth attach http://localhost:8545```。 87 | 88 | > 若一開始建立沒有 RPC,但想要加入 RPC 可以 attach 後,輸入以下 function: 89 | ```sh 90 | > admin.startRPC("0.0.0.0", 8545, "*", "web3,db,net,eth") 91 | ``` 92 | 93 | 進入後透過 admin API 來取得節點的資訊: 94 | ```sh 95 | > admin.nodeInfo.enode 96 | "enode://e3dd0392a2971c4b0c4c43a01cd682e19f31aaa573c43a9b227685af7ffed5070217392ae5ada278968d5c4bfddd9c93547bcf4592852196a8facbcdad64d257@[::]:30301?discport=0" 97 | ``` 98 | > 這邊要取代```[::]```為主機 IP,如以下: 99 | ``` 100 | "enode://e3dd0392a2971c4b0c4c43a01cd682e19f31aaa573c43a9b227685af7ffed5070217392ae5ada278968d5c4bfddd9c93547bcf4592852196a8facbcdad64d257@172.16.1.99:30301?discport=0" 101 | ``` 102 | 103 | 上面沒問題後,接著進入到`geth-2`節點,然後透過以下指令開啟 console: 104 | ```sh 105 | $ geth init --datadir=data/ private.json 106 | $ geth --datadir data/ \ 107 | --networkid 123 \ 108 | --nodiscover \ 109 | --maxpeers 5 \ 110 | --port 30301 \ 111 | --rpc \ 112 | --rpcaddr "0.0.0.0" \ 113 | --rpcport "8545" \ 114 | --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \ 115 | --rpccorsdomain "*" \ 116 | -verbosity 6 \ 117 | console 118 | ``` 119 | > 也可以透過上一個節點的方式將服務放到背景,在 attach。 120 | 121 | 完成上面指令會直接進入 console,接著透過以下方式來連接`geth-1`: 122 | ```sh 123 | > admin.addPeer("enode://e3dd0392a2971c4b0c4c43a01cd682e19f31aaa573c43a9b227685af7ffed5070217392ae5ada278968d5c4bfddd9c93547bcf4592852196a8facbcdad64d257@172.16.1.99:30301?discport=0") 124 | true 125 | 126 | I0525 12:56:40.623642 eth/downloader/downloader.go:239] Registering peer e3dd0392a2971c4b 127 | I0525 12:57:10.622920 p2p/server.go:467] <-taskdone: wait for dial hist expire (29.99999387s) 128 | ``` 129 | 130 | 接著透過 net API 進行查看連接狀態: 131 | ```sh 132 | > net.peerCount 133 | 1 134 | 135 | > admin.peers 136 | [{ 137 | caps: ["eth/61", "eth/62", "eth/63"], 138 | id: "e3dd0392a2971c4b0c4c43a01cd682e19f31aaa573c43a9b227685af7ffed5070217392ae5ada278968d5c4bfddd9c93547bcf4592852196a8facbcdad64d257", 139 | name: "Geth/v1.4.5-stable/linux/go1.5.1", 140 | network: { 141 | localAddress: "172.16.1.100:51038", 142 | remoteAddress: "172.16.1.99:30301" 143 | }, 144 | protocols: { 145 | eth: { 146 | difficulty: 131072, 147 | head: "882048e0d045ea48903eddb4c50825a4e3c6c1a055df6a32244e9a9239f8c5e8", 148 | version: 63 149 | } 150 | } 151 | }] 152 | ``` 153 | 154 | ### 驗證服務 155 | 這部分將透過幾個指令與流程來驗證服務,首先在`geth-1`透過 attach 進入,並建立一個賬戶與查看乙太幣: 156 | ```sh 157 | $ geth attach http://localhost:8545 158 | 159 | > kairen = personal.newAccount(); 160 | Passphrase: 161 | Repeat passphrase: 162 | "0xcb41ad8ba28c4b8b52eee159ef3bb6da197ff60b" 163 | 164 | > personal.listAccounts 165 | ["0xcb41ad8ba28c4b8b52eee159ef3bb6da197ff60b"] 166 | 167 | > web3.fromWei(eth.getBalance(kairen), "ether"); 168 | 0 169 | ``` 170 | > P.S. 若要移除帳號,可以刪除```data/keystore```底下的檔案。 171 | 172 | 接著在```geth-2```透過以下指令建立一個賬戶與查看乙太幣: 173 | ```sh 174 | > pingyu = personal.newAccount(); 175 | Passphrase: 176 | Repeat passphrase: 177 | "0xf8c70df559cb9225f6e426d0f139fd6e8752c644" 178 | 179 | > personal.listAccounts 180 | ["0xf8c70df559cb9225f6e426d0f139fd6e8752c644"] 181 | 182 | > web3.fromWei(eth.getBalance(pingyu), "ether"); 183 | 0 184 | ``` 185 | 186 | 接著回到`geth-1`來賺取一些要交易的乙太幣: 187 | ```sh 188 | > miner.setEtherbase(kairen) 189 | true 190 | ``` 191 | 192 | 當賬戶設定完成後,就可以執行以下指令進行採礦: 193 | ```sh 194 | > miner.start(1) 195 | true 196 | ``` 197 | > 這邊需要一點時間產生 DAG,可以開一個新的命令列透過```screen -x geth```查看。 198 | 199 | > 經過一段時間後,當 DAG 完成並開始採擴時就可以```miner.stop()```。 200 | 201 | 接著在```geth-1```查看賬戶的乙太幣: 202 | ```sh 203 | > web3.fromWei(eth.getBalance(kairen), "ether"); 204 | 40.78125 205 | ``` 206 | 207 | 當成開採區塊後,就可以查看```geth-1```共採集的 ether balance 的數值: 208 | ``` 209 | > eth.getBalance(eth.coinbase).toNumber() 210 | 40781250000000000000 211 | ``` 212 | > 即為```40.78125```乙太幣。 213 | 214 | 接著我們要在將```geth-1```的賬戶乙太幣轉移到```geth-2```上,首先在```geth-1```上建立一個變數來存```geth-2```的賬戶位址: 215 | ```sh 216 | > consumer = "0xf8c70df559cb9225f6e426d0f139fd6e8752c644" 217 | "0xf8c70df559cb9225f6e426d0f139fd6e8752c644" 218 | ``` 219 | 220 | 完成上述後,首先要將賬戶解鎖: 221 | ```sh 222 | > personal.unlockAccount(kairen) 223 | true 224 | ``` 225 | > 輸入當初建立賬戶的密碼。 226 | 227 | 並透過 eth API 的交易函式還將 ether balance 數值轉移: 228 | ```sh 229 | $ eth.sendTransaction({from: kairen, to: consumer, value: web3.toWei(10, "ether")}) 230 | "0x1aee9082a55751c59077a273e7b08acd028d5099a4986f002518b0c8919d9e36" 231 | ``` 232 | 233 | 若有在每一台 geth 節點上進入 debug 模式的話,會發現該交易資訊被存到一個區塊,這邊也可以透過 txpool 與 eth API 來查看: 234 | ```sh 235 | > txpool.status 236 | { 237 | pending: 1, 238 | queued: 0 239 | } 240 | 241 | > eth.getBlock("pending", true).transactions 242 | [{ 243 | blockHash: "0x0b58d0b17e02f56746b0b5b22f195b6ae71d47343bf778763c4c476386ad7db7", 244 | blockNumber: 112, 245 | from: "0xcb41ad8ba28c4b8b52eee159ef3bb6da197ff60b", 246 | gas: 90000, 247 | gasPrice: 20000000000, 248 | hash: "0x1aee9082a55751c59077a273e7b08acd028d5099a4986f002518b0c8919d9e36", 249 | input: "0x", 250 | nonce: 0, 251 | to: "0xf8c70df559cb9225f6e426d0f139fd6e8752c644", 252 | transactionIndex: 0, 253 | value: 10000000000000000000 254 | }] 255 | ``` 256 | > 這邊的```pending```表示目前還沒有被驗證,因此我們需要一些節點來進行採礦驗證。這邊也可以發現該交易資訊被存在區塊編號```112```,可以提供往後查詢之用。 257 | 258 | 接著回到```geth-2```節點,查看目前的數值變化: 259 | ```sh 260 | > web3.fromWei(eth.getBalance(pingyu), "ether"); 261 | 0 262 | ``` 263 | 264 | 這邊會發現沒有任何錢進來,Why? so sad。其實是因為該區塊還沒有被採集與認證,因此該交易不會被執行。 265 | 266 | 因此我們需要在任一節點提供運算,這邊在```geth-1```執行以下指令來進行採礦,這樣就可以看到該交易被驗證與接受: 267 | ```sh 268 | > miner.start(1) 269 | true 270 | 271 | TX(1aee9082a55751c59077a273e7b08acd028d5099a4986f002518b0c8919d9e36) 272 | Contract: false 273 | From: cb41ad8ba28c4b8b52eee159ef3bb6da197ff60b 274 | To: f8c70df559cb9225f6e426d0f139fd6e8752c644 275 | Nonce: 0 276 | GasPrice: 20000000000 277 | GasLimit 90000 278 | Value: 10000000000000000000 279 | Data: 0x 280 | V: 0x1c 281 | R: 0x9de7d843959f55a553577dc68a887893adf1b80eccd872021dfa6b8bcf3db43 282 | S: 0x287f8e01640ccd5924308725d2d274def7edc4a18169b36ae26c95216fdf0fed 283 | Hex: f86d808504a817c80083015f9094f8c70df559cb9225f6e426d0f139fd6e8752c644888ac7230489e80000801ca009de7d843959f55a553577dc68a887893adf1b80eccd872021dfa6b8bcf3db43a0287f8e01640ccd5924308725d2d274def7edc4a18169b36ae26c95216fdf0fed 284 | ``` 285 | > 當該區塊的交易確認沒問題被執行後,就可以透過```miner.stop()```停止採礦。 286 | 287 | 288 | 這時再回到```geth-2```節點,查看目前的數值變化,會發現增加了 10 枚乙太幣: 289 | ```sh 290 | > web3.fromWei(eth.getBalance(pingyu), "ether"); 291 | 10 292 | ``` 293 | 294 | 之後可以在任一節點透過 eth web3 的 API 來查找指定區塊的交易資訊: 295 | ```sh 296 | > eth.getTransactionFromBlock(40) 297 | { 298 | blockHash: "0xe839c1392657731417fc04b9aecf7a181dd339086d5f7cdea0bccc2b1483b885", 299 | blockNumber: 112, 300 | from: "0xcb41ad8ba28c4b8b52eee159ef3bb6da197ff60b", 301 | gas: 90000, 302 | gasPrice: 20000000000, 303 | hash: "0x1aee9082a55751c59077a273e7b08acd028d5099a4986f002518b0c8919d9e36", 304 | input: "0x", 305 | nonce: 0, 306 | to: "0xf8c70df559cb9225f6e426d0f139fd6e8752c644", 307 | transactionIndex: 0, 308 | value: 10000000000000000000 309 | } 310 | ``` 311 | 312 | ### 簡單的 Contract 313 | 這邊將說明如何建立一個簡單的合約(Contract)來部署於區塊鏈上,首先複製以下內容: 314 | ``` 315 | contract SimpleStorage { 316 | uint storedData; 317 | function set(uint x) { 318 | storedData = x; 319 | } 320 | function get() constant returns (uint retVal) { 321 | return storedData; 322 | } 323 | } 324 | ``` 325 | 326 | 接著將內容貼到 [browser-solidity](https://ethereum.github.io/browser-solidity) 進行編譯成 JavaScript。如快照畫面所示。 327 | 328 | ![](images/snapshot-contract.png) 329 | 330 | 透過這個 IDE 可以將 Solidity 語言轉換成 web3 code(JavaScript),複製 web3 code 的內容,並儲存成```SimpleStorage.js```檔案放置到```geth-1```上。接著 attach 進入 geth 執行以下指令: 331 | ```sh 332 | > loadScript('SimpleStorage.js'); 333 | ``` 334 | 335 | 若有自行安裝```browser-solidity```的話,則可以使用如下圖一樣的方式連接。 336 | 337 | ![](images/snapshot-dash-web3-provider.png) 338 | --------------------------------------------------------------------------------