Scaffolded Go Chaincode-Projekt

Blockchain App Builder übernimmt die Eingabe aus Ihrer Spezifikationsdatei und generiert ein voll funktionsfähiges gerüstetes Chaincode-Projekt. Das Projekt enthält automatisch generierte Klassen und Funktionen, CRUD-Methoden, SDK-Methoden, automatische Validierung von Argumenten, Marshalling/Unmarshalling und transparente Persistenzfähigkeit (ORM).

Wenn sich das chaincode-Projekt in der Go-Sprache befindet, enthält das gerüstete Projekt drei Hauptdateien:
  • main.go
  • <chaincodeName>.model.go
  • <chaincodeName>.controller.go
Alle erforderlichen Librarys sind installiert und in einem Package enthalten.

Die Datei <chaincodeName>.model.go im Unterverzeichnis model enthält mehrere Assetdefinitionen, und die Datei <chaincodeName>.controller.go im Unterverzeichnis controller enthält das Verhalten des Assets und die CRUD-Methoden. Die verschiedenen Go-Struktur-Tags und -Packages in model.go und controller.go unterstützen Features wie die automatische Validierung von Argumenten, Marshalling/Unmarshalling von Argumenten, transparente Persistenzfähigkeit (ORM) und Aufruf von Rich-Abfragen.

Das Gerüstprojekt finden Sie unter $GOPATH/src/example.com/<chaincodeName>

Modell

Eigenschaft Vermögensgegenstandstyp

Standardmäßig verfügt jede Struktur über eine zusätzliche Eigenschaft namens AssetType. Diese Eigenschaft kann nützlich sein, um nur Assets dieses Typs abzurufen. Alle Änderungen an dieser Eigenschaft werden beim Erstellen und Aktualisieren des Assets ignoriert. Der Eigenschaftswert lautet standardmäßig <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"'
}

Validatoren

ID
id:"true"
Dieser Validator identifiziert die Eigenschaft, die den Basiswert eindeutig definiert. Das Asset wird durch den Wert in diesem Schlüssel gespeichert. Dieser Validator gilt automatisch, wenn ein neues Go-Projekt gerüstet wird.
Im folgenden Screenshot ist "SupplierId" der Schlüssel für das Lieferantenasset und enthält die Tag-Eigenschaft id:"true" für die Eigenschaft SupplierId.
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"'   
}
Abgeleitet
derived:"strategy,algorithm,format"
Dieser Dekorator wird zur Definition des aus anderen Eigenschaften abgeleiteten Attributs verwendet. Dieser Dekorateur hat zwei obligatorische Parameter:
  • strategy: Übernimmt Werte von concat oder hash. Erfordert einen zusätzlichen Parameter algorithm, wenn hash ausgewählt ist. Der Standardalgorithmus ist sha256; md5 wird ebenfalls unterstützt.
  • format: Übernimmt ein Array von Spezifikationszeichenfolgen und -werten, die von der Strategie verwendet werden sollen.
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"'
}
Obligatorisch
validate:"mandatory"
Dadurch wird die folgende Eigenschaft als erforderlich markiert und kann beim Speichern im Buch nicht übersprungen werden. Wenn sie übersprungen wird, wird ein Fehler ausgelöst. Im folgenden Beispiel hat "SupplierId" das Tag 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"'
}
Standard
default:"<param>"
Dadurch wird angegeben, dass die folgende Eigenschaft einen Standardwert haben kann. Der Standardwert im Standardtag wird verwendet, wenn die Eigenschaft beim Speichern im Buch übersprungen wird. In der folgenden Beispieleigenschaft hat Active den Standardwert true, der als Tag default:"true" angegeben wird
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"'
}
Typen validieren
Basis-Go-Typen werden für eine Eigenschaft validiert, indem ein Validierungstag definiert wird. Die folgenden Validierungstags basieren auf Typen:
  • Zeichenfolge: validate: "string"
  • Datum: validate: "date"
  • Zahl: validate: "int"
  • Boolescher Wert: validate: "bool"
Min.-Validator
validate:"min=<param>"
Mit dem Min-Validator kann ein Mindestwert für eine Eigenschaft vom Typ Zahl und Zeichenfolge festgelegt werden.
Für int-Typ: Im Beispiel hat die Eigenschaft RawMaterialAvailable den Mindestwert 0, und wenn ein Wert kleiner als 0 auf RawMaterialAvailable angewendet wird, wird ein Fehler zurückgegeben.
Für Typzeichenfolge: Für den Stringtyp überprüft der minimale Validator die Länge der Zeichenfolge mit dem angegebenen Wert. Daher muss die Eigenschaft License im folgenden Beispiel mindestens 10 Zeichen lang sein.
Beispiel:
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"'
}
Max. Validator
validate:"max=<param>"
Mit dem Max-Validator kann der Höchstwert für eine Eigenschaft vom Typ Zahl und Zeichenfolge festgelegt werden.
Für int-Typ: Wenn ein für structfield angegebener Wert für int-Typ wie für den min-Validator größer als der im Validator angegebene Wert ist, wird ein Fehler zurückgegeben.
Für Typzeichenfolge: Wie der Min-Validator prüft auch der Max-Validator die Länge der Zeichenfolge mit dem angegebenen Wert. Im Beispiel hat die Eigenschaft Domain einen Höchstwert von 50. Wenn die Eigenschaft Domain also eine Zeichenfolgenlänge von mehr als 50 Zeichen aufweist, wird eine Fehlermeldung zurückgegeben.
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"'
}
Datumsvalidatoren
Vor dem Validator:
validate:"before=<param>"
Der Before Validator validiert eine Eigenschaft des Typs date, sodass ein Wert kleiner als der im Parameter angegebene Wert ist.
In diesem Beispiel muss die Eigenschaft ExpiryDate vor "2020-06-26" liegen. Andernfalls wird ein Fehler zurückgegeben.
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"'
}
Nach dem Validator:
validate:"after=<param>"
Der Before Validator validiert eine Eigenschaft des Typs date, sodass ein Wert größer als der im Parameter angegebene Wert ist.
In diesem Beispiel muss die Eigenschaft CompletionDate nach "2020-06-26" liegen. Andernfalls wird ein Fehler zurückgegeben.
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-Validator
validate:"url"
Der URL-Validator validiert eine Eigenschaft für URL-Zeichenfolgen.
In diesem Beispiel muss die Eigenschaft Domain eine gültige URL sein.
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"'
}
Regexp-Validator
validate:"regexp=<param>"
Der Regexp-Validator validiert die Eigenschaft für den eingegebenen regulären Ausdruck.
In diesem Beispiel wird die Eigenschaft PhoneNumber für eine Mobiltelefonnummer gemäß dem regulären Ausdruck validiert.
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"'
}
Mehrere Validatoren
Es können mehrere Validatoren auf eine Eigenschaft angewendet werden.
In diesem Beispiel hat die Eigenschaft Domain eine Validierung für eine Zeichenfolge, eine URL sowie eine Mindest- und Höchstlänge der Zeichenfolge.
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

Transparente Persistenzfähigkeit oder vereinfachtes ORM wird in der Klasse Model des Context-(Ctx-)Objekts erfasst. Wenn Ihr Modell eine der folgenden SDK-Methoden aufruft, greifen Sie mit t.Ctx.Model darauf zu.

SDK-Methoden, die ORM implementieren, sind die folgenden Methoden:
  • Save: Dadurch wird die Hyperledger Fabric-Methode PutState aufgerufen.
  • Get: Dadurch wird die Hyperledger Fabric-Methode GetState aufgerufen.
  • Update: Dadurch wird die Hyperledger Fabric-Methode PutState aufgerufen.
  • Delete: Dadurch wird die Hyperledger Fabric-Methode DeleteState aufgerufen.
  • History: Dadurch wird die Hyperledger Fabric-Methode GetHistoryForKey aufgerufen.
  • GetByRange: Dadurch wird die Hyperledger Fabric-Methode GetStateByRange aufgerufen.
  • GetByRangeWithPagination: Dadurch wird die Hyperledger Fabric-Methode GetStateByRangeWithPagination aufgerufen.

SDK-Methoden

Go Chaincodes implementieren Transparent Persistence Capability (ORM) mit dem Modellpaket.

Hinweis:

Ab Version 21.2.3 hat sich der Zugriff auf die ORM-Methoden geändert. Führen Sie den Befehl ochain --version aus, um die Version von Blockchain App Builder zu bestimmen.

In früheren Releases wurden die ORM-Methoden als statische Methoden im Modellpackage angegeben. Die Methoden werden nun am Modellempfänger definiert, der den Transaktionsstub enthält. Um diese Methoden aufzurufen, verwenden Sie den Modellempfänger, der vom Transaktionskontext im Controller gehalten wird. Sie nennen diese Methoden t.Ctx.Model.<method_name> anstelle von model.<method_name>.

Das folgende Beispiel zeigt die Methodenaufrufe Save und Get in früheren Releases:

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
}

Das folgende Beispiel zeigt die Methodenaufrufe Save und Get ab Version 21.2.3:

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
}

Nach dem Upgrade auf Version 21.2.3 nehmen Sie diese Änderung in allen Chaincode-Projekten vor, die Sie mit einer früheren Version von Blockchain App Builder erstellt haben. Wenn Sie den Befehl sync verwenden, um Änderungen zwischen der Spezifikationsdatei und dem Quellcode zu synchronisieren, werden die Änderungen für die einsatzbereiten Methoden automatisch an den Controller übertragen. Sie müssen Konflikte weiterhin manuell lösen.

Die folgenden ORM-Methoden werden über das Modellpaket bereitgestellt:

Get
Fragt das Buch für die gespeicherte Anlage basierend auf der angegebenen ID ab.
func Get(Id string, result ...interface{}) (interface{}, error)
Parameter:
  • Id: Die ID des Vermögensgegenstands, der aus dem Buch erforderlich ist.
  • result (interface{}): Dies ist ein leeres Assetobjekt eines bestimmten Typs, das per Referenz übergeben wird. Dieses Objekt enthält das Ergebnis dieser Methode. Wird nur verwendet, wenn ein typspezifisches Ergebnis erforderlich ist.
  • asset (interface): Leeres Assetobjekt, das per Referenz übergeben wird. Dieses Objekt enthält das Ergebnis dieser Methode. Wird nur verwendet, wenn ein typspezifisches Ergebnis erforderlich ist.
Rückgabewert:
  • interface {}: Die Schnittstelle enthält das Asset im Format map[string]interface{}. Bevor Sie auf dieser Karte arbeiten, müssen Sie die erhaltene Schnittstelle mit dem Typ map[string]interface{} bestätigen. Um diese Zuordnung in ein Assetobjekt zu konvertieren, können Sie die Utility-API util.ConvertMaptoStruct verwenden (siehe: Utilitypackage).
  • error: Enthält einen Fehler, wenn er zurückgegeben wird, oder einen Nullwert.
Update
Aktualisiert die angegebene Anlage im Buch mit den neuen Werten.
func Update(args ...interface{}) (interface{}, error)
Parameter:
  • obj (interface): Das Objekt, das im Buch aktualisiert werden muss, wird per Referenz mit den neuen Werten an diese API übergeben. Das Eingabeasset wird anhand der in der Modellspezifikation genannten Strukturtags validiert und verifiziert und dann im Buch gespeichert.
Rückgabewert:
  • interface{}: Das gespeicherte Asset wird als Schnittstelle zurückgegeben.
  • error: Enthält einen Fehler, wenn er zurückgegeben wird, oder einen Nullwert.
Save
Speichert den Vermögensgegenstand im Buch, nachdem alle Strukturtags validiert wurden.
func Save(args ...interface{}) (interface{}, error)
Parameter:
  • obj/args[0] (interface{}): Das Objekt, das im Buch gespeichert werden muss, wird in dieser Utilitymethode per Referenz übergeben.
  • metadata/args[1] (interface{}): Dieser Parameter ist optional. Es wurde angegeben, um Ihnen zu erleichtern, wenn Sie zur Laufzeit Metadaten zusammen mit dem Asset im Buch speichern müssen. Dieser Parameter kann übersprungen werden, wenn keine solche Anforderung vorhanden ist.
Rückgabewert:
  • interface {}: Das Asset wird als Schnittstelle zurückgegeben.
  • error: Enthält einen Fehler, wenn er zurückgegeben wird, oder einen Nullwert.
Delete
Löscht den Vermögensgegenstand aus dem Buch.
func Delete(Id string) (interface{}, error)
Parameter:
  • id (string): Die ID des Vermögensgegenstands, der aus dem Buch gelöscht werden muss.
Rückgabewert:
  • interface {}: Enthält das zu löschende Asset im Format map[string]interface{}.
GetByRange
Gibt die Liste der Anlagen nach ID-Bereich zurück.
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
Parameter:
  • startkey (string): Start-ID für den Bereich der erforderlichen Objekte.
  • endkey (string): Ende des erforderlichen Objektbereichs.
  • asset interface: (Optional) Leeres Assetarray, das per Referenz übergeben wird. Dieses Array enthält das Ergebnis dieser Methode. Wird verwendet, wenn ein typspezifisches Ergebnis erforderlich ist.
Rückgabewert:
  • []map[string]interface{}: Dieses Array enthält die Liste der aus dem Buch abgerufenen Assets. Sie können auf die Objekte zugreifen, die über dieses Array iterieren, die Objekte als map[string]interface{} bestätigen und das Utility zur Konvertierung in ein Assetobjekt verwenden.
  • error: Enthält einen Fehler, wenn er zurückgegeben wird, oder einen Nullwert.
GetByRangeWithPagination
Die Methode GetByRangeWithPagination ist eine statische Methode der Klasse OchainModel, die von den konkreten Model-Klassen von {chaincodeName}.model.ts geerbt wird.
Dadurch wird eine Liste des Assets zwischen dem Bereich startId und endId zurückgegeben, gefiltert nach Seitengröße und Lesezeichen. Diese Methode ruft die Hyperledger Fabric-Methode GetStateByRangeWithPagination intern auf.
Wenn der Parameter modelName nicht angegeben ist, gibt die Methode Promise<Object [ ] > zurück. Wenn der Parameter modelName angegeben wird, verarbeitet die Methode das Casting in den Typ Model des Aufrufers. Im folgenden Beispiel hat das Ergebnisarray den Typ Supplier. Wenn der aus dem Buch zurückgegebene Vermögensgegenstand nicht den Typ Model aufweist, wird er nicht in die Liste aufgenommen. Diese Prüfung wird von der schreibgeschützten Eigenschaft assetType in der Klasse Model durchgeführt.
Um alle Assets zwischen dem Bereich startId und endId zurückzugeben, gefiltert nach Seitengröße und Lesezeichen, verwenden Sie die generische Controllermethode getAssetsByRange.
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error) 
Parameter:
  • startkey : string: Startschlüssel des Bereichs. Im Bereich enthalten.
  • endkey : string: Endschlüssel des Bereichs. aus dem Bereich ausgeschlossen.
  • pageSize : number: Die Seitengröße der Abfrage.
  • Bookmark : string: Das Lesezeichen der Abfrage. Die Ausgabe beginnt mit diesem Lesezeichen.
  • asset interface – (Optional) Ein leeres Array von Assets, per Referenz übergeben. Dieses Array enthält das Ergebnis dieser Methode. Verwenden Sie diesen Parameter, um typspezifische Ergebnisse abzurufen.
Rückgabewert:
  • []map[string]interface{}: Ein Array, das die Liste der aus dem Buch abgerufenen Assets enthält. Sie können auf die Objekte zugreifen, indem Sie über dieses Array iterieren, die Objekte als map[string]interface{} bestätigen und ein Utility zur Konvertierung in ein Assetobjekt verwenden.
  • error: Enthält einen Fehler, wenn ein Fehler zurückgegeben wird, andernfalls Null.
GetHistoryById
Gibt die Historie der Anlage mit der angegebenen ID zurück.
func GetHistoryByID(Id string) ([]interface{}, error)
Parameter:
  • Id (string): ID des Assets, für das die Historie erforderlich ist.
Rückgabewert:
  • []interface{}: Dieser Bereich enthält die Historie des Assets, das aus dem Ledger in Form eines Bereichs von map[string]interface{} abgerufen wurde. Sie können auf jedes Historienelement zugreifen, indem Sie über diesen Bereich iterieren, die Objekte als map[string]interface{} bestätigen und das Utility zur Konvertierung in ein Assetobjekt verwenden.
  • error: Enthält den Fehler, falls beobachtet.
Query
Die Abfragemethode führt eine SQL/Couch DB-Abfrage über das Ledger aus. Diese Methode wird nur für die Remotebereitstellung auf Oracle Blockchain Platform unterstützt. Dies ist eine generische Methode zur Ausführung von SQL-Abfragen für das Ledger.
func Query(queryString string) ([]interface{}, error)
Parameter:
  • queryString (string): Geben Sie die Abfragezeichenfolge ein.
Rückgabewert:
  • []interface{}: Enthält die Ausgabe der Abfrage. Das Ergebnis sind Schnittstellenbereiche. Sie müssen den Abschnitt iterieren und die Elemente verwenden, indem Sie sie in geeignete Typen konvertieren.
  • error: Enthält den Fehler, falls beobachtet.
QueryWithPagination
Die Abfragemethode führt eine SQL/Couch DB-Abfrage über das Hauptbuch aus, gefiltert nach Seitengröße und Lesezeichen. Diese Methode wird nur für die Remotebereitstellung auf Oracle Blockchain Platform unterstützt. Dies ist eine generische Methode zur Ausführung von SQL-Abfragen für das Ledger.
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
Parameter:
  • queryString (string) - Rich SQL/Couch DB-Abfrage.
  • pageSize : number: Die Seitengröße der Abfrage.
  • bookmark : string: Das Lesezeichen der Abfrage. Die Ausgabe beginnt mit diesem Lesezeichen.
Rückgabewert:
  • []interface{}: Enthält die Ausgabe der Abfrage. Das Ergebnis sind Schnittstellenbereiche. Sie müssen den Abschnitt iterieren und die Elemente verwenden, indem Sie sie in geeignete Typen konvertieren.
  • error: Enthält den Fehler, falls beobachtet.
InvokeCrossChaincode
Sie können diese Methode in einem Chaincode verwenden, um eine Funktion in einem anderen Chaincode aufzurufen. Beide Chaincodes müssen auf demselben Peer installiert sein.
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Parameter:
  • chaincodeName: Der Name des aufzurufenden Chaincodes.
  • methodName: Der Name der Methode, die im Chaincode aufgerufen werden soll.
  • arg: Das Argument der aufrufenden Methode.
  • channelName: Der Kanal, in dem sich der aufzurufende Chaincode befindet.
Rückgabewert:
  • interface{}: Gibt ein map[string]interface{}-Objekt zurück, das drei Schlüssel enthält:
    • isValid: true, wenn der Aufruf gültig ist.
    • payload: Die Ausgabe, die vom Cross-Chaincode-Aufruf als JSON-Objekt zurückgegeben wird.
    • message: Die vom Cross-Chaincode-Aufruf zurückgegebene Nachricht im UTF-8-Format.
Beispiel für einen Rückgabewert:
{
      "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
Sie können diese Methode in einem Chaincode verwenden, um eine Funktion in einem anderen Chaincode aufzurufen. Beide Chaincodes müssen auf demselben Peer installiert sein.
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Parameter:
  • chaincodeName: Der Name des aufzurufenden Chaincodes.
  • methodName: Der Name der Methode, die im Chaincode aufgerufen werden soll.
  • arg: Das Argument der aufrufenden Methode.
  • channelName: Der Kanal, in dem sich der aufzurufende Chaincode befindet.
Rückgabewert:
  • interface{}: Gibt ein map[string]interface{}-Objekt zurück, das drei Schlüssel enthält:
    • isValid: true, wenn der Aufruf gültig ist.
    • payload: Die vom Cross-Chaincode-Aufruf zurückgegebene Ausgabe im UTF-8-Format.
    • message: Die vom Cross-Chaincode-Aufruf zurückgegebene Nachricht im UTF-8-Format.
Beispiel für einen Rückgabewert:
{
    "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}"
} 

Composite-Schlüsselmethoden

GenerateCompositeKey
Diese Methode generiert und gibt den zusammengesetzten Schlüssel basierend auf dem indexName und den in den Argumenten angegebenen Attributen zurück.
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
Parameter:
  • indexName (string): Objekttyp des zusammengesetzten Schlüssels.
  • attrbutes ([]string): Attribute des Assets, auf dessen Basis der zusammengesetzte Schlüssel gebildet werden muss.
Rückgabewert:
  • string: Enthält das Ergebnis des zusammengesetzten Schlüssels.
  • error: Enthält den Fehler, falls beobachtet.
GetByCompositeKey
Diese Methode gibt das Asset zurück, das mit dem Schlüssel und der in den Parametern angegebenen Spalte übereinstimmt. Der Parameter index gibt den Index des Schlüssels an, der im Array der Stub-Methode SplitCompositeKey zurückgegeben wird.
Intern ruft diese Methode die getStateByPartialCompositeKey, splitCompositeKey und getState von Hyperledger Fabric auf.
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
Parameter:
  • key (string): Beim Erstellen des zusammengesetzten Schlüssels angegebener Objekttyp.
  • column ([]string): Dies ist der Bereich der Attribute, nach denen das Buch mit dem zusammengesetzten Schlüssel abgefragt werden muss.
  • index(int): Index des Attributs.
Rückgabewert:
  • Interface{}: Enthält die Liste der Assets, die das Ergebnis dieser Methode sind.
  • error: Enthält ggf. vorhandene Fehler.

Stub-Methode

GetNetworkStub
Diese Methode gibt die Hyperledger Fabric chaincodeStub zurück.
Sie können auf das Shim-Stub zugreifen, indem Sie die Methode GetNetworkStub aufrufen. Dadurch können Sie Ihre eigene Implementierung erstellen und direkt mit den Assets arbeiten.
func GetNetworkStub() shim.ChaincodeStubInterface
Parameter:
  • Kein
Rückgabewert:
  • shim.ChaincodeStubInterface - Dies ist der Hyperledger Fabric-Kettencode-Stub.

Sonstige Methoden

  • GetTransactionId()
  • GetTransactionTimestamp()
  • GetChannelID()
  • GetCreator()
  • GetSignedProposal()
  • GetArgs()
  • GetStringArgs()
  • GetCreatorMspId()
  • GetId
GetTransactionId
Gibt die Transaktions-ID für die aktuelle Chaincode-Aufrufanforderung zurück. Die Transaktions-ID identifiziert die Transaktion im Geltungsbereich des Kanals eindeutig.
func GetTransactionId() string
Parameter:
  • Kein
Rückgabewert:
  • string: Enthält die erforderliche Transaktions-ID.
GetTransactionTimestamp
Gibt den Zeitstempel der Erstellung der Transaktion zurück. Dies wird aus der Transaktion ChannelHeader übernommen. Daher wird der Zeitstempel des Clients angegeben und für alle Endorser derselbe Wert verwendet.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
Parameter:
  • Kein
Rückgabewert:
  • timestamp.Timestamp: Enthält den erforderlichen Zeitstempel.
  • error: Enthält ggf. vorhandene Fehler.
GetChannelID
Gibt die Kanal-ID für den Vorschlag für den zu verarbeitenden Chaincode zurück.
func GetChannelID() string
Parameter:
  • Kein
Rückgabewert:
  • string: Enthält die erforderliche Kanal-ID als Zeichenfolge.
GetCreator
Gibt das Identity-Objekt des Weiterleitenden des Chaincode-Aufrufs zurück
func GetCreator() ([]byte, error)
Parameter:
  • Kein
Rückgabewert:
  • []byte: Enthält das erforderliche Identitätsobjekt serialisiert.
  • error: Enthält ggf. vorhandene Fehler.
GetSignedProposal
Gibt ein vollständig decodiertes Objekt des unterzeichneten Transaktionsvorschlags zurück.
func GetSignedProposal() (*peer.SignedProposal, error)
Parameter:
  • Kein
Rückgabewert:
  • *peer.SignedProposal: Enthält das erforderliche unterzeichnete Vorschlagsobjekt.
  • error: Enthält ggf. vorhandene Fehler.
GetArgs
Gibt die Argumente als Zeichenfolgenarray aus der Chaincode-Aufrufanforderung zurück.
func GetArgs() [][]byte
Parameter:
  • Kein
Rückgabewert:
  • [][]byte: Enthält die übergebenen Argumente.
GetStringArgs
Gibt die Argumente für Chaincode Init und Invoke als Zeichenfolgenarray zurück.
func GetStringArgs() []string
Parameter:
  • Kein
Rückgabewert:
  • []string: Enthält die erforderlichen Argumente als Zeichenfolgenarray.
GetCreatorMspId
Gibt die MSP-ID der aufrufenden Identity zurück.
func GetCreatorMspId() string
Parameter:
  • Kein
Rückgabewert:
  • string: Gibt die MSP-ID der aufrufenden Identität zurück.
GetId
Wenn das Asset den abgeleiteten Schlüssel Id aufweist, können Sie mit dieser Methode eine abgeleitete ID abrufen. Diese Methode gibt einen Fehler zurück, wenn der abgeleitete Schlüssel %t (Zeitstempel) enthält.
Parameter:
  • object: Das Objekt muss alle Eigenschaften enthalten, von denen der abgeleitete Schlüssel abhängig ist.
Rückgabewert:
  • Gibt den abgeleiteten Schlüssel als Zeichenfolge zurück.
Beispiel:
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)
}

Utility-Package

Die folgenden Methoden im Utilitypackage können nützlich sein:

Util.CreateModel
Parst die angegebene JSON-Zeichenfolge und erstellt ein Assetobjekt des angegebenen Typs.
func CreateModel(obj interface{}, inputString string) error
Parameter:
  • inputString (string): Die JSON-Eingabezeichenfolge, aus der das Objekt erstellt werden soll.
  • obj (interface{}): Die Referenz des Objekts, das aus der JSON-Zeichenfolge erstellt werden soll. Dieses Objekt speichert das erstellte Modell, das ebenfalls anhand von Validatortags validiert wird.
Rückgabewert:
  • error: Enthält Fehler, die beim Erstellen oder Validieren des Assets gefunden wurden.
util.ConvertMapToStruct
Konvertieren Sie die bereitgestellte Zuordnung in ein Objekt des angegebenen Typs.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
Parameter:
  • inputMap (map[string](interface{})): Zuordnung, die in das Assetobjekt konvertiert werden muss.
  • resultStruct (interface{}): Die Referenz des erforderlichen Assetobjekts, das aus der Zuordnung generiert werden muss. Enthält das erforderliche Ergebnisassetobjekt.
Rückgabewert:
  • error: Enthält Fehler, die beim Erstellen oder Validieren des Assets gefunden wurden.

Token-SDK-Methoden finden Sie in den Themen unter Tokenisierungsunterstützung mit Blockchain App Builder.

Controller

Die Datei Controller.go implementiert CRUD und benutzerdefinierte Methoden für die Assets.

Sie können eine beliebige Anzahl von Klassen, Funktionen oder Dateien erstellen, aber nur die Methoden, die in Chaincode-Strukturen definiert sind, können von außen aufgerufen werden. Die restlichen Methoden sind ausgeblendet.

Automatisch generierte Methoden

Wie unter Eingabespezifikationsdatei beschrieben, können Sie angeben, welche CRUD-Methoden in der Spezifikationsdatei generiert werden sollen. Beispiel: Wenn Sie alle Methoden generieren möchten, sieht das Ergebnis wie folgt aus:

//	
//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
}

Benutzerdefinierte Methoden

Die folgenden benutzerdefinierten Methoden wurden aus unserer Beispielspezifikationsdatei generiert.

Die executeQuery zeigt, wie SQL-Rich-Abfragen aufgerufen werden können. Die Validatoren für die Argumente werden automatisch von Blockchain App Builder basierend auf dem Typ des in der Spezifikationsdatei angegebenen Arguments hinzugefügt.

Sie können die Funktionalität entsprechend der Geschäftslogik implementieren. Wenn Sie benutzerdefinierte Methoden hinzufügen, fügen Sie sie der Controllerdatei hinzu. Wenn Sie der Bibliothek anstelle der Controllerdatei benutzerdefinierte Methoden hinzufügen, gehen Ihre Änderungen verloren, wenn der Inhalt des Bibliotheksordners während der Synchronisierungs- oder Chaincodeupgradeprozesse aktualisiert wird.

//	
//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
}
Bei Go-Chaincodes muss jede benutzerdefinierte Methode zwei Werte zurückgeben: leere Schnittstelle, Fehler. Beispiel:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) { 
    return nil, nil
}

Initiierungsmethode

Eine benutzerdefinierte Init-Methode wird im Controller mit einer leeren Definition bereitgestellt. Wenn Sie Blockchain App Builder für das Deployment oder Upgrade verwenden, wird die Methode Init automatisch aufgerufen. Wenn Sie die Oracle Blockchain Platform-Konsole auf der Hyperledger Fabric v1.4.7-Plattform bereitstellen oder upgraden, wird die Methode Init auch automatisch aufgerufen. Wenn Sie die Oracle Blockchain Platform-Konsole auf der Hyperledger Fabric v2.x-Plattform bereitstellen oder upgraden, müssen Sie die Methode Init manuell aufrufen. Sie können ein Drittanbietertool wie Postman verwenden, um die Methode Init manuell aufzurufen.

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

Wenn Sie zu diesem Zeitpunkt einen beliebigen Anwendungsstatus initialisieren möchten, können Sie diese Methode verwenden.