年薪百萬的技術面試都問啥?來收下這份必考題葵花寶典吧|套路
隨著各大企業紛紛佈局區塊鏈,各行業對區塊鏈人才求賢若渴,區塊鏈從業者的待遇也是水漲船高。
動輒百萬的年薪+通證激勵,不知你是否已經蠢蠢欲動。不過區塊鏈涉及的領域既多且雜,在面試中你不僅需要有牢固的知識儲備,還需要一本“面試葵花寶典”以防萬一。
話不多說,上乾貨。
作者 | John Baker
譯者 | Guoxi
話說,區塊鏈行業對人才的缺口越來越大,但由於區塊鏈涉及的知識領域較為廣泛,能找到真正有用的人才對每個企業來說都非常不易。
另一方面,由於區塊鏈行業「待遇高」、「前途好」,很多人以次充好,做了幾天開發就敢自成專家。那麼真正的區塊鏈人才究竟應該具備哪些知識?
作為想要在區塊鏈領域發展的你,又該如何通過區塊鏈企業的技術面試?俗話說知己知彼百戰不殆,瞭解了企業的面試套路,才能邁出區塊鏈的決勝的第一步。
本篇文章「 套路滿滿 」,營長將從各方瞭解到的企業常見的面試問題著手,從「區塊鏈」、「智慧合約」、「Solidity」、「DApp」、「Web 3.0 」 、「核心技術」、「函式」等幾個方面, 列出在面試技術崗位中最常問的問題,並給出標準的技術解答 。
是月薪八千,還是百萬年薪,就看你能記住多少了, 營長只能幫你到這了~
01
區塊鏈面試真經
(1)以太坊常見問題
問:在以太坊中,Wei和Ether(以太幣)有什麼區別?
答: Wei是以太幣的最小面值,就好比說人民幣的最小面值是分,英鎊的最小面值是便士。 其換算關係為1以太幣 =10^18Wei。
問:以太坊的平均區塊間隔時間是多少?
答: 平均區塊間隔時間為14秒,當然了這只是理論值,你可以在Etherscan
(https://etherscan.io/chart/blocktime)
中查到每日的平均區塊時間間隔。
問:以太坊的平均區塊大小是多少?
答: 區塊大小視情況而定,大約是 2KB 。不同於比特幣使用區塊大小來規定區塊的交易量上限,以太坊使用燃料(gas)限制。燃料限制決定了每個區塊中處理的交易量、儲存/頻寬的上限,因為交易和智慧合約中函式的執行都要根據指令的複雜度多少來付出相應的燃料,所以使用燃料限制來約束區塊大小是可行的。
燃料限制會隨網路的波動和礦工的意願變化,每個礦工都可以選擇自己願意接受的燃料價格。燃料價格就像是比特幣中的交易費,只是這裡的價格是最小單位燃料的價格,而不是每筆交易的價格。
想要算出一個區塊中可以容納多少筆交易,你不需要清楚地知道燃料的價格,只需知道平均每筆交易使用多少燃料並用整個燃料限制除以它即可。
去年以太貓的發行造成了以太坊網路的大擁堵,整個網路中充斥著大量未被處理的交易。在這種情況下礦工有兩種選擇。他們可以投票提高燃料限制來處理更多交易,也可以開始提高自己的燃料價格標準並拒絕處理燃料費用過低的交易。
與比特幣一樣,即使燃料價格很低的交易也可能會被處理加入區塊鏈中,但礦工肯定會先處理完燃料價格高的交易再處理它。如果你的交易並沒有那麼緊急,設定一個很低的燃料價格也不是不可以,就像我們現實生活中的“花時間來節省金錢”。
如果有惡意使用者持續地發起海量交易堵塞網路,全網的交易成本就會越來越高,直到這個惡意使用者用完資金或者礦工賺足了交易費並決定擴大網路容量。
問:以太幣是如何產生的?
答: 2014年以太坊專案以眾籌的形式建立並預售了6000萬個以太幣,除此之外,礦工挖礦也會生成新的以太幣。
問:以太坊中的節點是什麼?
答: 從本質上來說,節點是一臺連線到區塊鏈、可以處理交易的計算機。
問:以太坊都有哪些網路?
答: 以太坊共有三種類型的網路: 以太坊主鏈 (就是我們平時用的以太坊)、 以太坊測試網路 (如Ropsten和Rinkeby,供開發人員的學習和測試)和 以太坊私有鏈 (也叫以太坊私有網路,任何人都能用以太坊的程式碼部署自己的私有鏈)。
問:與以太坊網路互動都哪些方法?
答: 你可以使用電子錢包或DApp。
問:你是否能在以太坊中“隱藏”一筆交易?
答: 不能。以太坊區塊鏈中所有的交易都是公開可見的。
問:以太坊的交易記錄存放在哪裡?
答: 在公共可見的賬本中,這個帳本通常被稱為區塊鏈。
問:以太坊主鏈已經很強大了,為什麼還要使用以太坊私有鏈?
答: 原因有很多,主要是因為資料涉及隱私,將資料庫去中心化,許可權控制和測試。
問:如何檢視一筆交易或一個區塊的詳細資訊?
答: 你可以使用區塊鏈瀏覽器,如etherscan.io或live.ether.camp。
問:如何檢視私有鏈中一筆交易或一個區塊的詳細資訊?
答: 一些開源的區塊鏈瀏覽器滿足這種需求,如etherparty推出的區塊鏈瀏覽器
(https://github.com/etherparty/explorer)。
問:區塊鏈的共識過程是什麼?
答: 共識是按照特定的協議(如以太坊的協議)驗證交易,將交易打包進區塊並加入區塊鏈的過程。
問:以太坊挖礦操作的工作原理是什麼呢?
答: 從原理上說,以太坊中的挖礦操作幾乎與比特幣相同。
“套路”
簡單地說,就是對於每個包含交易的區塊,礦工使用計算機反覆且非常快速地試驗謎題的答案,直到有一個礦工猜對謎題。
更具體地說,礦工將當前區塊唯一的區塊頭元資料(包括時間戳和軟體版本)和一個隨機數(nonce value)作為雜湊函式的輸入,函式將返回一個固定長度、看起來像是由數字和字母隨機組成的亂碼,叫做雜湊值。雜湊函式的特性是不同輸入對應不同的雜湊值,因此礦工僅需改變隨機數的值,就會得到一個完全不同的雜湊值。
如果算出來的雜湊值小於當前的目標值(挖礦難度),則這個礦工就挖出了一個區塊,他會獲得一些以太幣獎勵,然後通過向全網路廣播該區塊,其他節點可以驗證該區塊中的交易,驗證通過後將該區塊加入到本地區塊鏈的副本中。也就是說,如果礦工B算出了一個雜湊值,礦工A將立刻停止當前區塊的雜湊值計算,把B挖出的區塊加入區塊鏈中並開始新一輪的雜湊值計算。
礦工們很難在這場算力競爭中作弊。為了得到迷題的答案,除了一個個試沒有更好的辦法,也沒有偽造這些計算工作的可能,這就是該解謎方法被稱為“工作量證明”的原因。
從另一方面來說,使用者不需要來驗證雜湊值是否正確,因為每個節點都已驗證過。
一般來說,每12到15秒就會有一個礦工挖出一個新區塊。如果礦工解謎的時間開始出現更快或更慢的傾向,演算法會自動調整問題的難度,以使礦工解謎的時間穩定在14秒左右。
礦工有一定機率能挖到新區塊賺取以太幣獎勵,他們的賺錢能力取決於運氣和他們投入的計算能力。
以太坊使用的工作量證明演算法被稱為“ethash”,它被設計的需要更多記憶體,從而增大了使用昂貴的ASIC礦機挖礦的難度,因為ASIC礦機的出現嚴重壓榨了使用其他裝置礦工的收益,以至於在比特幣中唯一能盈利的挖礦形式就是使用這種定製化的晶片。
從某種意義上來說,ethash可能已經成功實現了這一目標,因為專用的ASIC礦機不能用於挖掘以太坊(至少目前還沒有)。
此外,由於以太坊將要從工作量證明挖礦逐步過渡到權益證明挖礦,因而購買ASIC礦機可能不是一個明智的選擇,因為一旦以太坊轉向權益證明它必將被淘汰。
問:區塊鏈中最常用的兩種共識協議是什麼?
答: 工作量證明(PoW)和權益證明(P o S),業界也在不斷湧現新的共識協議,比如說活動證明(Proof-of-Activity,PoA)。
問:請簡述權益證明的工作原理。
答: 權益證明就是根據持有貨幣的數量和時間隨機選擇區塊的建立者,它不是計算密集型的挖礦形式。
問:以太坊使用哪種共識協議呢?
答: 截至2018年初,以太坊使用工作量證明建立共識,但在未來它將轉向權益證明。
活動證明在比特幣的工作量證明中引入了一種新形式的激勵結構,這種混合結構結合了工作量證明和權益證明。為避免系統出現惡性通貨膨脹,應該停發新的加密貨幣,也就是說礦工的挖礦行為不再能拿到挖礦獎勵。
這樣系統中的加密貨幣數量就恆定了。在活動證明中,礦工使用工作量證明產生區塊,加密貨幣的持有者通過權益證明簽署區塊,交易費將按比例分給礦工和簽署該塊的驗證人。
問:簽署一筆交易需要用到什麼工具?
答: 使用者的私鑰。
問:在私鑰丟失後,使用者是否還可以恢復以太坊帳戶?
答: 是的,使用者可以使用12字助記詞恢復。
問:用什麼方法可以連線到以太坊節點?
答: IPC-RPC,JSON-RPC和WS-RPC(RPC指Remote Procedure Call,遠端過程呼叫)。
問:以太坊中異常火爆的Geth是什麼呢?
答: Geth是以太坊的一個命令列客戶端。
問:連線到Geth客戶端的預設方式是什麼?
答: 預設情況下使用IPC-RPC,禁用其他所有的RPC。
問:Geth客戶端中都有哪些API(Application Programming Interface,應用程式程式設計介面)?
答: Admin(管理員)、 eth(以太幣)、web3、miner(礦工)、net(網路)、personal(個人)、shh、debug(除錯)和 txpool(工具)。
問:你可以使用哪些RPC通過網路連線到Geth客戶端?
答: 你可以使用JSON-RPC或WS-RPC通過網路連線到Geth客戶端。 IPC-RPC只能用來連線本地部署的Geth客戶端。
問:如果你輸入命令“--rpc”,啟用的是哪一個RPC?
答:JSON-RPC。
問: 預設情況下哪些RPC API是啟用的?
答: eth(以太幣)、 web3和net(網路)。
問:如何為JSON-RPC啟用admin api?
答: 輸入命令“--rpcapi”。
問:命令“--datadir”有什麼功能?
答: 它指定了區塊鏈的儲存位置。
問:Geth的“快速”同步是什麼,為什麼它更快速呢?
答: “快速”同步僅下載收款交易所在的區塊,並拉取(pull)整個最近狀態資料庫,而不是像普通同步一樣,下載整個區塊鏈的資料並重放所有發生的交易。
問:命令“--testnet”有什麼功能?
答: 它將客戶端連線到以太坊Ropsten測試網路。
問:啟動Geth客戶端會在螢幕上列印大量的輸出資訊,如果不想被這些繁雜資訊干擾該怎麼辦?
答: 使用“--verbosity”命令調低輸出資訊複雜度的值(預設值為3)。
問:如何使用IPC-RPC連線兩個Geth客戶端?
答: 首先啟動一個Geth客戶端,複製其管道位置(pipe location),然後使用相同的資料文件儲存目錄(datadir)啟動另一個Geth客戶端,並使用”--attach”命令傳遞複製的管道位置。
問:如何將自定義javascript檔案載入到Geth控制檯?
答: 輸入”--preload”命令和檔案的路徑即可。
問:Geth客戶端中帳戶儲存在哪裡?
答: 儲存在金鑰庫(keystore)目錄中。
問:如何使用給定的賬戶發起一筆交易?
答: 首先你要在“ --unlock ”命令中傳入帳戶地址或索引來解鎖賬戶。然後你需要使用“- -password ”命令指定一個此賬戶的密碼檔案。
問:我們剛才說到了有關索引的內容。賬戶的索引取決於什麼?
答: 取決於你新增帳戶的順序。
問:Geth客戶端是否能用來挖礦?
答: 是的,輸入“--mine”命令即可。
問:挖礦選項中的“etherbase”是什麼?
答: 這是接受挖礦獎勵的帳戶地址,該帳戶的索引為0。
(2)智慧合約常見問題
問:ABI是什麼?
答: 簡單來說,“ABI”就是低級別的“API”。
ABI(Application Binary Interface)應用程式二進位制介面,從本質上講就是你呼叫智慧合約中的函式並獲取它返回值的方式。
ABI中定義瞭如何呼叫智慧合約中的函式以及應該選用哪種二進位制格式將資訊從一個程式元件傳遞到下一個程式元件的詳細資訊。
以太坊智慧合約以位元組碼的形式部署在以太坊區塊鏈上,一個智慧合約中可能會有多個函式。所以說,有了ABI你才可以指定呼叫智慧合約中的哪個函式,才能保證函式的返回值是你期望的格式。
這是一個來自以太坊ABI規範的例子:
contract Foo { function bar(real[2] xy) {} function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; } function sam(bytes name, bool z, uint[] data) {} }
如果我們想使用引數“69”和“真”呼叫函式baz(),我們總共會傳遞68位元組的資料,整個過程可以分解為:
0xcdcd77c0:baz()函式的ID。這是函式baz(uint32,bool)以ASCII形式編碼的Keccak-256雜湊值的前4個位元組。
0x0000000000000000000000000000000000000000000000000000000000000045 :
傳入函式baz()的第一個引數,32位無符號整數69被填充為32個位元組(10進制中的69換算成16進製為45)。
0x00000000000000000000000000000000000000000000000000000000000000000001 :
傳入函式baz()的第二個引數,布林值真,也就是1,被填充為32個位元組。
這68個位元組會存放在交易的資料欄位(data),需要注意的是,一定要仔細檢查交易資料欄位中新增的內容,因為在將其傳遞給智慧合約時可能會產生意外的,甚至可能是惡意的副作用。)
為了避免出現生成函式ID時的常見錯誤,在此過程中必須使用規範的資料型別,就比如說使用標準的256位無符號整型(uint256)而不是無符號整型(uint)。
在Solidity中計算上述sam()函式ID的的程式碼如下:
bytes4(sha3("sam(bytes,bool,uint256[])")
在這裡可以使用諸如web3.js等高階程式庫來抽象大部分的細節,不過提供給web3.js的JSON格式ABI是必不可少的。
注意: ABI是一個抽象,它並不是以太坊核心協議的一部分 。任何人都可以為自己的智慧合約定義專屬的ABI,這些智慧合約的任何呼叫者都必須遵守該ABI的規定才能得到有意義的呼叫結果。但是,對於所有開發人員來說,使用Solidity,Serpent和web3.js更為簡單,這些也都符合ABI的規定。
問:智慧合約是什麼?
答: 從本質上說,智慧合約就是用多種語言編寫的計算機程式碼。智慧合約存在於區塊鏈網路上,它們按照自身嵌入的規則執行相關操作,可以看做是參與者之間的契約。
問:智慧合約可以用哪種語言編寫?
答: 最常用的語言是Solidity,除此之外還有一些小眾的語言,比如說Serpent和類Lisp語言。
問:智慧合約都有什麼樣的使用場景呢?
答: 舉一個簡單的商品買賣場景,買方在以太坊中部署一個智慧合約並向其中存入資金,賣方看到存入的資金後傳送商品,買方收到商品後通過智慧合約支付貨款。這裡的智慧合約可以看作是一個保障淘寶交易的去中心化的支付寶。
問:什麼是MetaMask?
答: Metamask是一款外掛型別的以太坊錢包,可以幫助使用者在瀏覽器中與以太坊網路進行互動。
問:Metamask使用什麼節點?
答: 它使用infura.io。
問:相比於傳統以太坊錢包,有哪些功能是Metamask不支援的?
答: 它不支援採礦和部署智慧合約。
問:智慧合約的執行是免費的嗎?
答: 不,只能通過執行交易來呼叫智慧合約,而交易需要燃料費用。
問:檢視智慧合約的狀態是免費的嗎?
答: 是的,查詢狀態不需要執行交易。
問:誰來執行智慧合約?
答: 礦工。
問:為什麼呼叫智慧合約中的函式需要花錢?
答: 除了一些不會改變智慧合約狀態,除了返回值之外沒有其他邏輯的函式之外,呼叫智慧合約中的函式都是需要花錢的。
這筆花費中,除了向智慧合約中轉入以太幣執行呼叫之外,呼叫改變智慧合約狀態的函式需要花費燃料來執行。
問:為什麼以太坊中要引入燃料費用呢?
答: 因為礦工使用自己的計算機(礦機)執行智慧合約程式碼,礦工如果能收回購買機器的成本並獲得盈利才能保證整個系統生態的安全性,所以以太坊設計使得礦工可以通過執行呼叫者請求的程式碼來賺取燃料費用,從而維持一個健康的生態。
問:燃料價格是否能決定交易被處理的時間?
答: 是的,也不全是。一般來說,你支付的燃料價格越高,交易越有可能被加入區塊鏈。儘管如此,燃料價格並不能保證交易更快地被處理。
問:交易中的燃料使用量取決於什麼?
答: 燃料使用量取決於儲存的用量,指令(操作碼)的型別和數量。每一條以太坊虛擬機器的操作碼都明確規定了所需燃料的數量。
問:交易費該如何計算?
答: 交易費 = 使用的燃料數量 * 燃料價格 (燃料價格由交易者指定)。
問:如果執行智慧合約的花費少於交易者支付的燃料費用,他是否會獲得退款?
答: 是的。
問:如果執行智慧合約的花費超過了交易者支付的燃料費用,這時會發生什麼?
答: 使用者不會獲得退款,並且一旦所有燃料耗盡執行就會停止,智慧合約的狀態就不會改變。
問:誰來支付呼叫智慧合約的費用?
答: 呼叫智慧合約的使用者。
問:節點在哪裡執行智慧合約的程式碼呢?
答: 節點在以太坊虛擬機器(EVM)中執行智慧合約的程式碼。以太坊虛擬機器規範是以太坊協議的一部分。以太坊虛擬機器只是節點執行的一個程序。
問:以太坊虛擬機器需要什麼工具來執行智慧合約?
答: 它需要智慧合約的位元組碼,它由高級別語言(如Solidity)編譯生成。
問:以太坊虛擬機器都包含哪些部分?
答: 記憶體區域,堆疊和執行引擎。
問:Remix是什麼?
答: Remix是一個用於開發,測試和部署智慧合約的線上工具。它非常適合快速構建和測試輕量級的智慧合約,但不適用於複雜的智慧合約。
問:在Remix中,你可以連線哪些節點?
答: 你可以使用Metamask錢包連線到公共節點,使用Geth錢包連線到本地節點以及使用Javascript虛擬機器連線到記憶體中模擬的節點。
問:什麼是DApp,它與普通App有什麼不同?
答: 應用程式通常包含一個與某些中心化資源(由組織擁有)互動的客戶端,通常有一個與中心化資料層相連的中間層。如果中心化資料層中的資料丟失,則無法(輕鬆)恢復。
DApp表示去中心化的應用程式。DApp通過智慧合約與區塊鏈網路互動,它們使用的資料駐留在智慧合約的例項中,與中心化的資料相比,去中心化的資料安全性更高。
(3)Solidity常見問題
問:Solidity是靜態型別語言(型別的檢查是在執行前做的,如編譯階段)還是動態型別語言(型別的檢查是在執行時做的)?
答: Solidity是靜態型別語言,這意味著型別在編譯階段是已知的。
問:Solidity中的什麼結構與Java中的類(Class)相對應?
答: 智慧合約。
問:智慧合約的例項是什麼?
答: 智慧合約的例項就是在區塊鏈上部署的一個智慧合約。
問:Java和Solidity之間存在哪些差異。
答: 相比於Java,Solidity支援多繼承(multiple inheritance),但不支援方法過載(Overloading)。
問:在Solidity檔案中需要指定的第一個引數是什麼?
答: 第一個引數是Solidity編譯器的版本,需要指定為^ 0.4.8。不要小看了這一步,因為它可以避免出現在使用其他版本編譯器進行編譯時引入的不相容錯誤。
問:一個智慧合約包含什麼?
答: 智慧合約主要由儲存變數,函式和事件組成。
問:智慧合約中都有哪些型別的函式?
答: 有建構函式(constructor),回退函式(fallback function),常量函式(constant functions)和修改智慧合約狀態的函式。
問:如果我將多個智慧合約定義放入單個Solidity檔案中,會出現什麼樣的錯誤?
答: 將多個智慧合約定義放入單個Solidity檔案中是完全可行的。
問:兩個智慧合約可以通過哪些方式進行互動?
答: 一個智慧合約可以呼叫、建立和繼承另一個智慧合約。
問:當你嘗試部署具有多個智慧合約的檔案時會發生什麼?
答: 編譯器只會部署該檔案中的最後一個智慧合約,也就是說,其他所有智慧合約都被忽略了。
問:如果我有一個龐大的專案,我是否需要將所有相關的智慧合約儲存在一個檔案中?
答: 不需要,你可以使用import語句匯入檔案,如下所示:
import “./MyOtherContracts.sol”;
問:我是否只能匯入本地檔案?
答: 不,你也可以使用HTTP匯入檔案(甚至是Github上的檔案),如下所示:
import “http://github.com/<owner>/<repo>/<path to the file>”
問:以太坊虛擬機器的記憶體都有哪些部分?
答: 儲存(Storage)、記憶體(Memory)和Calldata。
問:請解釋一下儲存(Storage)。
答: 可以把儲存想象成一個數據庫。每個智慧合約都管理自己的儲存變數,從而得到一個鍵值對資料庫(256位的鍵和值)。儲存與普通資料庫的唯一區別就是,由於存在燃料費用的問題它讀取和寫入操作的成本更高。
問:請解釋一下記憶體(Memory)。
答: 記憶體是一個臨時性的儲存。當函式呼叫執行完畢後,記憶體中的資料將會被釋放。你可以在記憶體中分配各種複雜的資料型別,如陣列和結構體。
問:請解釋一下Calldata。
答: Calldata可以理解為一個函式呼叫堆疊(Callstack)。它是臨時的,不可修改的,它儲存著以太坊虛擬機器的執行資料。
問:儲存區和記憶體區分別儲存了哪些變數?
答: 狀態變數和區域性變數(通常區域性變數都是對狀態變數的引用)位於儲存區中,而函式的引數位於記憶體區中。
問:閱讀以下程式碼,請解釋程式碼的哪一部分對應哪個記憶體區域:
contract MyContract { // part 1 uint count; uint[] totalPoints; function localVars(){ // part 2 uint[] localArr; // part 3 uint[] memory memoryArr; // part 4 uint[] pointer = totalPoints; } }
答: 第1部分 - 儲存。
第2部分 - 儲存(陣列大小指向計數器的位置)
第3部分 – 記憶體。
第4部分 – 對儲存的引用。
問:我是否可以這樣定義一個函式:
function doSomething(uint[] storage args) internal returns(uint[] storage data) {…}
答: 是的,你可以強制函式的引數為儲存型別。在這種情況下,如果你沒有向函式中傳入儲存引用,編譯器將會抱怨。
問:EVM呼叫和非EVM呼叫之間有什麼區別呢?
答:
-
EVM呼叫是智慧合約中的函式呼叫,它觸發函式執行並需要燃料。
-
非EVM呼叫讀取公開可見的資料,不需要燃料。
問:如何設定智慧合約的以太幣餘額限制,如果向有餘額限制的智慧合約中傳送超額的以太幣會發生什麼?
答:
pragma solidity ^0.4.19; contract yourContract{ uint256 public balanceLimit = 999; function () payable{ if (this.balance + msg.value > balanceLimit) { throw;//超額後會回滾。 } } }
問:如何在智慧合約帳戶中設定msg.val的值?
答: msg.val => msg.value =
隨訊息傳送的wei的個數。
(4)DApp和web3.0常見問題
問:DApp是什麼?
答: 去中心化應用程式(DApp)是在點對點網路的計算機上而不是單臺計算機上執行的應用程式。去中心化應用程式自點對點網路出現以來就已經存在,它是一種旨在以不受任何實體控制的方式存在於Internet上的軟體工具。
-
去中心化應用程式不一定需要在區塊鏈網路上執行 。 BitTorrent(去中心化下載軟體)、Popcorn Time(去中心化視訊軟體)、BitMessage(去中心化通訊協議)、Tor(洋蔥路由)都是在點對點網路上執行的傳統去中心化應用程式,它們都沒有在區塊鏈上執行(區塊鏈是一種特殊的點對點網路)。
-
與簡單的智慧合約相反 ,在比特幣的經典使用場景,即使用者A向用戶B匯款,去中心化應用程式的參與者可以是市場中的任意一個人。
問:DApp與智慧合約有何不同?
答:去中心化應用程式是一個基於區塊鏈的網站,其中智慧合約允許它連線到區塊鏈中。說起來有點繞,為了更好地理解去中心化應用程式和智慧合約,讓我們先來了解傳統網站的工作方式。
-
傳統的Web(網路)應用程式在前端使用HTML,CSS和Javascript來呈現頁面,在後端它需要利用API從資料庫中獲取一些詳細資訊,比如使用者的使用者名稱和頭像。當你進入網頁版的新浪微博時,該頁面將呼叫API來獲取你的個人資料並將其顯示在頁面上。也就是說,傳統網站的工作方式為:前端→API→資料庫。
-
去中心化應用程式類似於傳統的Web應用程式。它在前端使用完全相同的技術來呈現頁面。一個關鍵的區別是,去中心化應用程式不使用API來連線到資料庫,而是使用智慧合約連線到區塊鏈。所以說,基於去中心化應用程式的網站的工作方式為:前端→智慧合約→區塊鏈。
在傳統的中心化應用程式中,後端程式碼在中心化的伺服器上執行。而去中心化應用程式與之相反,它的後端程式碼在去中心化的點對點網路上執行。去中心化應用程式包括從後端到前端的整個軟體包,智慧合約只是去中心化應用程式的一部分。
也就是說,DApp包括:
-
前端 (你能看到的頁面),和
-
後端 (應用程式後臺的邏輯)。
另一方面,智慧合約僅包含後端,通常只是整個DApp的一小部分。 這意味著如果你想在智慧合約系統上建立去中心化的應用程式,你必須與多個智慧合約相結合並依賴第三方系統作為前端 。
問:前端使用什麼工具連線到後端的智慧合約?
答: Web3 API程式庫。
問:請列幾個你所知道的DApp。
答: Golem(單詞含義:傀儡),Golem專案旨在建立業界首個閒置計算機算力的全球市場;Augur(單詞含義:預兆),Augur專案旨在將預測市場與去中心化網路相結合,建立一個預測工具,以獲得潛在的收益;Aragon Network,它旨在充當一個方便使用者的數字化管理組織。
問:你需要什麼工具與DApp的智慧合約進行互動?
答: 需要智慧合約的ABI和位元組碼。
問:ABI的作用是什麼?
答: ABI是智慧合約公共介面的描述,DApp用這個公共介面來呼叫智慧合約。
問:位元組碼的作用是什麼?
答: 每個節點上的以太坊虛擬機器都需要智慧合約的位元組碼來執行智慧合約。
問:為什麼要使用大數運算程式庫(BigNumber library)?
答: 因為Javascript無法正確處理大數字。
問:為什麼要始終檢查DApp程式碼的開頭是否設定了web3提供程式(provider)?
答: 因為如果不這樣,Metamask會用自己的web3提供程式覆蓋掉它。
問:為什麼使用web3 js的1.x版本而不是0.2x.x版本?
答: 主要是因為1.x版本的非同步呼叫使用promise物件(承諾將來會執行,比回撥物件更合理和更強大)而不是回撥物件,promise物件也是javascript中的首選。
問:在web3 1.x版本中如何列出所有帳戶?
答: 使用命令:“ web3.eth.getAccounts ”
問:“.call”和“.send”有什麼區別?
答: “.send”發起交易並且產生費用,而“.call”僅查詢智慧合約的狀態不產生費用。
問:是否可以通過這樣的命令“.send({value:1})”傳送一個以太幣?
答: 不可以,實際上這樣你只送了1wei(1以太幣 =10^18Wei)。交易中的單位是wei,而不是以太幣。
問:那是否意味著,為了傳送一個以太幣,我需要將值設定為10^18?
答: 不用,這樣太麻煩。你可以使用util方法,即:
web3.utils.toWei(1,'ether') 。
問:呼叫“.send()”時我需要指定什麼?
答: 你必須指定其中的發件人地址“from”。其他一切都是可選的。
問:將以太幣傳送到特定地址的函式是否只有
web3.eth.sendTransaction()一個?
答: 不,你還可以呼叫智慧合約中的函式。
問:以太坊的可擴充套件性問題有什麼解決方案?
答: 解決可拓展性問題的思路是使用鏈下交易機制。具體的解決方案有狀態通道(state channels)和plasma。
02
面試核心要點梳理
(1)Solidity檔案的佈局
原始檔中可能包含任意數量的智慧合約定義,包括指令和編譯指示(pragma directives)。
Pragma版本(Version Pragma)
Pragma版本用來宣告程式碼應該使用的Solidity編譯器版本。
version pragma ^0.4.00;
注意:有了這條指令,原始檔不會使用早於版本0.4.0的編譯器進行編譯,也不會使用晚於版本0.5.0的編譯器進行編譯。
匯入其他原始檔
以太坊的Solidity語言支援與JavaScript非常相似的匯入語句(import),不過Solidity中沒有“預設匯出(default export)”的概念。
在全域性級別,你可以使用以下的匯入語句:
import "filename";
上述程式碼將“filename(你所指定的檔名)”中所有全域性符號匯入到當前的全域性範圍。
import * as symbolName from "filename";
上述程式碼建立了一個新的全域性符號symbolName,其成員是“filename”中所有的全域性符號。
註釋
和大多數程式語言一樣,Solidity也可以使用單行註釋和多行註釋。
// 這是一個單行註釋。 /* 這是一個 多行註釋。 */
(2)以太坊儲存區域
在我們進一步深入瞭解Solidity之前,你應該知道以太坊有三個儲存區域。
-
儲存(Storage):所有智慧合約狀態變數所在的位置。每個智慧合約都有自己的儲存,並且只有函式呼叫才能改變儲存中的狀態變數。
-
記憶體(Memory):用於儲存外部呼叫的臨時資料並在呼叫結束之後釋放資料,相比之下,使用記憶體中的資料價格更低。
-
堆疊(Stack):用於儲存小的區域性變數。堆疊幾乎是免費使用的,但只能儲存有限數量的值。
對於幾乎所有的型別,你都無法指定它們儲存的位置,因為每次使用時它們都會在這三種類型間互相複製。
在瞭解了以太坊Solidity中的儲存位置之後,我們來學習Solidity中的資料型別。
(3)Solidity中的資料型別
以下的資料型別通常也被稱為值型別,因為這些型別的資料始終按值傳遞。
Solidity中的資料型別
布林型別
關鍵詞:Bool
布林型別可能的取值是固定的,即“真”或“假”。
整型
關鍵字:int / uint(從uint8(8位無符號整型)到uint256(256位無符號整型),從int8(8位整型)到int256(256位整型))
整型就是各種大小的有符號或無符號整數。
我們可以按以下程式碼來定義整型:
contract MySample{ uint UnsignedInt =50; }
在上面的程式碼中,我們建立了一個名為InsignedInt的無符號整型(uint)並將它的值設定為50。
地址型別
關鍵字:address
地址型別用於儲存長度為20位元組的值(以太坊地址的長度)。地址型別有其內部的資料成員,是所有智慧合約的基礎。
地址的資料成員:餘額(balance)與轉賬(transfer)
你可以使用餘額屬性查詢某個地址中的餘額,也可以使用轉賬函式將以太幣傳送到某個地址,如下所示:
address x = 0x123; address myAddress = this; if (x.balance < 10 && myAddress.balance > = 10) x.transfer(10);
字串型別
關鍵字:字串中的文字通常用雙引號或單引號引出,例如“foo”,“bar”。
字串型別可以是任意長度的UTF資料,如下所示:
string language = "Solidity";
這些值型別可以在包含運算子的表示式中相互互動。接下來,我們就來說說各種運算子。
(4)運算子
Solidity中的運算子與JavaScript相同,有四種類型的運算子:
Solidity中的運算子
算術運算子
與大多數程式語言類似,Solidity語言中包含一些非常簡單的數學運算:
-
加法:x + y
-
減法:x - y
-
乘法:x * y
-
除法:x / y
-
求模/求餘:x%y
如下所示,Solidity中也支援指數運算子:
uint x = 10 ** 3; // equal to 10^3 = 1000
增量運算子
Solidity中的增量運算子包括:a ++,a - ,++ a,-a,a + = 1,a = a + 1
Solidity中增量運算子的運算規則與其他程式語言類似。
位運算子
Solidity中的位運算子包括:按位或“ | ”,按位異或“ ^ ”,按位取反“ ~ ”,按位右移“ >> ”,按位左移“ << ”。
邏輯運算子
Solidity中的邏輯運算子包括:邏輯非“ ! ”,邏輯與“ && ”,邏輯或“ || ”,相等“ == ”,不相等“ != ”。
用法請看以下示例:
contract operators { //算數運算子 // +,-,*,/, %, ** // 增量運算子 // a++, a--, a+=1, a=a+1,++a,--a; a=10; a= a++; //在這裡,輸出結果將為10, 因為“a++”運算中先返回a的值再執行自加。 a=++a;//此時輸出的結果將為12,因為“++a”運算中先自加再返回a的值。 //邏輯運算子 !, &&, ||, ==, != isOwner = true && false; var orValue= 0x02 | 0x01; // 這裡的輸出應該是 0x03 //位運算子~,>>, <<; function Operators() { // 在這裡初始化狀態變數}}
在複雜的智慧合約中僅僅使用這些資料型別不能滿足需求。為此,Solidity還提供了資料結構。
(5)Solidity中的資料結構
Solidity提供三種類型的資料結構:
Solidity中的資料結構
結構體
Solidity提供了一種以結構體定義新資料型別的方法。 結構體是自定義型別,其中可以包含多個變數。我們可以按如下方式定義結構體:
pragma solidity ^0.4.0; contract Ballot { struct Voter { // 結構體 uint weight1, weight2, weight3; bool voted; address delegate1, delegate2, delegate3, delegate4; string name; uint vote1, vote2, vote3, vote4, vote5; uint height1, height2, height3 } }
注意:結構體型別中最多隻能有16個成員,數量超標後可能會發生“堆疊太深(Stack too Deep)”錯誤。
結構體型別可以用來建立功能更完善、更復雜的資料型別。
結構體型別很強大,但如果要處理多個相同種類的資料,比如說要儲存多個以太坊地址,該怎麼辦呢?與大多數程式語言類似,Solidity中也支援陣列。
陣列
Solidity中的陣列可以是固定長度陣列,也可以是動態陣列。
uint[3] fixed; //這是一個長度為3的固定長度陣列。 uint[] dynamic; //這是一個動態陣列,長度隨元素的個數變化。
如果陣列中的元素為結構體,那麼我們可以得到一個結構體陣列。如下所示,使用剛才建立的Voter結構體建立一個結構體陣列:
Voter[] voting;
注意:將陣列宣告為公開(public)將自動為其建立getter方法。
Voter[] public voting;
對映
對映可以看作是元素被虛擬初始化的雜湊表,即每個鍵值對中的鍵被初始化,鍵對映的值用預設值0代替。
對映的宣告方式如下所示:
Mapping(_Keytype => _ValueType )
注意:“_Keytype”可以是除了動態陣列,智慧合約,列舉型別和結構體型別之外的任何型別。
請看以下示例:
contract MappingExample { mapping(address => uint) public balances; function update(uint newBalance) { balances[msg.sender] = newBalance; }} contract MappingUser { function f() returns (uint) { MappingExample m = new MappingExample(); m.update(100); return m.balances(this); }}
(6)程式控制結構
除了switch和goto之外,Solidity支援JavaScript中的大多數程式控制結構,也就是說Solidity支援以下的程式控制結構:if,else,while,do,for,break,continue,return,? :,它們的用法與C語言和JavaScript中的用法相同。
注意:Solidity不能像C語言和JavaScript那樣將非布林型別資料轉換成布林型別資料。
現在讓我們看看如何在Solidity中使用這些程式控制結構:
contract ControlStructure { address public a; function ControlStructure>){ // if-else 可以這樣使用 if(input1==2) a=1; else a=0; // while 可以這樣使用 while(input1>=0){ if(input1==5) continue; input1=input1-1; a++;} // for迴圈可以這樣使用 for(uint i=0;i<=50;i++) { a++; if(a==4) break; } //如果使用do while的話,程式碼為 do { a--; } (while a>0); // 條件操作可以這樣使用 bool IsTrue = (a == 1)?true: false; /*這將會報錯 因為Solidity不能將非布林型別資料轉換成布林型別資料 */ if(1) { }
將資料型別與程式控制結構相結合就得到了程式的程式碼。接下來讓我們談談智慧合約中可執行的程式碼單元,也就是我們剛才提到的函式。
(7)函式
如何在Solidity中宣告一個函式呢?請看以下示例:
function sampleFunc(string name, uint amount) { }
上面的程式碼中聲明瞭一個空函式,它有兩個引數:一個是字串和一個是無符號整型(uint)。
你可以通過以下命令呼叫這個函式:
sampleFunc("Shashank", 10000);
除了函式之外,Solidity中還提供函式修改器(Function Modifiers)。
(8)函式修改器
函式修改器可以輕易的修改一個函式的功能。只要提前在智慧合約的函式定義中宣告,即使在執行函式呼叫之前也可以進行修改。
如果你想要呼叫一個只有函式的所有者或建立者才能呼叫的銷燬智慧合約函式killContract(),程式碼如下所示:
contract FunctionModifiers{ address public creator; function FunctionModifiers() { creator = msg.sender;} Modifier onlyCreator() { if(msg.sender!=creator){ throw; } _; //在函式修改器修改完畢後恢復函式 } function killContract() onlyCreator{ //不出意外的話,修改後的函式可以正常呼叫。 self-destruct(creator); }}
(9)繼承
Solidity可以通過複製包含多型(介面的不同實現方式)的程式碼來支援多繼承(一個子類可以有多個父類,它繼承了多個父類的特性)。
contract Owned { address Owner ; function owned() { owner = msg.sender; }} contract Mortal is Owned { // 'is' 關鍵詞被用來繼承。 function kill(){ self-destruct(owner); }} contract User is Owned, Mortal //多繼承 { string public UserName; function User(string _name){ UserName = _name; }}
原文連結:
https://medium.com/coinmonks/blockchain-interview-questions-the-collection-38de299ce44d
--【完】--
親愛的讀者們, 歡迎文末留言交流喲!
既然都看到這了,就順手點個贊吧,授人玫瑰,手有餘香嘛!
最新熱文:
-
ofollow,noindex" target="_blank"> 普華永道:2030年區塊鏈價值將突破30萬億
-
OA==&mid=2247498302&idx=4&sn=d6008299a1158fae5ef733930fcb2d5d&chksm=e99ec9c7dee940d11ef5da308d760fdb6cf73852b62f19f55b91764a3e50fda5361aab113d96&scene=21#wechat_redirect" rel="nofollow,noindex" target="_blank"> 只講技術,拒絕空談!2018 AI開發者大會精彩議程曝光
大力戳↑↑↑ 加入區塊鏈大本營讀者⑦號群
(群滿加微信 qk15732632926 入群)
(內容轉載請聯絡微信:qk15732632926)
(商務合作請聯絡微信:fengyan-1101)
區塊鏈技術沙龍
◆
成都站
◆
CSDN區塊鏈技術沙龍【 成都站 】火熱報名中,活動圍繞區塊鏈核心技術、智慧合約、DApp開發、“區塊鏈+”等內容進行深度分享。掃碼「 免費 」報名,名額有限!