版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第5章HyperledgerComposer入門5.1HyperledgerComposer簡介5.2環(huán)境搭建5.3
HyperledgerComposer的建模語言5.4開發(fā)你的第一個業(yè)務(wù)網(wǎng)絡(luò)5.5部署和測試本章小結(jié)
5.1
HyperledgerComposer簡介
1.工作流步驟1——搭建并啟動Fabric網(wǎng)絡(luò)首先,要明確HyperledgerComposer只是我們開發(fā)業(yè)務(wù)網(wǎng)絡(luò)的助手,而不是區(qū)塊鏈網(wǎng)絡(luò)本身的模塊。HyperledgerComposer僅僅為我們提供了應(yīng)用打包、安裝部署、可視化測試等功能,但由于應(yīng)用包最終將部署在Fabric區(qū)塊鏈網(wǎng)絡(luò)上,因此啟動Fabric網(wǎng)絡(luò)以及HyperledgerComposer框架的安裝是一切開發(fā)工作的基礎(chǔ)。搭建并啟動Fabric網(wǎng)絡(luò)分為安裝依賴、編寫網(wǎng)絡(luò)配置文件和啟動三個步驟,如圖5-1所示。
圖5-1
HyperledgerComposer工作流步驟1
2.工作流步驟2——部署和測試業(yè)務(wù)網(wǎng)絡(luò)
借助HyperledgerComposer獨特的建模語言和工程結(jié)構(gòu),能夠輕松地進行應(yīng)用程序的開發(fā)。
開發(fā)完成后,首先需要使用HyperledgerComposer命令將工程代碼打包成一個BNA(BusinessNetworkApplication,業(yè)務(wù)網(wǎng)絡(luò)應(yīng)用包);接著將該網(wǎng)絡(luò)包(BNA)安裝部署到Fabric網(wǎng)絡(luò)的Peer節(jié)點上,然后啟動該網(wǎng)絡(luò);最后可通過HyperledgerComposer的RestServer工具生成RestfulAPI進行可視化測試。為了讓用戶可以方便調(diào)試,HyperledgerComposer提供了日志功能,用戶可以通過查看交易日志來分析測試結(jié)果,如圖5-2所示。圖5-2
HyperledgerComposer工作流步驟2
5.2環(huán)
境
搭
建
使用HyperledgerComposer之前,必須先搭建好FabricRuntime(運行時環(huán)境)。官網(wǎng)已經(jīng)提供了一鍵安裝并搭建環(huán)境的腳本,所有的依賴都會自動安裝,免除了從Github上克隆項目再手動安裝的麻煩。
安裝步驟如下:
(1)使用Cd命令切換至想要安裝HyperledgerComposer框架的目錄,命令行如下:
(2)用Curl命令遠程下載自動安裝腳本,命令行如下:
(3)下載完畢后執(zhí)行腳本。如遇到無法執(zhí)行的問題,可先使用Chmod命令修改腳本權(quán)限為可執(zhí)行,然后再執(zhí)行該腳本,命令行如下:
(4)退出系統(tǒng)當(dāng)前用戶并重新登錄,使系統(tǒng)設(shè)置生效,命令行如下:
(5)安裝HyperledgerComposer相關(guān)工具所需的Linux指令如下:
(6)安裝Fabric運行時環(huán)境:
①
創(chuàng)建并切換至fabric工作目錄,稍后要將Fabric工具下載到該目錄中,命令行如下:
②
下載并解壓Fabric測試服務(wù)器壓縮包,命令行如下:
③
運行解壓后的腳本并安裝Docker鏡像文件,命令行如下:
(7)啟動Fabric測試網(wǎng)絡(luò)并創(chuàng)建網(wǎng)絡(luò)節(jié)點訪問卡(證書),命令行如下:
5.3
HyperledgerComposer的建模語言
1.?CTO建模語言的特點
(1)簡單易懂:其語法類似于面向?qū)ο笳Z言中的Class和SQL中的建表。開發(fā)人員編寫CTO的過程就像編寫數(shù)據(jù)庫實體類和建表一樣,大大降低了開發(fā)復(fù)雜度。
(2)語法靈活:定義對象的屬性時可指定多個特殊字段,如“可選的”、指定范圍和校驗等。
2.?CTO文件的內(nèi)容
CTO文件后綴為?.CTO。一個完整的CTO模型文件包含下面幾個方面:
(1)命名空間。
(2)資源定義(資產(chǎn)、參與者、交易等)。
(3)從其他命名空間導(dǎo)入(按需)。
5.3.1命名空間
CTO中命名空間的概念和其他語言的概念基本一致,類似于文件系統(tǒng)中的文件目錄或Java中的包,主要作用是對代碼文件進行合理的劃分。
在Composer開發(fā)中,業(yè)務(wù)網(wǎng)絡(luò)可能會有一個或多個.CTO模型文件。通常,每個模型文件以命名空間作為文件名,用于對不同資源進行劃分。
一個CTO文件必須在文件開頭指定一個命名空間。該文件中定義的資源只屬于該命名空間,不同命名空間的資源相互獨立。
5.3.2資源
資源可以理解為區(qū)塊鏈業(yè)務(wù)網(wǎng)絡(luò)中出現(xiàn)的對象,是Composer的重要概念。
1.資源的種類
資源對象包含以下種類:
(1)資產(chǎn)(Asset):即有價值的、可被交易的物品。
(2)參與者(Participant):參與業(yè)務(wù)網(wǎng)絡(luò)的角色。
(3)交易(Transaction):業(yè)務(wù)網(wǎng)絡(luò)中的資產(chǎn)轉(zhuǎn)移。
(4)事件(Event):業(yè)務(wù)網(wǎng)絡(luò)中觸發(fā)的某種通知。
(5)枚舉(Enum):一組同類型的值的集合。
(6)概念(Concept):資源中的通用屬性集。
2.資源的特點
資源的特點如下:
(1)資源屬于某命名空間。
(2)資源名在命名空間內(nèi)唯一。
(3)資源類型為Asset和Participant時,必須指定主鍵(Identifiedby)。
(4)資源類型為Transaction時,會自動生成ID和交易時間,因此不能顯式地指定主鍵。
(5)資源具有屬性(o表示屬性)。
(6)資源可互相依賴(-->表示依賴)。
(7)資源支持單繼承(Extends關(guān)鍵字)。
(8)資源支持抽象類(Abstract關(guān)鍵字)。
資源定義格式如下:
5.3.3屬性
每種資源都可能具有屬性,用“o+屬性類型+屬性名”表示。如電腦可能有名稱、生產(chǎn)數(shù)量、價格、功能、生產(chǎn)日期等屬性。
1.屬性的樣例代碼
2.屬性的基本類型
屬性包括如下基本類型:
(1)?String(UTF-8字符串);
(2)?Double(64位帶符號浮點數(shù));
(3)?Integer(32位帶符號整數(shù));
(4)?Long(64位帶符號整數(shù));
(5)?Boolean(布爾類型:true/false);
(6)?DataTime(與ISO-8601兼容的時間,具有可選的時區(qū)和UTZ偏移)。
3.屬性的引用類型
屬性包括如下引用類型:
(1)?Array(數(shù)組,基本類型或引用類型后加中括號);
(2)?Concept;
(3)?Enum;
(4)?依賴類型。
5.3.4依賴
資源之前可能存在依賴(引用)關(guān)系(依賴也是一種屬性),用“-->+依賴資源名+屬性名”表示。如電腦和生產(chǎn)者存在依賴關(guān)系。
依賴樣例代碼如下:
5.3.5枚舉
枚舉通常是一組相關(guān)值的集合,無法被實例化,其中定義的屬性最好全大寫;多單詞間用下劃線分隔。比如表示訂單的狀態(tài)。
枚舉樣例代碼如下:
5.3.6概念
概念表示多個資源中通用的屬性,無法被實例化。比如參與者類型很多時,我們可以將所有參與者共有的屬性用概念來表示(也可以使用抽象類和繼承)。
概念樣例代碼如下:
5.3.7
CTO語言特性
CTO建模語言和SQL建表語句——指定名稱、標(biāo)識主鍵、列舉字段——十分相似。此外,CTO語法還包括屬性默認值以及可選屬性。
屬性默認值和可選屬性樣例代碼如下:
1.正則表達式
Composer還可以限制屬性取值范圍,支持正則表達式。
正則表達式為用戶姓名和年齡屬性定制了規(guī)則,其樣例代碼如下。
2.繼承樣例代碼
CTO建模語言使用面向?qū)ο蟮乃枷?,支持資源之間的繼承(Extends)以及抽象類(Abstract)。
繼承樣例代碼如下:
3.CTO建模語言須遵循的規(guī)范
CTO建模語言還有一些高級特性,如注解,但須遵循以下規(guī)范:
(1)注解可以定義在除概念和枚舉外的所有資源上。
(2)注解可以定義在除概念之外的所有屬性和依賴上。
(3)同一資源和屬性上可定義多個注解,但不能同名。
(4)每條注解可定義多個參數(shù)。
下面樣例的注解是合法的:
4.導(dǎo)入其他命名空間
CTO建模語言還支持導(dǎo)入其他命名空間。
通過Import語句,可以使用其他命名空間中定義的資源,但注意資源名稱不能沖突。
導(dǎo)入命名空間樣例代碼如下:
5.4開發(fā)你的第一個業(yè)務(wù)網(wǎng)絡(luò)
5.4.1網(wǎng)絡(luò)定義卡牌交易網(wǎng)絡(luò)是一個簡單的網(wǎng)絡(luò)。在卡牌交易網(wǎng)絡(luò)中,卡牌商人可以生產(chǎn)卡牌,玩家可以從商人手里購買卡牌。該網(wǎng)絡(luò)由如下資源組成:
(1)資產(chǎn):卡牌。
(2)參與者:卡牌商人,玩家。
(3)交易:卡牌商人生產(chǎn)卡牌,玩家購買卡牌。
開發(fā)流程如下:
(1)生成工程目錄模板。
(2)資源建模:編寫CTO文件。
(3)業(yè)務(wù)邏輯:編寫交易JS腳本。
(4)訪問控制:編寫ACL。
5.4.2生成工程目錄模板
(1)進入到配置環(huán)境時指定的Fabric工作目錄文件夾,命令行如下:
(2)通過Yeoman自動生成工程目錄結(jié)構(gòu)模板(搭建環(huán)境時已安裝Yoeman和模板),如圖5-3所示。圖5-3使用Yeoman生成工程目錄結(jié)構(gòu)模板
(3)選擇生成空模板,將創(chuàng)建模板文件,如圖5-4所示。圖5-4使用Yeoman生成模板文件成功
5.4.3資源建模
資源建模是指在CTO文件中定義卡片交易網(wǎng)絡(luò)中的資源。Yeoman已經(jīng)自動生成了models文件夾和一個CTO文件,在該CTO文件開頭指定了命名空間(與文件名相同),代碼如下:
1.資產(chǎn)定義
卡片屬于資產(chǎn)。定義卡片的代碼如下:
2.參與者定義
定義參與者時有一個小技巧,由于卡片商人和玩家有很多共同的屬性,如ID、姓名和資金,因此可以定義一個抽象類,讓二者去繼承。
卡片商人和玩家的定義代碼如下:
3.定義交易
在定義交易時,交易的屬性和后面要編寫的交易函數(shù)的傳入?yún)?shù)相對應(yīng)。當(dāng)通過交易創(chuàng)建資產(chǎn)時,屬性通常包含要被創(chuàng)建的資產(chǎn)的屬性。類似于創(chuàng)建一個對象時,要通過傳參來對其屬性進行初始化。
生產(chǎn)卡片交易Transaction的定義代碼如下:
購買卡片交易Transaction的定義代碼如下:
注意:在該交易中只包含了buyer和card兩個依賴,因為卡片的主人(即商人)可以在Card的owner屬性中獲取。交易傳遞參數(shù)時將會遞歸地傳遞依賴及依賴的依賴。
5.4.4業(yè)務(wù)邏輯
HyperledgerComposer中的業(yè)務(wù)邏輯是寫在js函數(shù)中的,CTO中定義的每個交易都必須對應(yīng)著一個js中的函數(shù)。
通過Yeoman生成的空項目模板并不包含lib文件夾和js文件,需要開發(fā)者手動創(chuàng)建。現(xiàn)在的工程目錄如圖5-5所示。圖5-5
card-network工程目錄
接下來依次編寫CTO中定義好的交易。注意:不是所有js中的函數(shù)都會被識別為交易函數(shù),必須使用doc注釋和注解來聲明一個函數(shù)為交易函數(shù),代碼如下:
代碼說明如下:
@param注解用于指定在CTO中定義的交易,tx表示向js函數(shù)中傳入的參數(shù)名。
@transaction注解用于聲明該函數(shù)為交易函數(shù)。
二者缺一不可。
編寫交易函數(shù)非常簡單,代碼如下(建議在logic.js開頭先定義一些常量):
此處定義的命名空間名稱(NS)能夠方便后續(xù)獲取資源實例和注冊器。logic.js中所有的新實例和關(guān)系都需要通過factory對象去創(chuàng)建(factory對象的實現(xiàn)基于設(shè)計模式中的工廠模式)。
生產(chǎn)卡片交易的實現(xiàn)代碼如下:
這段代碼包含最簡單的業(yè)務(wù)邏輯判斷,即商人有足夠的錢即可生產(chǎn)卡片。其整體業(yè)務(wù)邏輯可被簡述為檢查商人的參與者信息,判斷金額是否足夠→產(chǎn)生新的卡片實例并對其屬性進行賦值操作→與注冊器交互,更新相關(guān)資源的狀態(tài)。注釋已經(jīng)足夠詳細,相信大家都能讀懂。但是注意這段代碼有幾個要點:
(1)函數(shù)前加async,這是ES7的異步關(guān)鍵字。獲取注冊器和CRUD操作都是異步的,因此需要進行同步控制,否則將會獲取不到注冊器或是在多個CRUD時代碼提前返回時導(dǎo)致調(diào)用失敗。開發(fā)者只需在函數(shù)調(diào)用前加await即可使異步函數(shù)同步執(zhí)行,省略了定義promise的麻煩。
(2)獲取新實例時需傳入ID,這個ID要由自行拼接或參數(shù)傳入。
(3)使用注冊器的方法進行CRUD操作,注意要加await關(guān)鍵字來同步。
(4)通過拋出異常的方式來使交易失敗。
第一個交易函數(shù)實現(xiàn)了新建資產(chǎn),下面編寫轉(zhuǎn)移資產(chǎn)的代碼。
購買卡片交易代碼如下:
5.4.5訪問控制
通過訪問控制,可以限制哪些參與者能夠?qū)δ男┵Y源進行何種權(quán)限的訪問。訪問控制列表文件后綴為.acl。
雖然本示例中不需要使用ACL,但是默認不配置ACL會使所有資源禁止被任何參與者訪問,因此必須在permissions.acl中配置開放管理員的訪問權(quán)限。訪問權(quán)限包含訪問網(wǎng)絡(luò)和訪問系統(tǒng)資源兩部分。
Yeoman已經(jīng)自動生成了默認配置文件permissions.acl,可直接查看。
配置文件permissions.acl代碼如下:
5.5部
署
和
測
試
5.5.1打包進入終端,使用cd命令切換當(dāng)前目錄至card-network目錄,通過Composer命令打包全部代碼,命令行如下:
card-network目錄下生成了card-network@0.0.1.bna文件,即業(yè)務(wù)網(wǎng)絡(luò)包,如圖5-6所示。圖5-6項目目錄結(jié)構(gòu)及生成的bna包
5.5.2手動部署
手動部署方式需要經(jīng)歷如下步驟:啟動Fabric網(wǎng)絡(luò)、創(chuàng)建節(jié)點管理員、安裝網(wǎng)絡(luò)包、啟動網(wǎng)絡(luò)包、生成業(yè)務(wù)網(wǎng)絡(luò)管理員卡等,較為復(fù)雜。
1.啟動FabricRuntime
通過Composer提供的一鍵啟動腳本啟動網(wǎng)絡(luò),方便快捷,命令行如下:
2.創(chuàng)建節(jié)點管理員
啟動網(wǎng)絡(luò)之后要創(chuàng)建節(jié)點管理員Card。由于業(yè)務(wù)網(wǎng)絡(luò)是部署在Peer節(jié)點上的,因此必須要擁有管理權(quán)限,使Composer能夠訪問Fabric網(wǎng)絡(luò)并在節(jié)點上部署應(yīng)用。創(chuàng)建節(jié)點管理員命令行如下:
3.安裝網(wǎng)絡(luò)包
使用composernetworkinstall命令安裝網(wǎng)絡(luò)包,命令行如下:
4.啟動網(wǎng)絡(luò)包
使用composernetworkstart命令啟動網(wǎng)絡(luò)包,命令如下:
5.訪問網(wǎng)絡(luò)
使用composercardimport命令將剛生成的業(yè)務(wù)網(wǎng)絡(luò)管理員卡導(dǎo)入錢包,之后就可以通過管理員身份訪問網(wǎng)絡(luò),命令行如下:
6.查看card文件列表
使用composercardlist命令查看Card文件列表,命令行如下:
7.網(wǎng)絡(luò)測試
使用composernetworkping命令測試網(wǎng)絡(luò)是否啟動成功,命令行如下:
8.啟動rest-server
指定以網(wǎng)絡(luò)管理員身份啟動rest-server,-n參數(shù)表示不使用命名空間,命令行如下:
5.5.3自動部署
采用自動部署時,推薦使用HyperledgerPlayground可視化界面自動部署項目。
ComposerPlayground的Web界面會調(diào)用ComposerRestServer提供的接口來訪問業(yè)務(wù)網(wǎng)絡(luò),如圖5-7所示。圖5-7
ComposerPlayground工作流
使用ComposerPlayground部署業(yè)務(wù)網(wǎng)絡(luò)非常簡單,下面介紹詳細步驟。
1.啟動ComposerPlayground
直接執(zhí)行下列命令即可啟動ComposerPlayground:
ComposerPlayground支持連接實際業(yè)務(wù)網(wǎng)絡(luò)(即本地FabricRuntime)和Web模擬業(yè)務(wù)網(wǎng)絡(luò)(利用localStorage)。我們使用Web方式即可,省去了啟動Fabric的麻煩,如圖5-8所示。圖5-8
Web方式部署業(yè)務(wù)網(wǎng)絡(luò)包
2.導(dǎo)入業(yè)務(wù)網(wǎng)絡(luò)包
如圖5-9所示,在可視化界面導(dǎo)入文件即可導(dǎo)入業(yè)務(wù)網(wǎng)絡(luò)包。圖5-9可視化導(dǎo)入業(yè)務(wù)網(wǎng)絡(luò)包
3.部署
點擊Deploy即可確認部署,如圖5-10所示。圖5-10確認部署
4.連接業(yè)務(wù)網(wǎng)絡(luò)
完成上述步驟,回到主頁,可以看到關(guān)于Card-Network業(yè)務(wù)網(wǎng)絡(luò)的訪問框。點擊Connectnow即可連接網(wǎng)絡(luò),如圖5-11所示。圖5-11連接業(yè)務(wù)網(wǎng)絡(luò)
5.測試
切換至test界面,進行測試,如圖5-12所示。圖5-12切換至測試界面
1)創(chuàng)建卡片商人
左邊列表可以切換資源,方法為:選中CardSeller,點擊最右邊按鈕,添加一個CardSeller;然后點擊彈窗下方GenerateRandomData生成隨機數(shù)據(jù);最后創(chuàng)建一個ID為1、擁有10塊錢的卡片商人即可,如圖5-13所示。圖5-13創(chuàng)建ID為1、資金為10的卡片商人
卡片商人創(chuàng)建成功后會看到如圖5-14所示的信息。圖5-14創(chuàng)建卡片商人成功
2)創(chuàng)建玩家
按照上述方法繼續(xù)創(chuàng)建一個ID為1、有100塊錢的玩家,如圖5-15所示。圖5-15創(chuàng)建ID為1、資金為100的玩家
3)執(zhí)行交易
下面執(zhí)行交易,點擊左下方按鈕,如圖5-16所示。
圖5-16執(zhí)行交易按鈕
4)制造卡片
選擇制造卡片交易,修改參數(shù),由ID為1的卡片商人制造一張50塊錢的卡,如圖5-17所示。圖5-17執(zhí)行制造卡片交易
5)生成卡片
制造成功,生成了一張Card,同時卡片商人的資金減少10,如圖5-18所示。圖5-18制造卡片交易執(zhí)行成功
6)購買卡片
接下來測試購買卡片交易,修改Card和玩家的ID值,如圖5-19所示。圖5-19執(zhí)行購買卡片交易
執(zhí)行交易后,Card的owner變?yōu)镻layer#1,同時ID為1的玩家資金減少50,ID為1的商人資金增加50。通過左邊列表AllTransactions可以查看所有歷史交易,如圖5-20所示。圖2-2
7)修改文件和升級網(wǎng)絡(luò)
當(dāng)我們需要修改文件和升級網(wǎng)絡(luò)時,選擇頂部define選項卡,點擊左邊f(xié)iles修改文件,然后點擊左下方部署按鈕即可,如圖5-21所示。圖5-21修改代碼界面
本
章
小
結(jié)
本章帶領(lǐng)讀者從零開始學(xué)習(xí)HyperledgerComposer,先給出開發(fā)業(yè)務(wù)網(wǎng)絡(luò)的整體思路,然后依次講解了搭建環(huán)境、CTO建模語言、業(yè)務(wù)邏輯代碼編寫、部署和測試的方法,并且完成了一個簡單的卡片交易業(yè)務(wù)網(wǎng)絡(luò)。讀者此時應(yīng)對HyperledgerComposer的開發(fā)流程有了基本的了解,并且感受到通過Composer開發(fā)區(qū)塊鏈應(yīng)用的方便。
本章重點掌握知識如下:
(1)什么是HyperledgerComposer。
(2)CTO建模語言。
(3)如何編寫業(yè)務(wù)邏輯代碼。
(4)如何手動安裝部署一個業(yè)務(wù)網(wǎng)絡(luò)。
(5)如何利用ComposerPlayground進行測試。
實際上,HyperledgerComposer的功能還遠不止這些。
在接下來的章節(jié)中,讀者會正式投入到業(yè)務(wù)網(wǎng)絡(luò)的開發(fā)中,學(xué)習(xí)和探索HyperledgerComposer更多強大的功能,了解更多設(shè)計原則和網(wǎng)絡(luò)擴展思路。第6章HyperledgerComposer業(yè)務(wù)
網(wǎng)絡(luò)實戰(zhàn)——基礎(chǔ)篇6.1易腐貨物網(wǎng)絡(luò)案例分析6.2共享單車網(wǎng)絡(luò)案例分析本章小結(jié)
6.1易腐貨物網(wǎng)絡(luò)案例分析6.1.1網(wǎng)絡(luò)建模分析業(yè)務(wù)需求后,首先要對需求中涉及的對象和交易建模。該業(yè)務(wù)網(wǎng)絡(luò)涉及如下內(nèi)容:
·易腐貨物;
·業(yè)務(wù)合作伙伴,比如種植者、運輸者和進口商;
·三方簽訂的交易合同;
·易腐貨物的生產(chǎn)、裝運;
·貨物腐爛;
·貨物送達。
1)資產(chǎn)
資產(chǎn)是指在業(yè)務(wù)網(wǎng)絡(luò)中具有一定價值、可被交易或修改狀態(tài)的物品,通常為某個參與者所擁有。
在易腐貨物網(wǎng)絡(luò)中,資產(chǎn)包括如下內(nèi)容:
·易腐貨物(蘋果、香蕉和咖啡);
·三方共同簽訂的交易合同。
2)參與者
加入業(yè)務(wù)網(wǎng)絡(luò)的成員叫做參與者。在易腐貨物網(wǎng)絡(luò)中,將模擬易腐貨物從生產(chǎn)到運輸?shù)阶罱K成功出售所經(jīng)過的流程,因此需要如下參與者:
·種植易腐貨物的種植者;
·運輸易腐貨物的運輸者;
·購置易腐貨物的進口商。
3)訪問控制
在業(yè)務(wù)網(wǎng)絡(luò)中,訪問控制通常是不可或缺的。它能夠控制哪些人能夠?qū)δ男┵Y源進行哪種權(quán)限的訪問,即隱私保護和權(quán)限控制。
在易腐貨物網(wǎng)絡(luò)中,暫時不需要進行訪問控制,使用默認的開放規(guī)則即可。
4)交易
區(qū)塊鏈?zhǔn)且粋€分布式賬本,賬本上記錄的便是交易。交易通常涉及資產(chǎn)的改變或轉(zhuǎn)移,會影響到區(qū)塊鏈賬本的狀態(tài),類似于區(qū)塊鏈中的“智能合約”。
在業(yè)務(wù)網(wǎng)絡(luò)中,通過發(fā)起交易來執(zhí)行對應(yīng)的業(yè)務(wù)邏輯。
易腐貨物網(wǎng)絡(luò)將會產(chǎn)生如下交易:
(1)種植出易腐貨物;
(2)種植者、進口商、運輸者三方簽訂交易合同;
(3)貨物送達;
(4)貨物中途腐爛。
5)事件
若開發(fā)者希望區(qū)塊鏈中產(chǎn)生交易或某資產(chǎn)發(fā)生改變時能夠收到相應(yīng)的通知提醒或執(zhí)行相關(guān)后續(xù)操作,則可以使用事件機制。
事件采用的是發(fā)布/訂閱方式,區(qū)別于發(fā)送/接收方式。所有訂閱了事件的用戶(應(yīng)用程序)在該事件發(fā)生時都會收到相應(yīng)的通知,以進行相應(yīng)的處理。
易腐貨物網(wǎng)絡(luò)的事件是當(dāng)貨物腐爛時發(fā)出警報。
確認上述模型后,開始編寫代碼實現(xiàn)模型和交易。
6.1.2代碼實現(xiàn)
在第5章中,讀者應(yīng)已熟悉工程模板的生成、基本的CTO建模語法以及簡單業(yè)務(wù)邏輯代碼的編寫。
代碼編寫包括CTO建模、業(yè)務(wù)邏輯、訪問控制列表三個部分。首先,使用Yeoman生成工程目錄結(jié)構(gòu),并新建lib文件夾和logic.js,工程目錄結(jié)構(gòu)如圖6-1所示。圖6-1工程目錄結(jié)構(gòu)
1.CTO建模
CTO建模就是編寫.cto文件,將業(yè)務(wù)網(wǎng)絡(luò)涉及的資源用面向?qū)ο笳Z法來表示。
模板自動在cto文件開頭生成了命名空間,代碼如下:
1)枚舉
由于易腐貨物具有相同的屬性(如名稱),因此無需把每種貨物都定義一個資產(chǎn),只需定義一個枚舉來表示貨物類別即可。
假設(shè)貨物類別有蘋果、香蕉和咖啡,則該貨物類別的枚舉代碼如下:
本例中的貨物狀態(tài)包括已創(chuàng)建、運輸中、已送達和已腐爛,該貨物狀態(tài)的枚舉代碼如下:
2)資產(chǎn)
對于擁有相同屬性(如id)的資產(chǎn)或參與者,可以使用抽象類來節(jié)約代碼量。抽象類無法被實例化,但它可被用作該類型的其他資產(chǎn)的超類型(super-type)。資產(chǎn)將擁有所指定的超類型所擁有的屬性,并且能夠根據(jù)定義追加新的屬性。
資產(chǎn)抽象類定義代碼如下:
易腐貨物定義代碼如下:
注意:資產(chǎn)類“Goods”的超類型“BaseAsset”的抽象屬性不會被其繼承。
由于易腐貨物剛產(chǎn)生時還無法確定運輸者和進口商,因此要為這兩個屬性添加optional(可選的)關(guān)鍵字,使得該屬性接受空值,否則在創(chuàng)建實例時會報錯。
交易合同定義代碼如下:
3)參與者
參與者抽象類定義代碼如下:
該抽象類定義了業(yè)務(wù)網(wǎng)絡(luò)參與者的通用屬性,其他參與者只需繼承該抽象類即可。
4)交易
交易中的屬性和依賴對應(yīng)于業(yè)務(wù)邏輯交易函數(shù)的參數(shù)。調(diào)用交易函數(shù)時,會傳入一個交易實例,從交易實例中可獲取到輸入?yún)?shù),因此,在定義交易模型時也要考慮交易函數(shù)的參數(shù),類似編寫面向?qū)ο缶幊陶Z言中的接口。
定義交易模型的屬性和依賴的三個原則如下:
·全面:保證參數(shù)滿足業(yè)務(wù)需求;
·精準(zhǔn):避免無用的參數(shù);
·易讀:屬性名稱和類型對應(yīng),并適當(dāng)添加注釋。
接下來講述易腐貨物網(wǎng)絡(luò)中的交易定義。
生產(chǎn)易腐貨物交易結(jié)構(gòu)體代碼如下:
簽訂合同交易結(jié)構(gòu)體代碼如下:
貨物送達交易結(jié)構(gòu)體代碼如下:
此處通過一個合同依賴即可獲取到所有參與合同簽訂的參與者,因此無需顯式定義它們,以便代碼更加精簡,避免屬性冗余。在該階段中,若交易雙方確認貨物運輸行為已完成,則可對所引用合約進行相應(yīng)的履約操作。
貨物腐爛結(jié)構(gòu)體代碼如下:
5)事件
如何在貨物腐爛時,向客戶端發(fā)送一個通知呢?可以通過定義事件來實現(xiàn)。
貨物腐爛事件代碼如下:
2.業(yè)務(wù)邏輯
HyperledgerComposer的業(yè)務(wù)邏輯代碼寫在lib目錄下的js文件中。Yeoman已經(jīng)默認生成了logic.js,直接編寫該文件即可。
1)常量定義
在交易函數(shù)前,可以定義一些在函數(shù)中經(jīng)常使用的對象、變量、枚舉等。
上述代碼中,getFactory是HyperledgerComposer提供的API,用于獲取工廠對象;工廠用于創(chuàng)建新的資源實例。
由于命名空間將多次出現(xiàn)在交易函數(shù)中,因此在開頭將其定義成常量。
在CTO建模時定義的枚舉在js中推薦轉(zhuǎn)換為定義一個屬性名全部大寫的對象,屬性值定義成對應(yīng)的大寫字符串。
2)種植易腐貨物
編寫交易函數(shù)的一般流程如圖6-2所示。圖6-2編寫交易函數(shù)的流程
種植者須消耗一定金錢去種植貨物,即創(chuàng)建易腐貨物實例。如果金錢不足,則不能種植。
交易函數(shù)的詳細代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:獲取交易發(fā)起者的參與者信息→檢查余額是否充足并扣除指定數(shù)目余額→創(chuàng)建新的貨物實例并賦值→與注冊器交互,更新相關(guān)資源的狀態(tài)。每個交易函數(shù)在定義前都要添加async關(guān)鍵字,獲取及使用注冊器時必須添加await關(guān)鍵字。
3)簽訂合同
下面的代碼看似比較復(fù)雜,其實大多是給新對象賦值的冗余代碼。讀者可自行使用lodash.js等工具庫來簡化對象賦值操作。交易代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:創(chuàng)建合同并根據(jù)傳入?yún)?shù)對合同屬性進行賦值→更新貨物(Goods)資產(chǎn)實例中對進口商(importer)、運輸者(shipper)的引用并更新貨物狀態(tài)→與注冊器交互,更新相關(guān)資源的狀態(tài)。
4)貨物到達
貨物到達后,要修改貨物狀態(tài)并判斷貨物是否腐爛。若腐爛,則運輸者進行賠償;否則進口商支付運輸者和種植者一定費用。函數(shù)中須獲取三個參與者和貨物的注冊器,對它們進行更新操作。
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:調(diào)取合約中各個參與者以及貨物的狀態(tài)信息→檢查貨物狀態(tài)(是否腐爛)→根據(jù)貨物狀態(tài)分配參與者資金→與注冊器交互,更新相關(guān)資源的狀態(tài)。
5)貨物腐爛
貨物腐爛(在業(yè)務(wù)網(wǎng)絡(luò)中具體表現(xiàn)為一個“貨物腐爛”(GoodsBlet)交易被發(fā)起)時,會觸發(fā)通知事件。事件可被外部應(yīng)用監(jiān)聽并接收。
事件的觸發(fā)流程如圖6-3所示。圖6-3事件觸發(fā)流程
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:調(diào)取交易中引用的貨物實例→更新貨物狀態(tài)為“已腐爛”→與注冊器交互,更新相關(guān)資源的狀態(tài)→創(chuàng)建新事件,定義事件類型和事件屬性→觸發(fā)事件。
3.訪問控制列表
目前無需對該網(wǎng)絡(luò)進行訪問控制,因此使用模板生成的默認訪問控制列表文件permissions.acl即可,所有用戶資源和系統(tǒng)資源都會開放訪問。該文件內(nèi)容如下:
4.代碼測試
代碼編寫完成,接下來使用命令將其打包并部署到ComposerPlayground上進行測試。
1)打包
打包命令如下:
2)啟動
啟動ComposerPlayground命令如下:
3)部署
以web方式部署,如圖6-4和圖6-5所示。圖6-4點擊部署一個業(yè)務(wù)網(wǎng)絡(luò)圖6-5點擊Drophere上傳本地網(wǎng)絡(luò)包
6.1.3情景測試
1.貨物交易成功
種植者種出一批香蕉,要賣給進口商,由運輸者負責(zé)這批香蕉的運輸,三方之間簽訂了一份交易合同。
合同簽訂后,運輸者開始運輸貨物。
風(fēng)和日麗,貨物在腐爛之前成功送達給進口商。進口商將按合同支付種植者貨物金額和運輸者的運輸費用。
(1)創(chuàng)建種植者,代碼如下:
(2)創(chuàng)建進口商,代碼如下:
(3)創(chuàng)建運輸者,代碼如下:
(4)種植者種植香蕉。要通過ComposerPlayground執(zhí)行一個交易,須先選擇對應(yīng)的交易類型,添加請求參數(shù)并提交。
請求數(shù)據(jù)如下:
執(zhí)行交易后,種植者花費10金錢來種植香蕉,結(jié)果數(shù)據(jù)如下:
產(chǎn)生了一個香蕉實例,其id由種植者id和當(dāng)前時間(毫秒數(shù))拼接而成。
(5)三方簽訂合同。發(fā)起一個簽訂合同交易,請求數(shù)據(jù)如下:
創(chuàng)建了一份合同,結(jié)果數(shù)據(jù)如下:
同時,運輸?shù)呢浳锏膕hipper和importer依賴都和相應(yīng)參與者關(guān)聯(lián),且狀態(tài)改為“運輸中”,結(jié)果數(shù)據(jù)如下:
(6)貨物送達。發(fā)起貨物送達交易,請求數(shù)據(jù)如下:
貨物狀態(tài)修改為“已送達”,結(jié)果數(shù)據(jù)如下:
種植者金錢增加20,結(jié)果數(shù)據(jù)如下:
進口商金錢減少40(運輸費+貨物價格),結(jié)果數(shù)據(jù)如下:
運輸者金錢增加20(運輸費),結(jié)果代碼如下:
2.貨物中途腐爛
種植者又種出一批蘋果,要賣給進口商,由運輸者負責(zé)運輸,三方之間再次簽訂了一份交易合同。
合同簽訂后,運輸者開始運輸。
可惜,風(fēng)浪導(dǎo)致貨物在中途腐爛,運輸者不得不按合同賠償種植者和進口商。
(1)種植者種植蘋果。按上述步驟執(zhí)行種植蘋果交易,結(jié)果數(shù)據(jù)如下:
種植者金錢減少10(種植費),結(jié)果數(shù)據(jù)如下:
(2)三方簽訂合同。執(zhí)行簽訂合同交易,請求數(shù)據(jù)如下:
創(chuàng)建了一個新的合同,結(jié)果數(shù)據(jù)如下:
(3)貨物腐爛。執(zhí)行貨物腐爛交易,請求數(shù)據(jù)如下:
蘋果的狀態(tài)改變?yōu)椤耙迅癄€”,結(jié)果數(shù)據(jù)如下:
該交易函數(shù)觸發(fā)了一個事件,可以在Playground左側(cè)的歷史記錄中查看,如圖6-6所示。圖6-6貨物腐爛事件
(4)貨物到達。執(zhí)行貨物到達交易,請求數(shù)據(jù)如下:
由于貨物腐爛,屬于運輸者違約,因此種植者和進口商都將獲得賠償。種植者金錢增加20,結(jié)果數(shù)據(jù)如下:
運輸者金錢減少50,結(jié)果數(shù)據(jù)如下:
6.1.4網(wǎng)絡(luò)擴展
1.合理性擴展
細心的讀者會發(fā)現(xiàn),前述章節(jié)在業(yè)務(wù)邏輯代碼中添加了一些校驗。如只有當(dāng)種植者金錢足夠時才能種植,否則將拋出異常。這就是合理性的體現(xiàn)。
編寫好基礎(chǔ)的邏輯代碼后,在進行網(wǎng)絡(luò)擴展時,首先應(yīng)考慮合理性擴展。有時,一個不合理的交易就會導(dǎo)致整個賬本數(shù)據(jù)合理性的雪崩!
在考慮合理性時,要綜合考慮多種情況,尤其是并發(fā)時的合理性。如要防止一箱易腐貨物同時被多個進口商購買。
在易腐貨物網(wǎng)絡(luò)中,可進行如下合理性擴展:
(1)簽訂合同時判斷進口商是否有足夠的金錢進貨,同時判斷運輸者是否有空余的運力。
(2)貨物送達時,再次判斷進口商是否有足夠的金錢購買貨物,因為運送期間其資金狀況有可能改變。
(3)一批貨物只能對應(yīng)一個合同。
2.安全性擴展
安全性擴展通常是指訪問控制。雖然易腐貨物網(wǎng)絡(luò)中暫未添加禁止訪問策略,但在實際應(yīng)用場景中,訪問控制不可或缺。
在易腐貨物網(wǎng)絡(luò)中,可進行如下安全性擴展:
將三方合同分為兩兩之間的合同,只有合同的簽訂者可以查看該合同。
3.模型擴展
模型擴展是指為業(yè)務(wù)網(wǎng)絡(luò)添加更多的資源,可以是資產(chǎn)、參與者、事件等類型,也可以為已有資源添加屬性和依賴,從而為功能擴展打下基礎(chǔ)。
通常模型擴展要做到OOP(ObjectOrientedProgramming,面向?qū)ο缶幊?的“開閉原則”,即對擴展開放,對修改關(guān)閉。同時應(yīng)盡量使模型的擴展不影響到已有代碼,尤其是在區(qū)塊鏈環(huán)境中,這種修改可能對賬本來說是破壞性的。因此對于模型最初的設(shè)計和每一步的擴展都要謹慎考慮。
在易腐貨物網(wǎng)絡(luò)中,可進行如下模型擴展:
·添加資產(chǎn)——船,來表示運輸者的運力。
·添加參與者——公證人,來證明合同的有效性。
·添加事件——貨物送達。
4.功能擴展
功能擴展通常依賴于模型擴展。每當(dāng)新增模型時,通常都要為該模型添加一定功能。此處的功能即定義新的交易或擴展現(xiàn)有交易邏輯。
注意:不要讓單個js文件太過龐大。當(dāng)交易類型很多時,可對交易進行垂直業(yè)務(wù)劃分,僅將同類的交易函數(shù)寫入同一js文件中,以此來提高代碼的可讀性和可維護性。
當(dāng)單一業(yè)務(wù)邏輯函數(shù)很復(fù)雜、行數(shù)很多時,可以采用“微服務(wù)”的思想,將其中的部分邏輯單獨封裝成一個通用函數(shù),供其他交易函數(shù)調(diào)用,這大大提高了代碼的可復(fù)用性和可維護性。
在易腐貨物網(wǎng)絡(luò)中,可進行如下功能擴展:
·周期性地記錄易腐貨物的溫度,動態(tài)判斷貨物是否腐爛。
·公證人證明合同生效。
·合同違約。
6.2共享單車網(wǎng)絡(luò)案例分析
6.2.1網(wǎng)絡(luò)建模該業(yè)務(wù)網(wǎng)絡(luò)涉及共享單車,單車生產(chǎn)者、用戶,生產(chǎn)單車,租用單車,歸還單車。真實的場景十分復(fù)雜。此處的業(yè)務(wù)網(wǎng)絡(luò)用作入門,將真實場景簡化,僅涉及最核心的交易部分。
1.資產(chǎn)
在共享單車網(wǎng)絡(luò)中,資產(chǎn)為共享單車。
2.參與者
加入業(yè)務(wù)網(wǎng)絡(luò)的成員叫做參與者。在共享單車網(wǎng)絡(luò)中,將模擬一輛共享單車從被生產(chǎn)到被租用再到被歸還的過程,因此需要如下參與者:
生產(chǎn)共享單車的生產(chǎn)商;
租用共享單車的用戶。
3.訪問控制
在共享單車網(wǎng)絡(luò)中,暫時不需要進行訪問控制,使用默認開放規(guī)則即可。
4.交易
共享單車網(wǎng)絡(luò)將會產(chǎn)生如下交易:
生產(chǎn)商生產(chǎn)一輛單車;
用戶租用一輛單車;
用戶歸還單車。
5.事件
共享單車網(wǎng)絡(luò)會觸發(fā)如下事件:
單車被租用時進行通知;
單車被歸還時進行通知。
確定網(wǎng)絡(luò)模型后,開始編寫代碼。
6.2.2代碼實現(xiàn)
代碼編寫包括CTO建模、業(yè)務(wù)邏輯、訪問控制列表三個部分。首先,使用Yeoman生成工程目錄結(jié)構(gòu),并新建lib文件夾和logic.js,如圖6-7所示。圖6-7工程目錄結(jié)構(gòu)
1.CTO建模
模板自動在cto文件開頭生成了命名空間代碼:
1)枚舉
共享單車狀態(tài)枚舉代碼如下:
2)概念
因為用戶、生產(chǎn)商和單車都需要有地址屬性,所以將其定義為概念(concept),即一組多資源通用的屬性組合。概念具有與資產(chǎn)、參與者、交易相似的類結(jié)構(gòu),但它們的存在更為“抽象”,通常被作為一個屬性包含于資產(chǎn)、參與者或交易類中。
地址定義代碼如下:
3)資產(chǎn)
共享單車定義代碼如下:
4)參與者
抽象參與者定義代碼如下:
5)交易
在此交易中,生產(chǎn)共享單車,會創(chuàng)建一輛單車,因此須定義一些單車的屬性。
生產(chǎn)單車交易定義代碼如下:
使用單車交易定義代碼如下:
歸還共享單車交易定義代碼如下:
6)事件
用戶租用單車事件(使用name屬性來傳遞其中一些事件內(nèi)容)代碼如下:
單車被歸還事件代碼如下:
2.業(yè)務(wù)邏輯
該步驟的任務(wù)是編寫交易函數(shù)到lib目錄下的logic.js文件中。
1)常量定義
有關(guān)常量定義的作用在5.4.4中已作解釋,代碼如下:
2)生產(chǎn)共享單車
生產(chǎn)共享單車交易的代碼如下:
第25行使用了js內(nèi)置的向數(shù)組添加元素的函數(shù)push。上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:獲取相關(guān)單車生產(chǎn)商的參與者信息→檢查余額是否充足并扣除指定數(shù)目的余額→創(chuàng)建新的單車實例并賦值→與注冊器交互,更新相關(guān)資源的狀態(tài)。
3)使用共享單車
使用共享單車函數(shù)觸發(fā)了一個事件,該事件訂閱者將在用戶使用單車時收到消息。該交易的完整代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被概括為:獲取交易雙方的參與者信息→檢查單車狀態(tài)是否為“可用”→檢查消費者余額是否充足并扣除指定數(shù)目的余額轉(zhuǎn)至單車供應(yīng)商的賬戶→修改單車的使用狀態(tài)與當(dāng)前使用者→與注冊器交互,更新相關(guān)資源的狀態(tài)→發(fā)布“租用單車”事件。
4)歸還共享單車
歸還共享單車函數(shù)觸發(fā)了一個事件,該事件訂閱者將在用戶使用單車時收到消息。該交易的完整代碼如下:
3.測試
代碼編寫完成,接下來將其打包并部署到ComposerPlayground上進行測試。
(1)打包命令如下:
(2)啟動ComposerPlayground命令如下:
(3)以web方式部署bna網(wǎng)絡(luò)包即可完成測試。
6.2.3情景測試
接下來通過情景模擬來測試網(wǎng)絡(luò)。情景模擬分為兩種,一種是使用共享單車并歸還,另一種是無法使用共享單車。下面具體加以講述。
1.使用共享單車并歸還
該情景模擬為:某生產(chǎn)商生產(chǎn)了一輛共享單車,將其投放到居民區(qū);用戶使用了這輛單車并按時歸還。
1)創(chuàng)建生產(chǎn)商
輸入數(shù)據(jù)如下:
2)創(chuàng)建用戶
輸入數(shù)據(jù)如下:
3)生產(chǎn)商生產(chǎn)單車
生產(chǎn)一輛單車,請求數(shù)據(jù)如下:
新生產(chǎn)了一輛單車,結(jié)果數(shù)據(jù)如下:
生產(chǎn)商花費10金錢生產(chǎn)單車,并將新生產(chǎn)的單車加入至已生產(chǎn)數(shù)組。結(jié)果數(shù)據(jù)如下:
4)用戶使用單車
用戶發(fā)起一個使用單車交易,請求數(shù)據(jù)如下:
單車狀態(tài)更改為“使用中”,且綁定了使用者,結(jié)果數(shù)據(jù)如下:
使用者扣除20金錢的使用費,結(jié)果數(shù)據(jù)如下:
該交易函數(shù)觸發(fā)了事件,可在Playground左側(cè)的歷史記錄中查看,如圖6-8所示。圖6-8單車租用事件
5)用戶歸還單車
執(zhí)行用戶歸還單車交易數(shù)據(jù)如下:
單車狀態(tài)重置為“可用”,數(shù)據(jù)如下:
該交易觸發(fā)了一個“單車歸還”事件(BikeBeReturnedEvent),如圖6-9所示。圖6-9單車歸還事件
2.無法使用單車
該情景模擬為:用戶使用完單車后,生產(chǎn)商將該單車拿去維修,因此該單車無法再次被使用。
1)修改單車狀態(tài)
使用Playground手動更新單車狀態(tài)為“修理中”,數(shù)據(jù)如下:
2)用戶使用單車
用戶執(zhí)行使用單車交易,請求數(shù)據(jù)如下:
用戶看到錯誤提示,交易執(zhí)行失敗,賬本狀態(tài)將不會發(fā)生任何改變,如圖6-10所示。圖6-10交易錯誤提示
歷史記錄中不會顯示失敗的交易信息,如圖6-11所示。圖6-11歷史記錄
6.2.4共享單車網(wǎng)絡(luò)擴展
共享單車網(wǎng)絡(luò)可從以下四個方面進行擴展:
1.合理性擴展
可在業(yè)務(wù)邏輯代碼中添加一些校驗,如只有當(dāng)單車處于“可用”狀態(tài)時,用戶才可以使用它,否則將拋出異常;又如只有當(dāng)生產(chǎn)商有足夠的金錢時才能生產(chǎn)單車,用戶有足夠的金錢時才能使用單車。
在編寫好基礎(chǔ)的邏輯代碼,進行網(wǎng)絡(luò)擴展時,首先應(yīng)該考慮的是合理性擴展。
在共享單車網(wǎng)絡(luò)中,可進行如下合理性擴展:用戶只能使用其所在地點(Address)的單車。
2.安全性擴展
安全性擴展通常是指訪問控制。雖然在共享單車網(wǎng)絡(luò)中未添加禁止訪問策略,但在實際應(yīng)用場景中,訪問控制不可或缺。
在共享單車網(wǎng)絡(luò)中,可進行如下安全性擴展:
·只有生產(chǎn)商能維修自行車;
·用戶不能使用及歸還他人的自行車。
3.模型擴展
模型擴展是指為業(yè)務(wù)網(wǎng)絡(luò)添加更多的資源,可以是資產(chǎn)、參與者、事件等類型,也可以為已有資源添加屬性和依賴,從而為功能擴展打下基礎(chǔ)。
在共享單車網(wǎng)絡(luò)中,可以進行如下模型擴展:
·添加資產(chǎn)——會員卡,持有者用車可以享受優(yōu)惠;
·添加參與者——警察,禁止單車的隨意停放;
·添加事件——使用費的扣除和到賬。
4.功能擴展
在共享單車網(wǎng)絡(luò)中,可進行如下功能擴展:
·根據(jù)時間計費;
·禁止用戶還車時隨意停放;
·持有會員卡的用戶使用單車時享受優(yōu)惠。
本
章
小
結(jié)
本章帶領(lǐng)讀者使用HyperledgerComposer開發(fā)了兩個簡單的區(qū)塊鏈業(yè)務(wù)網(wǎng)絡(luò),學(xué)習(xí)了HyperledgerComposer的可選屬性、概念、事件等用法,并在編碼后進行了情景測試,為讀者提供了擴展網(wǎng)絡(luò)的思路。
因為業(yè)務(wù)邏輯代碼使用Javascript腳本語言編寫,所以可直接使用Js的原生api,比如共享單車網(wǎng)絡(luò)中的數(shù)組操作。
由于業(yè)務(wù)網(wǎng)絡(luò)打包依賴于npm,這表示業(yè)務(wù)邏輯代碼支持模塊化,因此甚至可以使用網(wǎng)絡(luò)上的npm包和Js組件庫,以減少重復(fù)的代碼。
讀者此時已經(jīng)具有了獨立開發(fā)一個簡單業(yè)務(wù)網(wǎng)絡(luò)的能力,但是HyperledgerComposer還有更強大的功能。休息一下,進入下一章的學(xué)習(xí),繼續(xù)在區(qū)塊鏈的開發(fā)之路上探索吧!第7章HyperledgerComposer業(yè)務(wù)
網(wǎng)絡(luò)實戰(zhàn)——提高篇7.1貨幣貿(mào)易網(wǎng)絡(luò)案例分析7.2能源購置網(wǎng)絡(luò)案例分析7.3產(chǎn)品拍賣網(wǎng)絡(luò)案例分析本章小結(jié)
7.1貨幣貿(mào)易網(wǎng)絡(luò)案例分析
7.1.1網(wǎng)絡(luò)建模該業(yè)務(wù)網(wǎng)絡(luò)涉及以下幾個方面的內(nèi)容:貨幣,交易者、警察,制造貨幣,交易貨幣,銷毀假幣。資產(chǎn)包含貨幣。在貨幣貿(mào)易網(wǎng)絡(luò)中,將模擬貨幣生產(chǎn)、交易以及假幣銷毀的過程,因此需要如下參與者:交易者,警察。
交易包含業(yè)務(wù)如下:
·交易者制造貨幣;
·交易者之間交易貨幣;
·警察銷毀假幣;
·批量銷毀貨幣。
確認模型后,開始編寫代碼實現(xiàn)模型。
7.1.2代碼實現(xiàn)
首先用Yeoman生成工程目錄結(jié)構(gòu),并新建lib文件夾和logic.js,如圖7-1所示。圖7-1工程目錄結(jié)構(gòu)
1.CTO建模
1)利用枚舉設(shè)置狀態(tài)
使用貨幣狀態(tài)來標(biāo)識貨幣的真?zhèn)危媒灰渍郀顟B(tài)標(biāo)識其是否合法。
貨幣狀態(tài)如下:
交易者狀態(tài)如下:
2)設(shè)置相關(guān)資產(chǎn)
貨幣結(jié)構(gòu)如下(通過引用類型指向該貨幣目前的擁有者與貨幣制造者):
3)設(shè)置參與者
設(shè)置參與者的抽象類,結(jié)構(gòu)如下:
貨幣交易者結(jié)構(gòu)如下(通過引用類型數(shù)組指向該交易者現(xiàn)持有的貨幣):
警察的結(jié)構(gòu)如下:
4)編寫交易代碼
制造貨幣交易代碼如下:
交易貨幣交易代碼如下:
銷毀假幣交易代碼如下:
批量銷毀貨幣交易代碼如下:
2.業(yè)務(wù)邏輯
貨幣貿(mào)易網(wǎng)絡(luò)的業(yè)務(wù)邏輯代碼寫在lib目錄下的logic.js文件中。
(1)常量定義,代碼如下:
(2)制造貨幣,代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被簡述為:獲取貨幣制造者的參與者信息并判斷操作是否合法→創(chuàng)建新的貨幣實例并賦值→將新的貨幣實例加入制造者的“現(xiàn)持有貨幣”數(shù)組→與注冊器交互更新相應(yīng)資源的狀態(tài)。
(3)交易貨幣,代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被簡述為:獲取交易雙方的參與者信息并判斷購買者余額是否足夠→改變交易雙方的剩余額度→將交易中的貨幣實例加入買方的“現(xiàn)持有貨幣”數(shù)組,并從賣方的對應(yīng)數(shù)組中移除該貨幣→與注冊器交互更新相應(yīng)資源的狀態(tài)。
(4)銷毀貨幣,代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被簡述為:檢查被操作貨幣的屬性→若滿足條件,則從“持有貨幣”數(shù)組中移除該貨幣實例并標(biāo)記貨幣制造者為‘非法’用戶→與注冊器交互,對貨幣實例進行銷毀操作→與注冊器交互更新相應(yīng)資源的狀態(tài)。
(5)批量銷毀貨幣,代碼如下:
業(yè)務(wù)邏輯所用到的輔助函數(shù)selectCoinsByStatus可用如下方式進行配置:
①
在項目根目錄(trade-network)下新建queries.qry文件,所有的自定義查詢都編寫在該文件中。
②
定義一個查詢。Hyperledger天生支持LevelDB和CouchDB兩種數(shù)據(jù)庫,因此可以使用類sql語句從數(shù)據(jù)庫中查詢數(shù)據(jù)。
批量銷毀貨幣交易時,需接收一個貨幣狀態(tài)參數(shù),因此要使用條件查詢(where)。查詢status等于傳入貨幣狀態(tài)的所有貨幣,代碼如下:
(6)編寫輔助函數(shù)。從貨幣數(shù)組中移除指定貨幣,可通過遍歷“貨幣持有”數(shù)組中的貨幣實例,根據(jù)貨幣ID判斷其是否為需要移除的對象。代碼如下:
7.1.3情景模擬
1.貨幣交易
小王和小明是兩位交易者。小王制作了一枚貨幣,小明想用金錢將其買下來。
(1)創(chuàng)建交易者小王和小明,代碼如下:
(2)執(zhí)行制造貨幣交易(MakeCoinTransaction),制造一枚貨幣,代碼如下:
新創(chuàng)建的貨幣信息如下所示(剛生產(chǎn)的貨幣的owner和maker相同):
根據(jù)業(yè)務(wù)邏輯,該貨幣將被自動放入制作者的錢包,代碼如下:
(3)購買貨幣,執(zhí)行貨幣交易(TradeCoinTransaction),代碼如下:
交易成功,該貨幣更換了主人,代碼如下:
賣方(貨幣制造者)金錢增加20,數(shù)據(jù)如下:
買方金錢減少20,將買到的貨幣放入錢包,數(shù)據(jù)如下:
2.假幣銷毀
上述情景中,小王實際上制作了一枚假幣!因此警察將會銷毀該假幣并禁止小王再次制作貨幣。
(1)創(chuàng)建警察,警察信息如下:
(2)發(fā)起銷毀假幣交易(DestoryIllegalCoinTransaction),交易信息如下:
假幣制造者被標(biāo)為“非法的”,代碼如下:
警察銷毀假幣數(shù)?+?1,代碼如下:
假幣已從貨幣擁有者的錢包移除,代碼如下:
3.假幣制造者再次制幣
執(zhí)行制造貨幣交易,代碼如下:
將看到錯誤提示,交易執(zhí)行失敗,賬本狀態(tài)將不會發(fā)生任何改變,如圖7-2所示。圖7-2錯誤提示
4.批量銷毀貨幣
手動創(chuàng)建兩個合法和兩個非法的貨幣,如圖7-3所示。圖7-3創(chuàng)建貨幣
執(zhí)行兩次批量銷毀貨幣交易,分別銷毀所有合法和非法的貨幣(status分別為LEGAL和ILLEGAL),代碼如下:
7.1.4網(wǎng)絡(luò)擴展
(1)進行合理性擴展,包含內(nèi)容如下:
·貨幣制作后立即檢驗,防止假幣流通;
·防止自買自賣。
(2)進行安全性擴展,包含內(nèi)容如下:
·只有警察可以訪問假幣。
(3)進行模型擴展,包含內(nèi)容如下:
·添加資產(chǎn)——新幣種;
·添加參與者——法庭,對假幣制造者進行裁決;
·添加參與者——黃牛,大量收獲貨幣并高價賣出。
(4)進行功能擴展,包含內(nèi)容如下:
·支持貨幣和貨幣間的交換;
·批量制作貨幣或批量購買貨幣優(yōu)惠;
·對假幣制造者進行金錢懲罰。
7.2能源購置網(wǎng)絡(luò)案例分析
7.2.1網(wǎng)絡(luò)定義該業(yè)務(wù)網(wǎng)絡(luò)涉及如下內(nèi)容:
·貨幣、能源
·居民、銀行、能源公司
·金錢、貨幣和能源之間的交易
(1)資產(chǎn)包含如下內(nèi)容:貨幣,能源。
(2)參與者包含如下內(nèi)容:居民,銀行,能源公司。
在能源購置網(wǎng)絡(luò)中,將模擬居民用銀行發(fā)行的貨幣來購買能源的過程。
(3)交易包含如下內(nèi)容:居民用金錢購買貨幣;居民用貨幣購買能源;居民退還貨幣,獲得金錢。
確認網(wǎng)絡(luò)中的模型后,即可編寫代碼實現(xiàn)模型和交易。
7.2.2代碼實現(xiàn)
首先用Yeoman生成工程目錄結(jié)構(gòu),并新建lib文件夾和logic.js。
1.CTO建模
1)利用枚舉設(shè)置貨幣持有者
貨幣持有者類型結(jié)構(gòu)如下:
2)設(shè)置相關(guān)資產(chǎn)類
設(shè)置抽象類,結(jié)構(gòu)如下:
設(shè)置貨幣類,代碼如下:
3)設(shè)置參與者相關(guān)類
設(shè)置參與者抽象類,結(jié)構(gòu)如下:
4)編寫交易代碼
居民用金錢從銀行購買貨幣,代碼如下:
居民用貨幣從能源公司購買能源,代碼如下:
居民從銀行將貨幣兌換成金錢,代碼如下:
2.業(yè)務(wù)邏輯
能源購置網(wǎng)絡(luò)的業(yè)務(wù)邏輯代碼寫在lib目錄下的logic.js文件中。
(1)常量定義,代碼如下:
(2)用金錢購買貨幣,代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被簡述為:獲取交易雙方的參與者信息并檢查購買者的余額是否足夠→將貨幣實例從賣方轉(zhuǎn)移至購買方→調(diào)整交易雙方的余額→與注冊器交互并更新相關(guān)資源的狀態(tài)。
(3)用貨幣購買能源,代碼如下:
上述代碼對應(yīng)的業(yè)務(wù)邏輯可被簡述為:獲取交易雙方的參與者信息→將貨幣實例從居民轉(zhuǎn)移至能源公司→將能源實例從能源公司轉(zhuǎn)移至居民→與注冊器交互并更新相關(guān)資源的狀態(tài)。
(4)將貨幣兌換成金錢,代碼如下:
(5)編寫輔助函數(shù)。從數(shù)組中移除指定元素,代碼如下:
7.2.3情景模擬
1.購買能源
某居民區(qū)附近有銀行和能源公司,銀行發(fā)行了一批貨幣,居民先從銀行購買貨幣,再使用貨幣從能源公司購買能源。
(1)創(chuàng)建居民,數(shù)據(jù)如下:
(2)創(chuàng)建銀行,數(shù)據(jù)如下:
(3)創(chuàng)建能源公司,數(shù)據(jù)如下:
(4)創(chuàng)建兩個貨幣,數(shù)據(jù)如下:
(5)創(chuàng)建能源實例,擁有者是id為1的公司,數(shù)據(jù)如下:
(6)居民從銀行購買貨幣,執(zhí)行購買貨幣交易(MoneyToCoinTransaction),數(shù)據(jù)如下:
貨幣的擁有者發(fā)生改變,數(shù)據(jù)如下:
銀行獲得20金錢,且支出了一枚貨幣,數(shù)據(jù)如下:
居民支出20金錢,且獲得了一枚貨幣,數(shù)據(jù)如下:
(7)居民用貨幣購買能源,執(zhí)行貨幣換能源交易(CoinToEnergyTransaction),數(shù)據(jù)如下:
能源的擁有者發(fā)生改變,數(shù)據(jù)如下:
貨幣的擁有者發(fā)生改變,數(shù)據(jù)如下:
公司支出能源,獲得貨幣,數(shù)據(jù)如下:
居民支出貨幣,獲得能源,數(shù)據(jù)如下:
2.退還貨幣
該居民又買了一枚貨幣,但發(fā)現(xiàn)目前不需要它,于是決定退還貨幣給銀行。
1)再次購買貨幣
執(zhí)行購買貨幣交易(MoneyToCoinTransaction),數(shù)據(jù)如下:
銀行獲得20金錢,支出貨幣,數(shù)據(jù)如下:
居民支出20金錢,獲得貨幣,數(shù)據(jù)如下:
2)執(zhí)行退還貨幣操作
執(zhí)行貨幣換金錢交易(CoinToMoneyTransaction),數(shù)據(jù)如下:
銀行獲得貨幣,退給居民10金錢,數(shù)據(jù)如下:
居民退還貨幣給銀行,獲得10金錢,數(shù)據(jù)如下:
7.2.4網(wǎng)絡(luò)擴展
(1)進行合理性擴展,內(nèi)容如下:
·用戶購買能源時必須確保能源公司仍有此能源;
·用戶購買貨幣時必須確保銀行仍有此貨幣;
·銀行在受理退幣時必須確保該用戶仍有此貨幣;
·在購買貨幣和退還貨幣返現(xiàn)交易中檢查金額是否合法。
(2)進行安全性擴展,內(nèi)容如下:
·用戶只能使用自己的貨幣。
(3)模型擴展,內(nèi)容如下:
·添加資產(chǎn)——新幣種;
·添加參與者——能源回收者,從居民回收能源;
·添加事件——銀行發(fā)行貨幣。
(4)進行功能擴展,內(nèi)容如下:
·能源公司也可以用貨幣從銀行兌換金錢;
·能源可能會過期,需要添加一個時間戳;
·不同的幣種兌換不同的能源數(shù)。
(5)進行其他網(wǎng)絡(luò)擴展。
實際上,可以將貨幣和能源進行通用處理,每次居民購買銀行發(fā)行的貨幣,銀行就從貨幣數(shù)組中彈出最后一個貨幣給居民。同理,居民用貨幣購買能源時,無需指定具體的貨幣id,取出最后一個貨幣即可。這樣不僅可以減少參數(shù)的傳遞,還提供了一種判斷能否交易的簡便方法——數(shù)組是否為空。
此外,還可以把price(價格)屬性從交易移至貨幣,這樣每次發(fā)起交易時,price是一個固定的值,而無需刻意傳參。當(dāng)銀行想要貨幣貶值時,可以使用updateAll函數(shù)對所有貨幣的價值進行更新,調(diào)整幣價將變得相當(dāng)簡單靈活。
7.3產(chǎn)品拍賣網(wǎng)絡(luò)案例分析7.3.1網(wǎng)絡(luò)定義根據(jù)需求對網(wǎng)絡(luò)進行建模,該業(yè)務(wù)網(wǎng)絡(luò)涉及如下內(nèi)容:拍賣品,出價者,加價,落錘(拍賣結(jié)束)。
(1)資產(chǎn)包含內(nèi)容:拍賣品。
(2)參與者。在產(chǎn)品拍賣網(wǎng)絡(luò)中,要模擬對產(chǎn)品的競價拍賣的流程,需要的參與者是:出價者。
(3)交易包含內(nèi)容:出價者加價,落錘(拍賣結(jié)束)。
(4)事件包含內(nèi)容:拍賣品拍賣結(jié)束時進行通知。確認網(wǎng)絡(luò)中的模型后,即可編寫代碼實現(xiàn)模型和交易。
7.3.2代碼實現(xiàn)
首先用Yeoman生成工程目錄結(jié)構(gòu),并新建lib文件夾和logic.js。
1.CTO建模
1)利用枚舉設(shè)置狀態(tài)
設(shè)置拍賣品狀態(tài),代碼如下:
2)設(shè)置相關(guān)資產(chǎn)
使用數(shù)組來記錄拍賣品的價格增長,結(jié)構(gòu)如下:
3)設(shè)置相關(guān)參與者
出價者結(jié)構(gòu)如下:
4)編寫交易代碼
出價者加價,代碼如下:
5)編寫事件代碼
拍賣品拍賣結(jié)束,使用message屬性來傳遞事件通知,代碼如下:
2.編寫業(yè)務(wù)邏輯
產(chǎn)品拍賣網(wǎng)絡(luò)的業(yè)務(wù)邏輯代碼寫在lib目錄下的logic.js文件中。
(1)常量定義,代碼如下:
(2)出價者加價,代碼如下:
首次叫價時,procedure數(shù)組為空。因此只要首次叫價價格大于起始價格,即為叫價成功,之后的叫價必須大于當(dāng)前最高出價。
代碼對應(yīng)的業(yè)務(wù)邏輯可被描述為:獲取拍賣者與拍賣品的狀態(tài)信息,檢查拍賣品狀態(tài)是否滿足要求→判斷拍賣者的金額是否足夠→根據(jù)拍賣進展判斷拍賣者叫價是否有效→若叫價有效則轉(zhuǎn)移拍賣品的暫時所有權(quán)至相應(yīng)拍賣者并更新叫價記錄數(shù)組→與注冊器交互,更新相關(guān)資源的狀態(tài)。
(3)拍賣結(jié)束,代碼如下:
7.3.3情景模擬
1.產(chǎn)品拍賣成功
一場大型拍賣會正在進行,很多企業(yè)家們都在爭搶一件絕世珍寶。拍賣規(guī)則很簡單,價高者得。
1)創(chuàng)建叫價者
創(chuàng)建三位叫價者,具有的資產(chǎn)分別為1000、2000、3000,代碼如下:
2)創(chuàng)建拍賣品
拍賣品初始狀態(tài)為“拍賣中”,代碼如下:
3)競拍叫價
執(zhí)行一次叫價交易,第一位叫價者叫價,代碼如下:
拍賣品記錄了最新叫價,且得主更換,代碼如下:
再執(zhí)行一次叫價交易,由第二位叫價者進行叫價,代碼如下:
拍賣品再次記錄了最新叫價,且得主更換,代碼如下:
再執(zhí)行一次叫價交易,由第三位叫價者叫價,代碼如下:
再次記錄叫價并改變拍賣品得主,代碼如下:
執(zhí)行叫價交易,第一位叫價者再次叫價,代碼如下:
金錢不足以叫價,錯誤提示如圖7-4所示。圖7-4叫價失敗錯誤提示
4)拍賣結(jié)束,一錘定音
執(zhí)行拍賣結(jié)束(落錘)交易,代碼如下:
產(chǎn)品拍賣成功,狀態(tài)更改,代碼如下:
拍賣品得主扣除金錢,獲得拍賣品,代碼如下:
查看交易歷史記錄,拍賣成功時,將收到事件通知,如圖7-5所示。圖7-5在歷史記錄中查看事件通知
2.產(chǎn)品拍賣失敗
接下來,開始拍賣另一件寶貝,不過好像大家都對這件拍賣品不感興趣,最終也無人叫價。
(1)創(chuàng)建拍賣品,數(shù)據(jù)如下:
(2)拍賣結(jié)束,執(zhí)行落錘操作。
執(zhí)行拍賣結(jié)束(落錘)交易,代碼如下:
無人購買,交易失敗,如圖7-6所示。圖7-6錯誤提示
7.3.4網(wǎng)絡(luò)擴展
(1)進行合理性擴展,包含內(nèi)容如下:
·拍賣成功時,當(dāng)前拍賣品必須處于拍賣中;
·拍賣成功時,要再次校驗得主的金錢是否足夠。
(2)進行安全性擴展,包含內(nèi)容如下:
·禁止任何人隨意修改拍賣品屬性,只能公開叫價。
(3)進行模型擴展,包含內(nèi)容如下:
·添加參與者——拍賣家,負責(zé)產(chǎn)品的拍賣;
·添加參與者——拍賣品原主人;
·添加事件——有新的叫價。
(4)進行功能擴展,包含內(nèi)容如下:
·自定義拍賣規(guī)則,未必價高者得;
·拍賣品原主人可在首次叫價前修改起價;
·產(chǎn)品拍賣成功,拍賣家收到一定酬勞。
本
章
小
結(jié)
通過本章的學(xué)習(xí),讀者應(yīng)對HyperledgerComposer的一個高級功能——自定義查詢——有了基本的了解。并且通過三方交易類型和拍賣業(yè)務(wù)網(wǎng)絡(luò)的實戰(zhàn),熟悉了框架,開拓了思路。至此,HyperledgerComposer項目實戰(zhàn)系列就結(jié)束了。HyperledgerComposer的主要功能均已探索,還有一些功能,如資源注解、訪問控制、動態(tài)綁卡、查看歷史記錄、OAuth等,在此不再贅述。讀者可自行閱讀官方文檔進行學(xué)習(xí)。
本系列教程僅僅演示了超級賬本項目的冰山一角。實際上,通過Fabric區(qū)塊鏈網(wǎng)絡(luò)和HyperledgerComposer框架,幾乎可以滿足任何業(yè)務(wù)需求,開發(fā)任何不同場景的應(yīng)用。Hyperledger項目還提供了Explorer作為區(qū)塊鏈的監(jiān)控界面。想要成為超級賬本的開發(fā)高手,就要不斷地積累項目經(jīng)驗,探索更多的技術(shù),激發(fā)區(qū)塊鏈技術(shù)的無限可能性。第8章HyperledgerComposer
客戶端接入8.1項目簡介8.2傳統(tǒng)項目的開發(fā)方式8.3區(qū)塊鏈項目的開發(fā)方式8.4多語言RestServer客戶端接入本章小結(jié)
8.1項
目
簡
介
區(qū)塊鏈?zhǔn)且粋€分布式數(shù)據(jù)庫,基于其加密、防篡改、可溯源等特點,現(xiàn)在很多項目都會利用區(qū)塊鏈來存儲重要、敏感的數(shù)據(jù)。和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫、NoSQL數(shù)據(jù)庫不同,對基于HyperledgerFabric的區(qū)塊鏈進行操作不需要使用SDK。HyperledgerComposer提供了RestServer和一套RestfulApi,只要使用Http請求遠程調(diào)用即可使用。
現(xiàn)在的主流項目開發(fā)語言,如Java、Php、Golang、Node.js、Python等,都支持Http客戶端調(diào)用。因此HyperledgerComposer的客戶端接入十分簡單,甚至讓開發(fā)者完全感受不到區(qū)塊鏈的存在,可以專注于業(yè)務(wù)。
本章首先從傳統(tǒng)項目開發(fā)方式講起,逐步揭秘傳統(tǒng)項目和區(qū)塊鏈項目開發(fā)過程的異同;再演示
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 染色師成果轉(zhuǎn)化模擬考核試卷含答案
- 道岔鉗工安全操作競賽考核試卷含答案
- 腳輪制作工安全風(fēng)險水平考核試卷含答案
- 醬鹵肉制品加工工操作管理評優(yōu)考核試卷含答案
- 纖維調(diào)施膠干燥工安全培訓(xùn)模擬考核試卷含答案
- 2025年太陽能組件生產(chǎn)裝備項目合作計劃書
- 2025年鍍鉻板(卷)合作協(xié)議書
- 中國垃圾填埋場治理行業(yè)市場前景預(yù)測及投資價值評估分析報告
- 信息安全與加密教學(xué)課件
- 2025年青海省西寧市中考生物真題卷含答案解析
- 大數(shù)據(jù)安全技術(shù)與管理
- 2026年中小學(xué)校長校園安全管理培訓(xùn)考試題及答案
- 2025年山東建筑大學(xué)思想道德修養(yǎng)與法律基礎(chǔ)期末考試模擬題必考題
- 江西省贛州地區(qū)2023-2024學(xué)年七年級上學(xué)期期末英語試(含答案)
- 2025年香港滬江維多利亞筆試及答案
- 述職報告中醫(yī)
- 患者身份識別管理標(biāo)準(zhǔn)
- 松下Feeder維護保養(yǎng)教材
- 汽車融資貸款合同范本
- 碼頭租賃意向協(xié)議書
- 初一語文2025年上學(xué)期現(xiàn)代文閱讀真題(附答案)
評論
0/150
提交評論