真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Solidity的高級特性怎么使用

這篇文章主要介紹“Solidity的高級特性怎么使用”,在日常操作中,相信很多人在Solidity的高級特性怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Solidity的高級特性怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

10年的阿巴嘎網(wǎng)站建設經(jīng)驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設備顯示端的尺寸不同,自動調整阿巴嘎建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“阿巴嘎網(wǎng)站設計”,“阿巴嘎網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。

前言

FISCO BCOS使用了Solidity語言進行智能合約開發(fā)。Solidity是一門面向區(qū)塊鏈平臺設計、圖靈完備的編程語言,支持函數(shù)調用、修飾器、重載,事件、繼承和庫等多種高級語言的特性。

合理控制函數(shù)和變量的類型

基于最少知道原則(Least Knowledge Principle)中經(jīng)典面向對象編程原則,一個對象應該對其他對象保持最少的了解。優(yōu)秀的Solidity編程實踐也應符合這一原則:每個合約都清晰、合理地定義函數(shù)的可見性,暴露最少的信息給外部,做好對內部函數(shù)可見性的管理。

同時,正確地修飾函數(shù)和變量的類型,可給合約內部數(shù)據(jù)提供不同級別的保護,以防止程序中非預期的操作導致數(shù)據(jù)產(chǎn)生錯誤;還能提升代碼的可讀性與質量,減少誤解和bug;更有利于優(yōu)化合約執(zhí)行的成本,提升鏈上資源的使用效率。

守住函數(shù)操作的大門:函數(shù)可見性

Solidity有兩種函數(shù)調用方式:

  • 內部調用:又被稱為『消息調用』。常見的有合約內部函數(shù)、父合約的函數(shù)以及庫函數(shù)的調用。(例如,假設A合約中存在f函數(shù),則在A合約內部,其他函數(shù)調用f函數(shù)的調用方式為f()。)

  • 外部調用:又被稱為『EVM調用』。一般為跨合約的函數(shù)調用。在同一合約內部,也可以產(chǎn)生外部調用。(例如,假設A合約中存在f函數(shù),則在B合約內可通過使用A.f()調用。在A合約內部,可以用this.f()來調用。)。

函數(shù)可以被指定為 external ,public ,internal 或者 private標識符來修飾。 Solidity的高級特性怎么使用

基于以上表格,我們可以得出函數(shù)的可見性 public > external > internal > private。

另外,如果函數(shù)不使用上述類型標識符,那么默認情況下函數(shù)類型為 public。

綜上所述,我們可以總結一下以上標識符的不同使用場景:

  • public,公有函數(shù),系統(tǒng)默認。通常用于修飾可對外暴露的函數(shù),且該函數(shù)可能同時被內部調用。

  • external,外部函數(shù),推薦只向外部暴露的函數(shù)使用。當函數(shù)的某個參數(shù)非常大時,如果顯式地將函數(shù)標記為external,可以強制將函數(shù)存儲的位置設置為calldata,這會節(jié)約函數(shù)執(zhí)行時所需存儲或計算資源。

  • internal,內部函數(shù),推薦所有合約內不對合約外暴露的函數(shù)使用,可以避免因權限暴露被攻擊的風險。

  • private,私有函數(shù),在極少數(shù)嚴格保護合約函數(shù)不對合約外部開放且不可被繼承的場景下使用。

不過,需要注意的是,無論用何種標識符,即使是private,整個函數(shù)執(zhí)行的過程和數(shù)據(jù)是對所有節(jié)點可見,其他節(jié)點可以驗證和重放任意的歷史函數(shù)。實際上,整個智能合約所有的數(shù)據(jù)對區(qū)塊鏈的參與節(jié)點來說都是透明的。

剛接觸區(qū)塊鏈的用戶常會誤解,在區(qū)塊鏈上可以通過權限控制操作來控制和保護上鏈數(shù)據(jù)的隱私。

這是一種錯誤的觀點。事實上,在區(qū)塊鏈業(yè)務數(shù)據(jù)未做特殊加密的前提下,區(qū)塊鏈同一賬本內的所有數(shù)據(jù)經(jīng)過共識后落盤到所有節(jié)點上,鏈上數(shù)據(jù)是全局公開且相同的,智能合約只能控制和保護合約數(shù)據(jù)的執(zhí)行權限。

如何正確地選擇函數(shù)修飾符是合約編程實踐中的『必修課』,只有掌握此節(jié)真諦方可自如地控制合約函數(shù)訪問權限,提升合約安全性。

對外暴露最少的必要信息:變量的可見性

與函數(shù)一樣,對于狀態(tài)變量,也需要注意可見性修飾符。狀態(tài)變量的修飾符默認是internal,不能設置為external。此外,當狀態(tài)變量被修飾為public,編譯器會生成一個與該狀態(tài)變量同名的函數(shù)。

具體可參考以下示例:

Solidity的高級特性怎么使用

這個機制有點像Java語言里lombok庫所提供的@Getter注解,默認為一個POJO類變量生成get函數(shù),大大簡化了某些合約代碼的書寫。

同樣,變量的可見性也需要被合理地修飾,不該公開的變量果斷用private修飾,使合約代碼更符合『最少知道』的設計原則。

精確地將函數(shù)分類:函數(shù)的類型

函數(shù)可以被聲明為pure、view,兩者的作用可見下圖。

Solidity的高級特性怎么使用

那么,什么是讀取或修改狀態(tài)呢?簡單來說,兩個狀態(tài)就是讀取或修改了賬本相關的數(shù)據(jù)。

在FISCO BCOS中,讀取狀態(tài)可能是:

  1. 讀取狀態(tài)變量。

  2. 訪問 block,tx, msg 中任意成員 (除 msg.sig 和 msg.data 之外)。

  3. 調用任何未標記為 pure 的函數(shù)。

  4. 使用包含某些操作碼的內聯(lián)匯編。

而修改狀態(tài)可能是:

  1. 修改狀態(tài)變量。

  2. 產(chǎn)生事件。

  3. 創(chuàng)建其它合約。

  4. 使用 selfdestruct。

  5. 調用任何沒有標記為 view 或者 pure 的函數(shù)。

  6. 使用底層調用。

  7. 使用包含特定操作碼的內聯(lián)匯編。

需要注意的是,在某些版本編譯器中,并沒有對這兩個關鍵字進行強制的語法檢查。

推薦盡可能使用pure和view來聲明函數(shù),例如將沒有讀取或修改任何狀態(tài)的庫函數(shù)聲明為pure,這樣既提升了代碼可讀性,也使其更賞心悅目,何樂而不為?

編譯時就確定的值:狀態(tài)常量

所謂的狀態(tài)常量是指被聲明為constant的狀態(tài)變量。

一旦某個狀態(tài)變量被聲明為constant,那么該變量值只能為編譯時確定的值,無法被修改。編譯器一般會在編譯狀態(tài)計算出此變量實際值,不會給變量預留儲存空間。所以,constant只支持修飾值類型和字符串。

狀態(tài)常量一般用于定義含義明確的業(yè)務常量值。

面向切片編程:函數(shù)修飾器(modifier)

Solidity提供了強大的改變函數(shù)行為的語法:函數(shù)修飾器(modifier)。一旦某個函數(shù)加上了修飾器,修飾器內定義的代碼就可以作為該函數(shù)的裝飾被執(zhí)行,類似其他高級語言中裝飾器的概念。

這樣說起來很抽象,讓我們來看一個具體的例子:

Solidity的高級特性怎么使用

如上所示,定義onlyOwner修飾器后,在修飾器內,require語句要求msg.sender必須等于owner。后面的"_;"表示所修飾函數(shù)中的代碼。

所以,代碼實際執(zhí)行順序變成了:

  1. 執(zhí)行onlyOwner修飾器的語句,先執(zhí)行require語句。(執(zhí)行第9行)

  2. 執(zhí)行changeOwner函數(shù)的語句。(執(zhí)行第15行)

由于changeOwner函數(shù)加上了onlyOwner的修飾,故只有當msg.sender是owner才能成功調用此函數(shù),否則會報錯回滾。

同時,修飾器還能傳入?yún)?shù),例如上述的修飾器也可寫成:

Solidity的高級特性怎么使用

同一個函數(shù)可有多個修飾器,中間以空格間隔,修飾器依次檢查執(zhí)行。此外,修飾器還可以被繼承和重寫。

由于其所提供的強大功能,修飾器也常被用來實現(xiàn)權限控制、輸入檢查、日志記錄等。

比如,我們可以定義一個跟蹤函數(shù)執(zhí)行的修飾器:

Solidity的高級特性怎么使用

這樣,任何用logMethod修飾器來修飾的函數(shù)都可記錄其函數(shù)執(zhí)行前后的日志,實現(xiàn)日志環(huán)繞效果。如果你已經(jīng)習慣了使用Spring框架的AOP,也可以試試用modifier實現(xiàn)一個簡單的AOP功能。

modifier最常見的打開方式是通過提供函數(shù)的校驗器。在實踐中,合約代碼的一些檢查語句常會被抽象并定義為一個modifier,如上述例子中的onlyOwner就是個最經(jīng)典的權限校驗器。這樣一來,連檢查的邏輯也能被快速復用,用戶也不用再為智能合約里到處都是參數(shù)檢查或其他校驗類代碼而苦惱。

可以debug的日志:合約里的事件(Event)

介紹完函數(shù)和變量,我們來聊聊Solidity其中一個較為獨有的高級特性——事件機制。

事件允許我們方便地使用 EVM 的日志基礎設施,而Solidity的事件有以下作用:

  1. 記錄事件定義的參數(shù),存儲到區(qū)塊鏈交易的日志中,提供廉價的存儲。

  2. 提供一種回調機制,在事件執(zhí)行成功后,由節(jié)點向注冊監(jiān)聽的SDK發(fā)送回調通知,觸發(fā)回調函數(shù)被執(zhí)行。

  3. 提供一個過濾器,支持參數(shù)的檢索和過濾。

事件的使用方法非常簡單,兩步即可玩轉。

  • 第一步,使用關鍵字『event』來定義一個事件。建議事件的命名以特定前綴開始或以特定后綴結束,這樣更便于和函數(shù)區(qū)分,在本文中我們將統(tǒng)一以『Log』前綴來命名事件。下面,我們用『event』來定義一個函數(shù)調用跟蹤的事件:

event LogCallTrace(address indexed from, address indexed to, bool result)

事件在合約中可被繼承。當他們被調用時,會將參數(shù)存儲到交易的日志中。這些日志被保存到區(qū)塊鏈中,與地址相關聯(lián)。在上述例子中,用indexed標記參數(shù)被搜索,否則,這些參數(shù)被存儲到日志的數(shù)據(jù)中,無法被搜索。

  • 第二步,在對應的函數(shù)內觸發(fā)定義事件。調用事件的時候,在事件名前加上『emit』關鍵字:

Solidity的高級特性怎么使用

這樣,當函數(shù)體被執(zhí)行的時候,會觸發(fā)執(zhí)行LogCallTrace。

最后,在FISCO BCOS的Java SDK中,合約事件推送功能提供了合約事件的異步推送機制,客戶端向節(jié)點發(fā)送注冊請求,在請求中攜帶客戶端關注的合約事件參數(shù),節(jié)點根據(jù)請求參數(shù)對請求區(qū)塊范圍的Event Log進行過濾,將結果分次推送給客戶端。更多細節(jié)可以參考合約事件推送功能文檔。在SDK中,可以根據(jù)事件的indexed屬性,根據(jù)特定值進行搜索。

合約事件推送功能文檔: https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk.html#id14

不過,日志和事件無法被直接訪問,甚至在創(chuàng)建的合約中也無法被直接訪問。

但好消息是日志的定義和聲明非常利于在『事后』進行追溯和導出。

例如,我們可以在合約的編寫中,定義和埋入足夠的事件,通過WeBASE的數(shù)據(jù)導出子系統(tǒng)我們可以將所有日志導出到MySQL等數(shù)據(jù)庫中。這特別適用于生成對賬文件、生成報表、復雜業(yè)務的OLTP查詢等場景。此外,WeBASE提供了一個專用的代碼生成子系統(tǒng)幫助分析具體的業(yè)務合約,自動生成相應的代碼。

WeBASE的數(shù)據(jù)導出子系統(tǒng): https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Collect-Bee/index.html 代碼生成子系統(tǒng): https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Codegen-Monkey/index.html

在Solidity中,事件是一個非常有用的機制,如果說智能合約開發(fā)最大的難點是debug,那善用事件機制可以讓你快速制伏Solidity開發(fā)。

面向對象之重載

重載是指合約具有多個不同參數(shù)的同名函數(shù)。對于調用者來說,可使用相同函數(shù)名來調用功能相同,但參數(shù)不同的多個函數(shù)。在某些場景下,這種操作可使代碼更清晰、易于理解,相信有一定編程經(jīng)驗的讀者對此一定深有體會。

下面將展示一個典型的重載語法:

Solidity的高級特性怎么使用

需要注意的是,每個合約只有一個構造函數(shù),這也意味著合約的構造函數(shù)是不支持重載的。

我們可以想像一個沒有重載的世界,程序員一定絞盡腦汁、想方設法給函數(shù)起名,大家的頭發(fā)可能又要多掉幾根。

面向對象之繼承

Solidity使用『is』作為繼承關鍵字。因此,以下這段代碼表示的是,合約B繼承了合約A:

Solidity的高級特性怎么使用

而繼承的合約B可以訪問被繼承合約A的所有非private函數(shù)和狀態(tài)變量。

在Solidity中,繼承的底層實現(xiàn)原理為:當一個合約從多個合約繼承時,在區(qū)塊鏈上只有一個合約被創(chuàng)建,所有基類合約的代碼被復制到創(chuàng)建的合約中。

相比于C++或Java等語言的繼承機制,Solidity的繼承機制有點類似于Python,支持多重繼承機制。因此,Solidity中可以使用一個合約來繼承多個合約。

在某些高級語言中,比如Java,出于安全性和可靠性的考慮,只支持單重繼承,通過使用接口機制來實現(xiàn)多重繼承。對于大多數(shù)場景而言,單繼承的機制就可以滿足需求了。

多繼承會帶來很多復雜的技術問題,例如所謂的『鉆石繼承』等,建議在實踐中盡可能規(guī)避復雜的多繼承。

繼承簡化了人們對抽象合約模型的認識和描述,清晰體現(xiàn)了相關合約間的層次結構關系,并且提供軟件復用功能。這樣,能避免代碼和數(shù)據(jù)冗余,增加程序的重用性。

面向對象之抽象類和接口

根據(jù)依賴倒置原則,智能合約應該盡可能地面向接口編程,而不依賴具體實現(xiàn)細節(jié)。

Solidity支持抽象合約和接口的機制。

如果一個合約,存在未實現(xiàn)的方法,那么它就是抽象合約。例如:

Solidity的高級特性怎么使用

抽象合約無法被成功編譯,但可以被繼承。

接口使用關鍵字interface,上面的抽象也可以被定義為一個接口。

Solidity的高級特性怎么使用

接口類似于抽象合約,但不能實現(xiàn)任何函數(shù),同時,還有進一步的限制:

  1. 無法繼承其他合約或接口。

  2. 無法定義構造函數(shù)。

  3. 無法定義變量。

  4. 無法定義結構體

  5. 無法定義枚舉。

合適地使用接口或抽象合約有助于增強合約設計的可擴展性。但是,由于區(qū)塊鏈EVM上計算和存儲資源的限制,切忌過度設計,這也是從高級語言技術棧轉到Solidity開發(fā)的老司機常常會陷入的天坑。

避免重復造輪子:庫(Library)

在軟件開發(fā)中,很多經(jīng)典原則可以提升軟件的質量,其中最為經(jīng)典的就是盡可能復用久經(jīng)考驗、反復打磨、嚴格測試的高質量代碼。此外,復用成熟的庫代碼還可以提升代碼的可讀性、可維護性,甚至是可擴展性。

和所有主流語言一樣,Solidity也提供了庫(Library)的機制。Solidity的庫有以下基本特點:

  1. 用戶可以像使用合約一樣使用關鍵詞library來創(chuàng)建合約。

  2. 庫既不能繼承也不能被繼承。

  3. 庫的internal函數(shù)對調用者都是可見的。

  4. 庫是無狀態(tài)的,無法定義狀態(tài)變量,但是可以訪問和修改調用合約所明確提供的狀態(tài)變量。

接下來,我們來看一個簡單的例子,以下是FISCO BCOS社區(qū)中一個LibSafeMath的代碼庫。我們對此進行了精簡,只保留了加法的功能:

Solidity的高級特性怎么使用

我們只需在合約中import庫的文件,然后使用L.f()的方式來調用函數(shù),(例如LibSafeMath.add(a,b))。

接下來,我們編寫調用這個庫的測試合約,合約內容如下:

Solidity的高級特性怎么使用

在FISCO BCOS控制臺中,我們可以測試合約的結果(控制臺的介紹文章詳見FISCO BCOS 控制臺詳解,飛一般的區(qū)塊鏈體驗),運行結果如下:

Solidity的高級特性怎么使用

通過以上示例,我們可清晰了解在Solidity中應如何使用庫。

類似Python,在某些場景下,指令『using A for B;』可用于附加庫函數(shù)(從庫 A)到任何類型(B)。這些函數(shù)將接收到調用它們的對象作為第一個參數(shù)(像 Python 的 self 變量)。這個功能使庫的使用更加簡單、直觀。

例如,我們對代碼進行如下簡單修改:

Solidity的高級特性怎么使用

驗證一下結果依然是正確的。

Solidity的高級特性怎么使用

到此,關于“Solidity的高級特性怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)頁名稱:Solidity的高級特性怎么使用
文章出自:http://weahome.cn/article/gjcich.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部