脚手架 Go Chaincode 项目

Blockchain App Builder 从您的规范文件中获取输入,并生成一个功能齐全的脚手架链代码项目。该项目包含自动生成的类和函数、CRUD 方法、SDK 方法、参数自动验证、编集/非编集和透明持久性功能 (ORM)。

如果链代码项目使用 Go 语言,则支架式项目包含三个主要文件:
  • main.go
  • <chaincodeName>.model.go
  • <chaincodeName>.controller.go
已安装并打包所有必需的磁带库。

model 子目录中的 <chaincodeName>.model.go 文件包含多个资产定义,controller 子目录中的 <chaincodeName>.controller.go 文件包含资产的行为和 CRUD 方法。model.gocontroller.go 中的各种 Go 结构标记和软件包支持自动验证参数、编集/解编集参数、透明持久性功能 (ORM) 和调用富查询等功能。

脚手架项目可以在 $GOPATH/src/example.com/<chaincodeName> 中找到

型号

资产类型财产

缺省情况下,每个结构将具有一个名为 AssetType 的附加属性。此属性可用于仅提取此类资产。在创建和更新资产期间,将忽略对此属性所做的任何更改。默认情况下,属性值为 <modelName>
type Supplier struct {
AssetType string 'json:"AssetType" default:"TestGoProject.Supplier"'

SupplierId            string      'json:"SupplierId" validate:"string,mandatory" id:"true'
RawMaterialAvailable  int         'json:"RawMaterialAvailable" validate:"int,min=0"'
License               string      'json:"License" validate:"string,min=10"'
ExpiryDate            date.Date   'json:"ExpiryDate" validate:"date,before=2020-06-26"'
Active                bool	  'json:"Active" validate:"bool" default:"true"'
Metadata              interface{} 'json:"Metadata,omitempty"'
}

验证器

ID
id:"true"
此验证程序标识唯一定义底层资产的属性。资产由此键中的值保存。此验证器在脚手架上安装了新的 Go 项目时自动应用。
在下面的屏幕截图中,"SupplierId" 是供应商资产的关键字,并且具有 SupplierId 属性的标记属性 id:"true"
type Supplier struct {
    Supplierld              string        'json:"Supplierld" validate:"string,mandatory" id:"true"' 
    RawMaterialAvailable    int           'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                 string        'json:"License" validate:"string,min=10"'
    ExpiryDate              date.Date     'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                  bool          'json:"Active" validate:"bool" default :"true"'
    Metadata                interface{}   'json:"Metadata,omitempty"'   
}
派生
derived:"strategy,algorithm,format"
此装饰器用于定义从其他属性派生的属性。此装饰器具有两个必需参数:
  • strategy:接受 concathash 的值。如果选择了 hash,则需要附加参数 algorithm。默认算法为 sha256;还支持 md5
  • format:接受策略要使用的规范字符串和值的数组。
type Supplier struct{
   AssetType string 'json:"AssetType" final:"chaincode1.Supplier"'
   SupplierId   string  'json:"SupplierId" validate:"string" id:"true" mandatory:"true" derived:"strategy=hash,algorith=sha256,format=IND%1%2,License,Name"'
   Name         string  'json:"Name" validate:"string,min=2,max=4"'
   License      string  'json:"License" validate:"string,min=2,max=4"'
}
必需
validate:"mandatory"
这会将以下属性标记为必需属性,在保存到分类账时无法跳过。如果跳过,则会引发错误。在下面的示例中,"SupplierId" 具有 validate:"mandatory" 标记。
Type Supplier struct {
    Supplierld              string      'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable    int         'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                 string      'json:"License" validate:"string,min=10"'
    ExpiryDate              date.Date   'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                  bool        'json:"Active" validate:"bool" default :"true"'
    Metadata                interface{} 'json:"Metadata,omitempty"'
}
默认值为
default:"<param>"
这表明以下属性可以具有默认值。保存到分类账时,将跳过属性时,使用默认标记中的默认值。在下面的示例属性中,Active 的默认值为 true,作为标记 default:"true" 提供
Type Supplier struct {
    Supplierld            string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License               string       'json:"License" validate:"string,min=10"'
    ExpiryDate            date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                bool         'json:"Active" validate:"bool" default :"true"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
验证类型
通过定义验证标记来验证属性的基本执行类型。以下是基于类型的验证标记:
  • 字符串:validate: "string"
  • 日期:validate: "date"
  • 编号:validate: "int"
  • 布尔值:validate: "bool"
最小验证器
validate:"min=<param>"
使用 min 验证器,可以为类型为 number 和 string 的属性设置最小值。
对于 int 类型:在示例中,RawMaterialAvailable 属性的最小值为 0,如果将小于 0 的值应用于 RawMaterialAvailable,将返回错误。
对于类型字符串:对于字符串类型,最小验证器将使用提供的值检查字符串的长度。因此,在以下示例中,License 属性的长度必须至少为 10 个字符。
示例:
Type Supplier struct {
    Supplierld             string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable   int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                string       'json:"License" validate:"string,min=10"'
    ExpiryDate             date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                 bool         'json:"Active" validate:"bool" default :"true"'
    Metadata               interface{}  'json:"Metadata,omitempty"'
}
最大验证器
validate:"max=<param>"
使用最大验证器,可以为类型为数字和字符串的属性设置最大值。
对于 int 类型:与 min 验证器一样,对于 int 类型,如果为 structfield 提供的值大于验证器中提供的值,则将返回错误。
对于类型字符串:与 min 验证器一样,max 验证器还将检查具有给定值的字符串的长度。在示例中,Domain 属性的最大值为 50,因此,如果 Domain 属性的字符串长度超过 50 个字符,则会返回错误消息。
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}
日期验证器
验证程序之前:
validate:"before=<param>"
之前的验证器验证 date 类型的属性的值小于参数中指定的值。
在此示例中,ExpiryDate 属性应在 "2020-06-26" 之前,如果不是,它将返回错误。
Type Supplier struct {
    Supplierld            string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License               string       'json:"License" validate:"string,min=10"'
    ExpiryDate            date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                bool         'json:"Active" validate:"bool" default :"true"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
验证器之后:
validate:"after=<param>"
之前的验证器验证 date 类型的属性的值是否大于参数中指定的值。
在此示例中,CompletionDate 属性应位于 "2020-06-26" 之后,如果不是,它将返回错误。
Type Supplier struct {
    Manufacturerld        string       'json:"Manufacturerld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,max=8"'
    ProductsAvailable     int          'json:"ProductsAvailable" validate:"int"'
    CompletionDate        date.Date    'json:"CompletionDate" validate:"date,after=2020-06-26"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
URL 验证器
validate:"url"
URL 验证器将验证 URL 字符串的属性。
在此示例中,Domain 属性必须是有效的 URL。
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"string,url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}
正则表达式验证器
validate:"regexp=<param>"
正则表达式验证器将验证输入正则表达式的属性。
在此示例中,PhoneNumber 属性将根据正则表达式验证移动电话号码。
type Customer struct {
Customerld      string       'json:"Customerld" validate:"string,mandatory" id:"true"'
Name            string       'json:"Name" validate:"string,mandatory"'
ProductsBought  int          'json:"ProductsBought" validate:"int"'
OfferApplied    int          'json:"OfferApplied" validate :"int,nax=0"'
PhoneNumber     string       'json:"PhoneNumber" validate:"string,regexp=A\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$"'
Received        bool         'json:"Received" validate:"bool"'
Metadata        interface{}  'json:"Metadata,omitempty"'
}
多个验证器
一个属性可以应用多个验证器。
在此示例中,Domain 属性对字符串、URL 以及最小和最大字符串长度进行了验证。
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"string,url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}

ORM

透明持久性功能或简化 ORM 在上下文 (Ctx) 对象的 Model 类中捕获。如果模型调用了以下任何 SDK 方法,请使用 t.Ctx.Model 访问这些方法。

实施 ORM 的 SDK 方法包括以下方法:
  • Save —这将调用超级账本架构 PutState 方法
  • Get —这将调用超级账本架构 GetState 方法
  • Update —这将调用超级账本架构 PutState 方法
  • Delete —这将调用超级账本架构 DeleteState 方法
  • History —这将调用超级账本架构 GetHistoryForKey 方法
  • GetByRange —这将调用超级账本架构 GetStateByRange 方法
  • GetByRangeWithPagination —这将调用超级账本架构 GetStateByRangeWithPagination 方法

SDK 方法

Go 链代码实现透明持久性能力 (ORM) 与模型包。

注意:

从版本 21.2.3 开始,访问 ORM 方法的方式已更改。运行 ochain --version 命令以确定区块链应用程序构建器的版本。

在以前的发行版中,ORM 方法作为静态方法在模型包中公开。这些方法现在在保存事务处理存根的模型接收器上定义。要调用这些方法,请使用控制器中事务处理上下文持有的模型接收器。可以将这些方法称为 t.Ctx.Model.<method_name> 而不是 model.<method_name>

以下示例显示了早期发行版中的 SaveGet 方法调用:

func (t *Controller) CreateSupplier(asset Supplier) (interface{}, error) {
  return model.Save(&asset)
}

func (t *Controller) GetSupplierById(id string) (Supplier, error) {
  var asset Supplier
  _, err := model.Get(id, &asset)
  return asset, err
}

以下示例显示了版本 21.2.3 及更高版本的 SaveGet 方法调用:

func (t *Controller) CreateSupplier(asset Supplier) (interface{}, error) {
  return t.Ctx.Model.Save(&asset)
}

func (t *Controller) GetSupplierById(id string) (Supplier, error) {
  var asset Supplier
  _, err := t.Ctx.Model.Get(id, &asset)
  return asset, err
}

升级到版本 21.2.3 后,请在使用早期版本的 Blockchain App Builder 创建的所有链代码项目中进行此更改。如果使用 sync 命令同步规范文件与源代码之间的更改,这些更改将自动带到控制器中,以便于使用。您仍需要手动解决任何冲突。

以下 ORM 方法通过模型包公开:

Get
根据给定 ID 查询存储资产的分类账。
func Get(Id string, result ...interface{}) (interface{}, error)
参数:
  • Id - 分类账中所需的资产的 ID。
  • result (interface{}) - 这是通过引用传递的特定类型的空资产对象。此对象将包含此方法的结果。仅当需要特定于类型的结果时才使用。
  • asset (interface) - 通过引用传递的空资产对象。此对象将包含此方法的结果。仅当需要特定于类型的结果时才使用。
返回:
  • interface {} - 接口以 map[string]interface{} 格式包含资产。在此映射上操作之前,需要断言类型为 map[string]interface{} 的已获取接口。要将此映射转换为资产对象,可以使用实用程序 API util.ConvertMaptoStruct(请参阅:实用程序包)。
  • error - 如果返回,则包含错误,或者为 nil。
Update
使用新值更新分类账中提供的资产。
func Update(args ...interface{}) (interface{}, error)
参数:
  • obj (interface) - 需要在分类账中更新的对象通过引用传递到此 API,其中包含新值。输入资产将根据模型规范中提到的结构标记进行验证和验证,然后存储到分类账中。
返回:
  • interface{} - 保存的资产将作为接口返回。
  • error - 如果返回,则包含错误,或者为 nil。
Save
验证所有结构标记后,将资产保存到分类账。
func Save(args ...interface{}) (interface{}, error)
参数:
  • obj/args[0] (interface{}) - 需要存储在分类账中的对象在此实用程序方法中通过引用传递。
  • metadata/args[1] (interface{}) - 此参数是可选的。如果需要在运行时将任何元数据与资产一起存储到分类账中,则系统会提供该帮助。如果不存在此类要求,则可以跳过此参数。
返回:
  • interface {} - 资产将作为接口返回。
  • error - 如果返回,则包含错误,或者为 nil。
Delete
从分类账中删除资产。
func Delete(Id string) (interface{}, error)
参数:
  • id (string) - 需要从分类账中删除的资产的 ID。
返回:
  • interface {} - 包含以 map[string]interface{} 格式删除的资产。
GetByRange
按 ID 范围返回资产列表。
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
参数:
  • startkey (string) - 所需对象范围的起始 ID。
  • endkey (string) - 所需对象范围的结束。
  • asset interface -(可选)空的资产数组,通过引用传递。此数组将包含此方法的结果。在需要特定于类型的结果时使用。
返回:
  • []map[string]interface{} - 此数组包含从分类账中获取的资产列表。您可以访问在此数组上迭代的对象,并将对象声明为 map[string]interface{},并使用实用程序转换为资产对象。
  • error - 如果返回,则包含错误,或者为 nil。
GetByRangeWithPagination
GetByRangeWithPagination 方法是 OchainModel 类的静态方法,由 {chaincodeName}.model.ts 的具体 Model 类继承。
这将返回介于 startIdendId 之间的资产列表,按页面大小和书签进行筛选。此方法在内部调用超级账本架构 GetStateByRangeWithPagination 方法。
如果未提供 modelName 参数,则方法返回 Promise<Object [ ] >。如果提供了 modelName 参数,则该方法将处理强制转换为调用者 Model 类型。在以下示例中,结果数组的类型为 Supplier。如果从分类账返回的资产不是 Model 类型,则该资产将不包括在列表中。此检查由 Model 类中的只读 assetType 属性完成。
要返回 startIdendId 范围之间的所有资产(按页大小和书签进行过滤),请使用通用控制器方法 getAssetsByRange
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error) 
参数:
  • startkey : string- 范围的起始键。包括在范围内。
  • endkey : string- 范围的结束键。从范围中排除。
  • pageSize : number —查询的页面大小。
  • Bookmark : string —查询的书签。输出从此书签开始。
  • asset interface-(可选)通过引用传递的空资产数组。此数组将包含此方法的结果。使用此参数可获取特定于类型的结果。
返回:
  • []map[string]interface{} —包含从分类账检索的资产列表的数组。您可以通过迭代此数组并将对象声明为 map[string]interface{} 并使用实用程序转换为资产对象来访问对象。
  • error- 如果返回了错误,则包含错误,否则为 nil。
GetHistoryById
返回具有给定 ID 的资产的历史记录。
func GetHistoryByID(Id string) ([]interface{}, error)
参数:
  • Id (string) - 需要历史记录的资产的 ID。
返回:
  • []interface{} - 此分片包含从分类帐中以 map[string]interface{} 分片形式获取的资产的历史记录。您可以通过迭代此分片并将对象声明为 map[string]interface{} 并使用实用程序转换为资产对象来访问每个历史记录元素。
  • error - 如果观察到,则包含错误。
Query
查询方法将通过分类账运行 SQL/Couch DB 查询。此方法仅适用于 Oracle Blockchain Platform 上的远程部署。这是对分类账执行 SQL 查询的一般方法。
func Query(queryString string) ([]interface{}, error)
参数:
  • queryString (string) - 输入查询字符串。
返回:
  • []interface{} - 这将包含查询的输出。结果采用接口分片的形式。您需要对时段进行迭代,并通过将元素转换为正确的类型来使用这些元素。
  • error - 如果观察到,则包含错误。
QueryWithPagination
该查询方法将通过分类账运行 SQL/Couch DB 查询,并按页面大小和书签进行筛选。此方法仅适用于 Oracle Blockchain Platform 上的远程部署。这是对分类账执行 SQL 查询的一般方法。
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
参数:
  • queryString (string) - 丰富的 SQL/Couch DB 查询。
  • pageSize : number - 查询的页大小。
  • bookmark : string - 查询的书签。输出从此书签开始。
返回:
  • []interface{} - 这将包含查询的输出。结果采用接口分片的形式。您需要对时段进行迭代,并通过将元素转换为正确的类型来使用这些元素。
  • error - 如果观察到,则包含错误。
InvokeCrossChaincode
可以在链代码中使用此方法来调用另一个链代码中的函数。两个链代码必须安装在同一对等点上。
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
参数:
  • chaincodeName- 要调用的链代码的名称。
  • methodName - 要在链代码中调用的方法的名称。
  • arg - 调用方法的参数。
  • channelName - 要调用的链代码所在的通道。
返回:
  • interface{} - 返回包含三个键的 map[string]interface{} 对象:
    • isValid - true(如果调用有效)。
    • payload - 跨链代码调用返回的输出,作为 JSON 对象。
    • message - 跨链代码调用以 UTF-8 格式返回的消息。
返回值示例:
{
      "isValid": true,
      "message": "Successfully invoked method [CreateAccount] on sub-chaincode [erc721_go_453]",
      "payload": {
                  "AccountId": "oaccount~6b83b8ab931f99442897dd04cd7a2a55f808686f49052a40334afe3753fda4c4",
                  "AssetType": "oaccount",
                  "BapAccountVersion": 0,
                  "NoOfNfts": 0,
                  "OrgId": "appdev",
                  "TokenType": "nonfungible",
                  "UserId": "user2"
      }
}
InvokeChaincode
可以在链代码中使用此方法来调用另一个链代码中的函数。两个链代码必须安装在同一对等点上。
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
参数:
  • chaincodeName- 要调用的链代码的名称。
  • methodName - 要在链代码中调用的方法的名称。
  • arg - 调用方法的参数。
  • channelName - 要调用的链代码所在的通道。
返回:
  • interface{} - 返回包含三个键的 map[string]interface{} 对象:
    • isValid - true(如果调用有效)。
    • payload- 跨链代码调用返回的输出,采用 UTF-8 格式。
    • message - 跨链代码调用以 UTF-8 格式返回的消息。
返回值示例:
{
    "isValid": true,
    "message": "Successfully invoked method [CreateAccount] on sub-chaincode [erc721_go_453]",
    "payload": "{\"AssetType\":\"oaccount\",\"AccountId\":\"oaccount~c6bd7f8dcc339bf7144ea2e1cf953f8c1df2f28482b87ad7895ac29e7613a58f\",\"UserId\":\"user1\",\"OrgId\":\"appdev\",\"TokenType\":\"nonfungible\",\"NoOfNfts\":0,\"BapAccountVersion\":0}"
} 

组合关键字方法

GenerateCompositeKey
此方法基于 indexName 和参数中给定的属性生成并返回组合键。
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
参数:
  • indexName (string) - 组合键的对象类型。
  • attrbutes ([]string) - 必须基于其形成组合键的资产属性。
返回:
  • string - 这包含组合键结果。
  • error - 如果观察到,则包含错误。
GetByCompositeKey
此方法返回与参数中给定的键和列匹配的资产。index 参数指示存根方法 SplitCompositeKey 数组中返回的键的索引。
在内部,此方法调用超级账本架构 (Hyperledger Fabric) 的 getStateByPartialCompositeKeysplitCompositeKeygetState
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
参数:
  • key (string) - 创建组合键时提供的对象类型。
  • column ([]string) - 这是必须使用组合键查询分类帐的属性切片。
  • index(int) - 属性的索引。
返回:
  • Interface{} - 包含由此方法生成的资产列表。
  • error - 包含任何错误(如果存在)。

存根方法

GetNetworkStub
此方法将返回超级账本架构 chaincodeStub
您可以通过调用 GetNetworkStub 方法来访问 shim stub。这将帮助您编写自己的实施,直接使用资产。
func GetNetworkStub() shim.ChaincodeStubInterface
参数:
返回:
  • shim.ChaincodeStubInterface- 这是超级账本架构链代码存根。

其他方法

  • GetTransactionId()
  • GetTransactionTimestamp()
  • GetChannelID()
  • GetCreator()
  • GetSignedProposal()
  • GetArgs()
  • GetStringArgs()
  • GetCreatorMspId()
  • GetId
GetTransactionId
返回当前链代码调用请求的事务处理 ID。事务处理 ID 在渠道范围内唯一标识事务处理。
func GetTransactionId() string
参数:
返回:
  • string - 这包含必需的事务处理 ID。
GetTransactionTimestamp
返回创建事务处理的时间戳。这取自事务 ChannelHeader,因此它将指示客户端的时间戳,并在所有背书者中具有相同的值。
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
参数:
返回:
  • timestamp.Timestamp - 包含所需的时间戳。
  • error - 包含任何错误(如果存在)。
GetChannelID
返回要处理的链代码的建议的渠道 ID。
func GetChannelID() string
参数:
返回:
  • string - 包含所需的通道 ID 作为字符串。
GetCreator
返回链代码调用的提交者的身份对象
func GetCreator() ([]byte, error)
参数:
返回:
  • []byte - 包含序列化所需的身份对象。
  • error - 包含任何错误(如果存在)。
GetSignedProposal
返回已签名事务处理建议的完全解码的对象。
func GetSignedProposal() (*peer.SignedProposal, error)
参数:
返回:
  • *peer.SignedProposal - 包含必需的签名建议对象。
  • error - 包含任何错误(如果存在)。
GetArgs
从链代码调用请求中以字符串数组形式返回参数。
func GetArgs() [][]byte
参数:
返回:
  • [][]byte - 包含传递的参数。
GetStringArgs
返回用于 chaincode Init 和 Invoke 的参数(作为字符串数组)。
func GetStringArgs() []string
参数:
返回:
  • []string - 将所需的参数作为字符串数组包含。
GetCreatorMspId
返回调用身份的 MSP ID。
func GetCreatorMspId() string
参数:
返回:
  • string - 返回调用身份的 MSP ID。
GetId
当资产的派生密钥为 Id 时,可以使用此方法获取派生 ID。如果派生密钥包含 %t (timestamp),则此方法将返回错误。
参数:
  • object - 对象应包含派生密钥所依赖的所有属性。
返回:
  • 以字符串形式返回派生关键字。
示例:
func (t *Controller) CustomGetterForSupplier(License string, Name string)(interface{}, error){
   var asset Supplier
   asset.License = License
   asset.Name = Name
   id,err := t.Ctx.Model.GetId(&asset)

   if err !=nil {
      return nil, fmt.Errorf("error in getting ID %v", err.Error())
   }
   return t.GetSupplierById(id)
}

实用程序程序包

实用程序软件包中的以下方法可能有用:

Util.CreateModel
对提供的 JSON 字符串进行语法分析并创建提供类型的资产对象。
func CreateModel(obj interface{}, inputString string) error
参数:
  • inputString (string) - 要从中创建对象的输入 JSON 字符串。
  • obj (interface{}) - 要从 JSON 字符串创建的对象的引用。此对象将存储创建的模型,该模型还根据验证器标记进行验证。
返回:
  • error - 包含在创建或验证资产时发现的任何错误。
util.ConvertMapToStruct
将提供的映射转换为提供的类型的对象。
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
参数:
  • inputMap (map[string](interface{})) - 需要转换为资产对象的映射。
  • resultStruct (interface{}) - 需要从映射生成的必需资产对象的引用。包含所需的结果资产对象。
返回:
  • error - 包含在创建或验证资产时发现的任何错误。

有关令牌 SDK 方法,请参阅使用区块链应用构建器支持令牌下的主题。

主管

Controller.go 文件为资产实施 CRUD 和定制方法。

您可以创建任意数量的类、函数或文件,但只有链代码结构上定义的方法可以从外部调用,其余的都是隐藏的。

自动生成的方法

Input Specification File 中所述,您可以指定要在规范文件中生成的 CRUD 方法。例如,如果选择生成所有方法,则结果将类似于:

//	
//Supplier
//	
func (t *ChainCode) CreateSupplier(inputString string) (interface{}, error) {
    var obj Supplier
    err := util.CreateModel(&obj, inputString)
    if err != nil {
        return nil, err   
    }
    return model.Save(&obj)
}

func (t *ChainCode) GetSupplierById(id string) (interface{}, error) {
    asset, err := model.Get(id) 
    return asset, err
}

func (t *ChainCode) UpdateSupplier(inputString string) (interface{}, error) {
    var obj Supplier
    err := util.CreateModel(&obj, inputstring)
    if err != nil {   
        return nil, err
    }
return model.Update(&obj)
}

func (t *ChainCode) DeleteSupplier(id string) (interface{}, error) { 
    return model.Delete(id)
}

func (t *ChainCode) GetSupplierHistoryById(id string) (interface{}, error) { 
    historyArray, err := model.GetHistoryByld(id) 
    return historyArray, err
}

func (t *ChainCode) GetSupplierByRange(startkey string, endKey string) (interface{}, error) { 
    assetArray, err := model.GetByRange(startkey, endKey) 
    return assetArray, err
}

定制方法

以下自定义方法是从我们的示例规范文件生成的。

executeQuery 显示了如何调用 SQL 多信息查询。基于参数的验证器由 Blockchain App Builder 根据规范文件中指定的参数类型自动添加。

您可以根据业务逻辑实施该功能。如果添加定制方法,请将其添加到控制器文件中。如果将定制方法添加到库而不是控制器文件,则在同步或链代码升级过程中更新库文件夹内容时,所做的更改将丢失。

//	
//Custom Methods
//			
/*
*	BDB sql rich queries can be executed in OBP CS/EE.
*	This method can be invoked only when connected to remote OBP CS/EE network.
*/
func (t *ChainCode) ExecuteQuery(inputQuery string) (interface{}, error) { 
    resultArray, err := model.Query(inputQuery) 
    return resultArray, err
}

func (t *ChainCode) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
    return nil, nil
}

func (t *ChainCode) GetRawMaterialFromSupplier(manufacturerId string, supplierId string, rawMaterialSupply int) (interface{} error) { 
    return nil, nil
}

Func (t *ChainCode) CreateProducts(manufacturerId string, rawMaterialConsumed int, productsCreated int) (interface{}, error) { 
    return nil, nil
}

func (t *ChainCode) SendProductsToDistribution() (interface{}, error) { 
    return nil, nil
}
对于 Go 链代码,每个定制方法应返回两个值:空接口错误。例如:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) { 
    return nil, nil
}

Init 方法

控制器中提供了一个定义为空的定制 Init 方法。如果您使用区块链应用程序构建器进行部署或升级,则会自动调用 Init 方法。如果您从 Hyperledger Fabric v1.4.7 平台上的 Oracle Blockchain Platform 控制台部署或升级,则也会自动调用 Init 方法。如果您从 Hyperledger Fabric v2.x 平台上的 Oracle Blockchain Platform 控制台部署或升级,则必须手动调用 Init 方法。您可以使用第三方工具(如 Postman)手动调用 Init 方法。

type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error) 
    { return nil, nil
}

如果要在此时初始化任何应用程序状态,可以使用此方法来执行此操作。