mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
118 lines
No EOL
4.2 KiB
Go
118 lines
No EOL
4.2 KiB
Go
// CreateAsset creates a new asset by placing the main asset details in the assetCollection
|
|
// that can be read by both organizations. The appraisal value is stored in the owners org specific collection.
|
|
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface) error {
|
|
|
|
// Get new asset from transient map
|
|
transientMap, err := ctx.GetStub().GetTransient()
|
|
if err != nil {
|
|
return fmt.Errorf("error getting transient: %v", err)
|
|
}
|
|
|
|
// Asset properties are private, therefore they get passed in transient field, instead of func args
|
|
transientAssetJSON, ok := transientMap["asset_properties"]
|
|
if !ok {
|
|
//log error to stdout
|
|
return fmt.Errorf("asset not found in the transient map input")
|
|
}
|
|
|
|
type assetTransientInput struct {
|
|
Type string `json:"objectType"` //Type is used to distinguish the various types of objects in state database
|
|
ID string `json:"assetID"`
|
|
Color string `json:"color"`
|
|
Size int `json:"size"`
|
|
AppraisedValue int `json:"appraisedValue"`
|
|
}
|
|
|
|
var assetInput assetTransientInput
|
|
err = json.Unmarshal(transientAssetJSON, &assetInput)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unmarshal JSON: %v", err)
|
|
}
|
|
|
|
if len(assetInput.Type) == 0 {
|
|
return fmt.Errorf("objectType field must be a non-empty string")
|
|
}
|
|
if len(assetInput.ID) == 0 {
|
|
return fmt.Errorf("assetID field must be a non-empty string")
|
|
}
|
|
if len(assetInput.Color) == 0 {
|
|
return fmt.Errorf("color field must be a non-empty string")
|
|
}
|
|
if assetInput.Size <= 0 {
|
|
return fmt.Errorf("size field must be a positive integer")
|
|
}
|
|
if assetInput.AppraisedValue <= 0 {
|
|
return fmt.Errorf("appraisedValue field must be a positive integer")
|
|
}
|
|
|
|
// Check if asset already exists
|
|
assetAsBytes, err := ctx.GetStub().GetPrivateData(assetCollection, assetInput.ID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get asset: %v", err)
|
|
} else if assetAsBytes != nil {
|
|
fmt.Println("Asset already exists: " + assetInput.ID)
|
|
return fmt.Errorf("this asset already exists: " + assetInput.ID)
|
|
}
|
|
|
|
// Get ID of submitting client identity
|
|
clientID, err := submittingClientIdentity(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Verify that the client is submitting request to peer in their organization
|
|
// This is to ensure that a client from another org doesn't attempt to read or
|
|
// write private data from this peer.
|
|
err = verifyClientOrgMatchesPeerOrg(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("CreateAsset cannot be performed: Error %v", err)
|
|
}
|
|
|
|
// Make submitting client the owner
|
|
asset := Asset{
|
|
Type: assetInput.Type,
|
|
ID: assetInput.ID,
|
|
Color: assetInput.Color,
|
|
Size: assetInput.Size,
|
|
Owner: clientID,
|
|
}
|
|
assetJSONasBytes, err := json.Marshal(asset)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal asset into JSON: %v", err)
|
|
}
|
|
|
|
// Save asset to private data collection
|
|
// Typical logger, logs to stdout/file in the fabric managed docker container, running this chaincode
|
|
// Look for container name like dev-peer0.org1.example.com-{chaincodename_version}-xyz
|
|
log.Printf("CreateAsset Put: collection %v, ID %v, owner %v", assetCollection, assetInput.ID, clientID)
|
|
|
|
err = ctx.GetStub().PutPrivateData(assetCollection, assetInput.ID, assetJSONasBytes)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to put asset into private data collection: %v", err)
|
|
}
|
|
|
|
// Save asset details to collection visible to owning organization
|
|
assetPrivateDetails := AssetPrivateDetails{
|
|
ID: assetInput.ID,
|
|
AppraisedValue: assetInput.AppraisedValue,
|
|
}
|
|
|
|
assetPrivateDetailsAsBytes, err := json.Marshal(assetPrivateDetails) // marshal asset details to JSON
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal into JSON: %v", err)
|
|
}
|
|
|
|
// Get collection name for this organization.
|
|
orgCollection, err := getCollectionName(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to infer private collection name for the org: %v", err)
|
|
}
|
|
|
|
// Put asset appraised value into owners org specific private data collection
|
|
log.Printf("Put: collection %v, ID %v", orgCollection, assetInput.ID)
|
|
err = ctx.GetStub().PutPrivateData(orgCollection, assetInput.ID, assetPrivateDetailsAsBytes)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to put asset private details: %v", err)
|
|
}
|
|
return nil
|
|
} |