脚手架 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 个字符。
示例:
 outputclass="language-go"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 方法。如果从 Oracle Blockchain Platform 控制台部署或升级,则必须手动调用 Init 方法。您可以使用第三方工具(如 Postman)手动调用 Init 方法。

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

此时,可以使用此方法初始化任何应用程序状态。