以太坊源碼目錄
Ⅰ CentOS 6.5上搭建以太坊私有鏈,編譯時報錯: make: *** [geth] Error 1,請各位大神指教
build/env.sh go run build/ci.go install ./cmd/geth
make: *** [geth] Error 1
沒有這個目錄,或者這個目錄許可權不夠
Ⅱ 怎樣開發區塊鏈 怎麼做區塊鏈開發
Go 是一個開源的編程語言,它能讓構造簡單、可靠且高效的軟體變得容易。想學習這門編程語言,首先要找到一份不錯的教程,兄弟連go語言+區塊鏈培訓最近新出了一套go語言的教程,老師講的非常不錯!
伴隨著「區塊鏈」概念在全球范圍內的熱議,金融、物流、徵信、製造、零售等日常生活場景中也悄然加入了相關區塊鏈技術應用。有專家表明,未來區塊鏈將與人們的生活息息相關,區塊鏈技術與大眾日常生活融合是大勢所趨。
區塊鏈市場的火熱引發了大量以區塊鏈技術型人員為基礎的人才性需求,區塊鏈人才受熱捧程度呈光速上升。據拉勾網發布的「2018年區塊鏈高薪清單」顯示,騰訊、小米、蘇寧、京東等國內企業巨頭發布了眾多高薪區塊鏈崗需求,力圖探索區塊鏈相關技術與應用。清單中同時指出,高薪崗位以區塊鏈相關技術型崗位需求為主,其中蘇寧和科達月薪最高已給到100k。
極大的技術型人才市場需求,必然會帶動整個區塊鏈培訓市場的爆發式涌現與增長。培訓模式大都可分為線上培訓、傳統IT機構培訓及主打高端形式的線下短期訓練營等幾種形式,但市場火爆演進過程中也充斥著種種區塊鏈培訓亂象:講師資質注水化、甚至是最基本的姓名都不敢公開,課程大綱不透明、授課質量縮水化,課時安排不合理及培訓收費標准參差不齊等等。
在整個區塊鏈培訓市場規模化發展之下,兄弟連教育攜手資深區塊鏈專家尹成及其清華水木未名團隊成立區塊鏈學院,利用其專業強大的技術講師團隊、細致全面的課程體系及海量真實性企業區塊鏈項目實戰,旨在深耕區塊鏈教培領域,並為企業為社會培養更多專業型技術人才。
尹成 資深區塊鏈技術專家 兄弟連區塊鏈學院院長畢業於清華大學,曾擔任Google演算法工程師,微軟區塊鏈領域全球最具價值專家,微軟Tech.Ed 大會金牌講師。精通C/C++、Python、Go語言、Sicikit-Learn與TensorFlow。擁有15年編程經驗與5年的教學經驗,資深軟體架構師,Intel軟體技術專家,著名技術專家,具備多年的世界頂尖IT公司微軟谷歌的工作經驗。具備多年的軟體編程經驗與講師授課經歷, 並在人機交互、教育、信息安全、廣告、區塊鏈系統開發諸多產品。具備深厚的項目管理經驗以及研發經驗, 擁有兩項人工智慧發明專利,與開發電子貨幣部署到微軟Windows Azure的實戰經驗。教學講解深入淺出,使學員能夠做到學以致用。
第一階段:區塊鏈行業及Go編程 5周
第二階段:密碼學與共識演算法 2周
第三階段:以太坊源碼解析與開發 3周
第四階段:超級賬本與Node.js 2周
第五階段:比特幣 & EOS 4周
第六階段:項目綜合性實戰
Ⅲ 一學就會,手把手教你用Go語言調用智能合約
智能合約調用是實現一個 DApp 的關鍵,一個完整的 DApp 包括前端、後端、智能合約及區塊 鏈系統,智能合約的調用是連接區塊鏈與前後端的關鍵。
我們先來了解一下智能合約調用的基礎原理。智能合約運行在以太坊節點的 EVM 中。因此要 想調用合約必須要訪問某個節點。
以後端程序為例,後端服務若想連接節點有兩種可能,一種是雙 方在同一主機,此時後端連接節點可以採用 本地 IPC(Inter-Process Communication,進 程間通信)機制,也可以採用 RPC(Remote Procere Call,遠程過程調用)機制;另 一種情況是雙方不在同一台主機,此時只能採用 RPC 機制進行通信。
提到 RPC, 讀者應該對 Geth 啟動參數有點印象,Geth 啟動時可以選擇開啟 RPC 服務,對應的 默認服務埠是 8545。。
接著,我們來了解一下智能合約運行的過程。
智能合約的運行過程是後端服務連接某節點,將 智能合約的調用(交易)發送給節點,節點在驗證了交易的合法性後進行全網廣播,被礦工打包到 區塊中代表此交易得到確認,至此交易才算完成。
就像資料庫一樣,每個區塊鏈平台都會提供主流 開發語言的 SDK(Software Development Kit,軟體開發工具包),由於 Geth 本身就是用 Go 語言 編寫的,因此若想使用 Go 語言連接節點、發交易,直接在工程內導入 go-ethereum(Geth 源碼) 包就可以了,剩下的問題就是流程和 API 的事情了。
總結一下,智能合約被調用的兩個關鍵點是節點和 SDK。
由於 IPC 要求後端與節點必須在同一主機,所以很多時候開發者都會採用 RPC 模式。除了 RPC,以太坊也為開發者提供了 json- rpc 介面,本文就不展開討論了。
接下來介紹如何使用 Go 語言,藉助 go-ethereum 源碼庫來實現智能合約的調用。這是有固定 步驟的,我們先來說一下總體步驟,以下面的合約為例。
步驟 01:編譯合約,獲取合約 ABI(Application Binary Interface,應用二進制介面)。 單擊【ABI】按鈕拷貝合約 ABI 信息,將其粘貼到文件 calldemo.abi 中(可使用 Go 語言IDE 創建該文件,文件名可自定義,後綴最好使用 abi)。
最好能將 calldemo.abi 單獨保存在一個目錄下,輸入「ls」命令只能看到 calldemo.abi 文件,參 考效果如下:
步驟 02:獲得合約地址。注意要將合約部署到 Geth 節點。因此 Environment 選擇為 Web3 Provider。
在【Environment】選項框中選擇「Web3 Provider」,然後單擊【Deploy】按鈕。
部署後,獲得合約地址為:。
步驟 03:利用 abigen 工具(Geth 工具包內的可執行程序)編譯智能合約為 Go 代碼。abigen 工具的作用是將 abi 文件轉換為 Go 代碼,命令如下:
其中各參數的含義如下。 (1)abi:是指定傳入的 abi 文件。 (2)type:是指定輸出文件中的基本結構類型。 (3)pkg:指定輸出文件 package 名稱。 (4)out:指定輸出文件名。 執行後,將在代碼目錄下看到 funcdemo.go 文件,讀者可以打開該文件欣賞一下,注意不要修改它。
步驟 04:創建 main.go,填入如下代碼。 注意代碼中 HexToAddress 函數內要傳入該合約部署後的地址,此地址在步驟 01 中獲得。
步驟 04:設置 go mod,以便工程自動識別。
前面有所提及,若要使用 Go 語言調用智能合約,需要下載 go-ethereum 工程,可以使用下面 的指令:
該指令會自動將 go-ethereum 下載到「$GOPATH/src/github.com/ethereum/go-ethereum」,這樣還算 不錯。不過,Go 語言自 1.11 版本後,增加了 mole 管理工程的模式。只要設置好了 go mod,下載 依賴工程的事情就不必關心了。
接下來設置 mole 生效和 GOPROXY,命令如下:
在項目工程內,執行初始化,calldemo 可以自定義名稱。
步驟 05:運行代碼。執行代碼,將看到下面的效果,以及最終輸出的 2020。
上述輸出信息中,可以看到 Go 語言會自動下載依賴文件,這就是 go mod 的神奇之處。看到 2020,相信讀者也知道運行結果是正確的了。
Ⅳ ZYNQ+linux網口調試筆記(3)PL-ETH
在ZYNQ上使用gigE Vision協議的網路介面相機。
第一步:調通PS側網口GEM0(Xilinx BSP默認配好)。
第二步:調通PS側網口GEM1(見前一篇文檔:開發筆記(1))。
第三步:調通PL側網口(本文闡述)。
第四步:在PL側網口上驗證Jumbo Frame特性,並在應用層適配gigE Vision協議。
根據《xapp1082》可知,PL側的PHY支持1000Base-X和SGMII兩種配置,這兩種配置對應兩種不同的PHY引腳介面(連接到MAC)。而我們的hdf文件使用的是1000Base-X的配置。
關於網口的Linux驅動,我們在官網找到一份資料: Xilinx Wiki - Zynq PL Ethernet 。資料很長,我們只看與我們相關的2.4.1 PL Ethernet BSP installation for 1000Base-X」這一章節就可以了。
首先導入FPGA設計同事提供的hdf文件:
在彈出的圖形界面里,進入Subsystem AUTO Hardware Settings——Ethernet Settings——Primary Ethernet,確認可以看到PL側網路設備axi_ethernet_0,說明hdf文件里已包含了必要的網口硬體信息:
上圖中被選中的網口將成為Linux上的設備eth0。這里我們默認選擇ps7_ethernet_0,即使用GEM0作為首選網口。
啟用Xilinx AXI Ethernet驅動
進入Device Drivers -- Network device support – 選中Xilinx AXI Ethernet(以及Xilinx Ethernet GEM,這是PS側網口的驅動)
進入Networking support – 選中 Random ethaddr if unset
進入Device Drivers -- Network device support -- PHY Device support and infrastructure – 啟用Drivers for xilinx PHYs
進入~~~~Device Drivers -- DMA Engine Support -– 禁用~~~~Xilinx AXI DMAS Engine~~~ (對應的配置項名為 ~~ CONFIG_XILINX_DMA ~~~)
注意: Xilinx Wiki里對設備樹節點的引用有誤(&axi_ethernet),導致編譯報錯,應改為&axi_ethernet_0。
註:PL-ETH驅動所在路徑:<project>/build/tmp/work-shared/plnx_arm/kernel-source/drivers/net/ethernet/xilinx/xilinx_axienet_main.c和xilinx_axienet_mdio.c。對應的內核配置項為CONFIG_NET_VENDOR_XILINX和CONFIG_XILINX_AXI_EMAC。
啟用ethtool和tcpmp(調試用,非必須):
然後將生成的BOOT.BIN和image.ub拷貝到SD卡根目錄下,將SD卡插入板子上,上電運行。
上電後,使用ifconfig eth1查看網口信息,觀察MAC地址與設置的一致,且ifconfig eth1 192.168.1.11 up沒有報錯。
測試網路通路:ping PC是通的。說明網口工作正常。
Linux下eth1(即PL-ETH)的MAC地址有誤
問題描述:
開機列印:
注意:
MAC地址是錯的,驅動里解析出的是GEM0的MAC地址。
試驗發現,即使在system-user.dtsi里不寫local-mac-address,也照樣解析出的是GEM0的MAC。
而將system-user.dtsi里的local-mac-address改名為pl-mac-address,並將驅動里解析的字元串也對應更改為pl-mac-address,則可以正確解析出來:
Passing MAC address to kernel via Device Tree Blob and U-Boot:
http://zedboard.org/content/passing-mac-address-kernel-device-tree-blob
通過更改u-boot環境變數和設備樹,為每個板子設置一個獨特的MAC地址:
https://www.xilinx.com/support/answers/53476.html
U-Boot里的環境變數ethaddr會覆蓋掉設備樹里pl-eth的local-mac-addr欄位,從而影響Linux啟動後的網卡MAC地址;
但U-Boot里的環境變數ipaddr不會對Linux啟動後的配置產生任何影響。因為設備樹里根本就沒有關於IP地址的配置。
phy-mode怎麼會是sgmii?查了下官方的提供的BSP里,也是「sgmii」。說明這個沒問題。具體原因不清楚。
@TODO: 設備樹里的中斷號的順序如何影響功能?
為何讀出來的IRQ號不對呢?這是因為這里讀到的不是硬體的中斷號,而是經過系統映射之後的軟體IRQ number。兩者不具有線性關系。
關於中斷號的疑問:
Linux上的網口eth0、eth1的順序,似乎是按照phy地址從小到大來排布的。
Xilinx xapp1082-zynq-eth.pdf (v5.0) July 16, 2018
https://www.xilinx.com/support/documentation/application_notes/xapp1082-zynq-eth.pdf
Xilinx Wiki - Zynq PL Ethernet:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841633/Zynq+PL+Ethernet
Xilinx Wiki - Linux Drivers:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841873/Linux+Drivers
Xilinx Wiki - Linux Drivers - Macb Driver:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841740/Macb+Driver
Xilinx Wiki - Zynq Ethernet Performance:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841743/Zynq+Ethernet+Performance
查到關於Jumbo frame MTU的定義,當前值為9000,可否改大一些?
驅動源碼里關於jumbo frame的說明:
設置MTU為9000,發現ping包最大長度只能設為ping 192.168.1.10 -s 1472
https://lore.kernel.org/patchwork/patch/939535/
【完】
Ⅳ 以太坊GasLimit的計算方法
以太坊黃皮書上說的gasLimit的計算方法:
gasLimit = Gtransaction + Gtxdatanonzero × dataByteLength
需要注意的是這只是靜態的gas消耗,實際gas消耗還需要加上合約執行的開銷。
計算 IntrinsicGas的源碼位置 core/state_transition.go
相關源碼位置:internal/ethapi/api.go
EstimateGas 採用二分查找法獲取要評估交易的gas值。二分查找的下限是 param.TxGas , 如果 args 參數指定 Gas 大於 param.Gas ,那麼二分查找的上限就是 args.Gas ,否則以當前pending塊的block gas limit(後面簡稱BGL)作為二分查找的上限。 doCall 函數模擬智能合約的執行,經過多次嘗試找到智能合約能夠成功運行的最佳gas值。
由於二分查找的上限和BGL有關,而BGL和不是固定不變的,因此每次gas評估的結果不一定都是相同的,可能每個區塊周期就會變動一次。
在實際進行gas評估的時候,可能會出現類似下面的錯誤
該錯誤出現的最可能是合約執行中出錯。
How do you calculate gas limit for transaction with data in Ethereum?
Ⅵ solidity 智能合約(3):使用truffle編譯部署及測試合約
先找源碼敲一遍,跑起來,後面慢慢講怎麼用solidity編寫以太坊智能合約。
這個文件編寫在 contracts 目錄下
這個文件在 migrations 目錄下
這個文件可以創建一個 test 目錄,然後放進去,我這里直接放在了根目錄,不太規范。
要編譯Truffle項目里的合約,請切換到項目工程所在根目錄,然後在終端中鍵入以下內容:
首次運行時,將編譯所有合約。 在後續運行中,Truffle將僅編譯自上次編譯以來有更改的合約。如果我們想覆蓋此行為,可以使用 --all 選項運行上面的命令。
編譯的目標文件 Artifacts 將放在 build/contracts/ 目錄中,相對於項目根目錄(如果該目錄不存在,將創建該目錄。)
這些 Artifacts 是Truffle內部工作的組成部分,它們在成功部署應用程序中起著重要作用。 不要去編輯這些文件,因為這些文件將被合約編譯和部署覆蓋。
編譯成功後
遷移腳本(JavaScript文件)可幫助我們將合約部署到以太坊網路。 這些文件負責暫存我們的部署任務,並且假設我們的部署需求會隨著時間的推移而發生變化。 隨著項目的發展,我們將創建新的遷移腳本,以進一步推動區塊鏈的發展。 先前運行的部署記錄通過特殊的 Migrations 遷移合約記錄在鏈上,詳細信息如下。
部署命令
要運行部署,請運行以下命令:
這將部署在項目的 migrations 目錄中的所有遷移文件。 最簡單的遷移只是一組管理部署腳本。 如果我們的遷移先前已成功運行,則 truffle migrate 將從上次運行的遷移開始執行,僅運行新創建的遷移。 如果不存在新的遷移, truffle migrate 將不會執行任何操作。 我們可以使用 --reset 選項從頭開始運行所有遷移。 對於本地測試,確保在執行 migrate 之前安裝並運行了 Ganache等 測試區塊鏈。
測試腳本中輸入數值 100 ,取出的數值為 64 (這個值是16進制格式,轉為十進制就是 100 ).
Ⅶ linux挖礦怎麼提現
用哈魚礦工的服務啊,用你的手機號在Linux挖礦,然後在他們網站通過手機提現,直接提現到支付寶,具體操作步驟如下:
如何使用Linux系統挖礦,要使用到哈魚礦工的服務,只需要兩步,就可以在Linux系統上挖礦。
打開網站,輸入手機號,選擇你要使用多少CPU來挖礦,默認為使用50%的CPU進行挖礦,點擊生成你的專屬命令並復制
只需要兩步,你就可以在Linux系統上挖礦,你所挖的錢只需要到哈魚礦工網站上,輸入你的手機號即可提現。
Ⅷ 以太坊多節點私有鏈部署
假設兩台電腦A和B
要求:
1、兩台電腦要在一個網路中,能ping通
2、兩個節點使用相同的創世區塊文件
3、禁用ipc;同時使用參數--nodiscover
4、networkid要相同,埠號可以不同
1.4 搭建私有鏈
1.4.1 創建目錄和genesis.json文件
創建私有鏈根目錄./testnet
創建數據存儲目錄./testnet/data0
創建創世區塊配置文件./testnet/genesis.json
1.4.2 初始化操作
cd ./eth_test
geth --datadir data0 init genesis.json
1.4.3 啟動私有節點
1.4.4 創建賬號
personal.newAccount()
1.4.5 查看賬號
eth.accounts
1.4.6 查看賬號余額
eth.getBalance(eth.accounts[0])
1.4.7 啟動&停止挖礦
啟動挖礦:
miner.start(1)
其中 start 的參數表示挖礦使用的線程數。第一次啟動挖礦會先生成挖礦所需的 DAG 文件,這個過程有點慢,等進度達到 100% 後,就會開始挖礦,此時屏幕會被挖礦信息刷屏。
停止挖礦,在 console 中輸入:
miner.stop()
挖到一個區塊會獎勵5個以太幣,挖礦所得的獎勵會進入礦工的賬戶,這個賬戶叫做 coinbase,默認情況下 coinbase 是本地賬戶中的第一個賬戶,可以通過 miner.setEtherbase() 將其他賬戶設置成 coinbase。
1.4.8 轉賬
目前,賬戶 0 已經挖到了 3 個塊的獎勵,賬戶 1 的余額還是0:
我們要從賬戶 0 向賬戶 1 轉賬,所以要先解鎖賬戶 0,才能發起交易:
發送交易,賬戶 0 -> 賬戶 1:
需要輸入密碼 123456
此時如果沒有挖礦,用 txpool.status 命令可以看到本地交易池中有一個待確認的交易,可以使用 eth.getBlock("pending", true).transactions 查看當前待確認交易。
使用 miner.start() 命令開始挖礦:
miner.start(1);admin.sleepBlocks(1);miner.stop();
新區塊挖出後,挖礦結束,查看賬戶 1 的余額,已經收到了賬戶 0 的以太幣:
web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
用同樣的genesis.json初始化操作
cd ./eth_test
geth --datadir data1 init genesis.json
啟動私有節點一,修改 rpcport 和port
可以通過 admin.addPeer() 方法連接到其他節點,兩個節點要要指定相同的 chainID。
假設有兩個節點:節點一和節點二,chainID 都是 1024,通過下面的步驟就可以從節點二連接到節點一。
首先要知道節點一的 enode 信息,在節點一的 JavaScript console 中執行下面的命令查看 enode 信息:
admin.nodeInfo.enode
" enode://@[::]:30303 "
然後在節點二的 JavaScript console 中執行 admin.addPeer(),就可以連接到節點一:
addPeer() 的參數就是節點一的 enode 信息,注意要把 enode 中的 [::] 替換成節點一的 IP 地址。連接成功後,節點一就會開始同步節點二的區塊,同步完成後,任意一個節點開始挖礦,另一個節點會自動同步區塊,向任意一個節點發送交易,另一個節點也會收到該筆交易。
通過 admin.peers 可以查看連接到的其他節點信息,通過 net.peerCount 可以查看已連接到的節點數量。
除了上面的方法,也可以在啟動節點的時候指定 --bootnodes 選項連接到其他節點。 bootnode 是一個輕量級的引導節點,方便聯盟鏈的搭建 下一節講 通過 bootnode 自動找到節點
參考: https://cloud.tencent.com/developer/article/1332424
Ⅸ 【深度知識】以太坊數據序列化RLP編碼/解碼原理
RLP(Recursive Length Prefix),中文翻譯過來叫遞歸長度前綴編碼,它是以太坊序列化所採用的編碼方式。RLP主要用於以太坊中數據的網路傳輸和持久化存儲。
對象序列化方法有很多種,常見的像JSON編碼,但是JSON有個明顯的缺點:編碼結果比較大。例如有如下的結構:
變數s序列化的結果是{"name":"icattlecoder","sex":"male"},字元串長度35,實際有效數據是icattlecoder 和male,共計16個位元組,我們可以看到JSON的序列化時引入了太多的冗餘信息。假設以太坊採用JSON來序列化,那麼本來50GB的區塊鏈可能現在就要100GB,當然實際沒這么簡單。
所以,以太坊需要設計一種結果更小的編碼方法。
RLP編碼的定義只處理兩類數據:一類是字元串(例如位元組數組),一類是列表。字元串指的是一串二進制數據,列表是一個嵌套遞歸的結構,裡面可以包含字元串和列表,例如["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]就是一個復雜的列表。其他類型的數據需要轉成以上的兩類,轉換的規則不是RLP編碼定義的,可以根據自己的規則轉換,例如struct可以轉成列表,int可以轉成二進制(屬於字元串一類),以太坊中整數都以大端形式存儲。
從RLP編碼的名字可以看出它的特點:一個是遞歸,被編碼的數據是遞歸的結構,編碼演算法也是遞歸進行處理的;二是長度前綴,也就是RLP編碼都帶有一個前綴,這個前綴是跟被編碼數據的長度相關的,從下面的編碼規則中可以看出這一點。
對於值在[0, 127]之間的單個位元組,其編碼是其本身。
例1:a的編碼是97。
如果byte數組長度l <= 55,編碼的結果是數組本身,再加上128+l作為前綴。
例2:空字元串編碼是128,即128 = 128 + 0。
例3:abc編碼結果是131 97 98 99,其中131=128+len("abc"),97 98 99依次是a b c。
如果數組長度大於55, 編碼結果第一個是183加數組長度的編碼的長度,然後是數組長度的本身的編碼,最後是byte數組的編碼。
請把上面的規則多讀幾篇,特別是數組長度的編碼的長度。
例4:編碼下面這段字元串:
The length of this sentence is more than 55 bytes, I know it because I pre-designed it
這段字元串共86個位元組,而86的編碼只需要一個位元組,那就是它自己,因此,編碼的結果如下:
184 86 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116
其中前三個位元組的計算方式如下:
184 = 183 + 1,因為數組長度86編碼後僅佔用一個位元組。
86即數組長度86
84是T的編碼
例5:編碼一個重復1024次"a"的字元串,其結果為:185 4 0 97 97 97 97 97 97 ...。
1024按 big endian編碼為004 0,省略掉前面的零,長度為2,因此185 = 183 + 2。
規則1~3定義了byte數組的編碼方案,下面介紹列表的編碼規則。在此之前,我們先定義列表長度是指子列表編碼後的長度之和。
如果列表長度小於55,編碼結果第一位是192加列表長度的編碼的長度,然後依次連接各子列表的編碼。
注意規則4本身是遞歸定義的。
例6:["abc", "def"]的編碼結果是200 131 97 98 99 131 100 101 102。
其中abc的編碼為131 97 98 99,def的編碼為131 100 101 102。兩個子字元串的編碼後總長度是8,因此編碼結果第一位計算得出:192 + 8 = 200。
如果列表長度超過55,編碼結果第一位是247加列表長度的編碼長度,然後是列表長度本身的編碼,最後依次連接各子列表的編碼。
規則5本身也是遞歸定義的,和規則3相似。
例7:
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
的編碼結果是:
248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116
其中前兩個位元組的計算方式如下:
248 = 247 +1
88 = 86 + 2,在規則3的示例中,長度為86,而在此例中,由於有兩個子字元串,每個子字元串本身的長度的編碼各佔1位元組,因此總共佔2位元組。
第3個位元組179依據規則2得出179 = 128 + 51
第55個位元組163同樣依據規則2得出163 = 128 + 35
例8:最後我們再來看個稍復雜點的例子以加深理解遞歸長度前綴,
["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]]
編碼結果是:
248 94 131 97 98 99 248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116
列表第一項字元串abc根據規則2,編碼結果為131 97 98 99,長度為4。
列表第二項也是一個列表項:
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
根據規則5,結果為
248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116
長度為90,因此,整個列表的編碼結果第二位是90 + 4 = 94, 佔用1個位元組,第一位247 + 1 = 248
以上5條就是RPL的全部編碼規則。
各語言在具體實現RLP編碼時,首先需要將對像映射成byte數組或列表兩種形式。以go語言編碼struct為例,會將其映射為列表,例如Student這個對象處理成列表["icattlecoder","male"]
如果編碼map類型,可以採用以下列表形式:
[["",""],["",""],["",""]]
解碼時,首先根據編碼結果第一個位元組f的大小,執行以下的規則判斷:
1.如果f∈ [0,128),那麼它是一個位元組本身。
2.如果f∈[128,184),那麼它是一個長度不超過55的byte數組,數組的長度為 l=f-128
3.如果f∈[184,192),那麼它是一個長度超過55的數組,長度本身的編碼長度ll=f-183,然後從第二個位元組開始讀取長度為ll的bytes,按照BigEndian編碼成整數l,l即為數組的長度。
4.如果f∈(192,247],那麼它是一個編碼後總長度不超過55的列表,列表長度為l=f-192。遞歸使用規則1~4進行解碼。
5.如果f∈(247,256],那麼它是編碼後長度大於55的列表,其長度本身的編碼長度ll=f-247,然後從第二個位元組讀取長度為ll的bytes,按BigEndian編碼成整數l,l即為子列表長度。然後遞歸根據解碼規則進行解碼。
以上解釋了什麼叫遞歸長度前綴編碼,這個名字本身很好的解釋了編碼規則。
(1) 以太坊源碼學習—RLP編碼( https://segmentfault.com/a/1190000011763339 )
(2)簡單分析RLP編碼原理
( https://blog.csdn.net/itchosen/article/details/78183991 )