I tried to write a chaincode such that when it's executed in a peer instance, it uploads data to google cloud storage bucket. The file I'll be uploading is actually stored as small file chunks in a folder, so that different peers upload different chunks to the GCS bucket. I'm using the fabcar blueprint to develop this chaincode, and test-network script files to execute the chaincode. The function I used to upload data is working well when I executed locally, but when I tried to use in the chaincode, it's showing
Error: endorsement failure during invoke. response: status:500 message:"error in simulation: failed to execute transaction 49a9b96088ff2f32906a6b6c9ba1f4ac0a530779bf8d506b176fcdfb8818afe2: error sending: chaincode stream terminated"
(What I'm doing might sound crazy, but I'm new to this hyperledger fabric)
Below is the code sample I'm executing (I think it's the problem with uploadGCS or InitLedger function)(FYI: chaincode execution runs InitLedger function only, which ofcourse uses uploadGCS function)
package main
import (
"fmt"
"os"
"io"
"log"
"strings"
"encoding/json"
"encoding/hex"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"path/filepath"
"strconv"
"crypto/sha256"
"time"
"context"
"cloud.google.com/go/storage"
"google.golang.org/api/option"
"golang.org/x/oauth2/google"
)
type SmartContract struct {
contractapi.Contract
}
type Data struct {
Owner string `json:"owner"`
File string `json:"file"`
FileChunkNumber string `json:"filechunknumber"`
SHA256 string `json:"sha256"`
}
func uploadGCS(owner, filechunklocation, uploadlocation string) error {
ct := context.Background()
creds, err := google.FindDefaultCredentials(ct, storage.ScopeReadOnly)
if err != nil {
log.Fatal("GoT an err %s", err)
}
client, err := storage.NewClient(ct, option.WithCredentials(creds))
if err != nil {
return fmt.Errorf("storage.NewClient: %v", err)
}
defer client.Close()
// Open local file.
f, err := os.Open(filechunklocation)
if err != nil {
return fmt.Errorf("os.Open: %v", err)
}
defer f.Close()
ct, cancel := context.WithTimeout(ct, time.Second*50)
defer cancel()
// Upload an object with storage.Writer.
wc := client.Bucket("btp2016bcs0015-cloud-storage").Object(uploadlocation).NewWriter(ct)
if _, err = io.Copy(wc, f); err != nil {
return fmt.Errorf("io.Copy: %v", err)
}
if err := wc.Close(); err != nil {
return fmt.Errorf("Writer.Close: %v", err)
}
return nil
}
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
filelocation := "/home/busyfriend/go/src/github.com/hyperledger/fabric-samples/test-network/samplefile---pdf"
data := []Data{
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "1", SHA256: "eb73a20d61c1fb294b0eba4d35568d10c8ddbfe2544a3cacc959d640077673f5"},
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "2", SHA256: "92dd8ea8aa0da4a48a2cb45ae38f70f17526b6b50ef80c44367a56de6ec9abf9"},
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "3", SHA256: "b97027d261d01f86d1e514a52886add096ddc4e66d15d01e53516dd9d5cfb20b"},
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "4", SHA256: "377582f5e62dc3b34e40741f2d70d8f37a029856f75cbe68a6659328258e23a3"},
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "5", SHA256: "afb6c6d112d446ac07d78b13957bb440105038411095032de444bf08e3bbdba8"},
Data{Owner: "ID126859", File: "samplefile.pdf", FileChunkNumber: "6", SHA256: "e43b885c2bfb47130c54fa70528fb2a91d9d1af1417a0f7c5a4c22d8f16efb01"},
}
for i := range data {
_, dir := filepath.Split(filelocation)
dir_1 := strings.Split(dir,"---")
filechunk := dir_1[0]+"_"+ data[i].FileChunkNumber
filechunklocation := filepath.Join(filelocation, filechunk)
uploadlocation := data[i].Owner + "/" + dir + "/" + filechunk
err := uploadGCS(data[i].Owner, filechunklocation, uploadlocation)
if err != nil {
return fmt.Errorf("Got an error %s", err.Error())
}
}
for i, putdata := range data {
dataAsBytes, _ := json.Marshal(putdata)
err := ctx.GetStub().PutState("DATA"+strconv.Itoa(i), dataAsBytes)
if err != nil {
return fmt.Errorf("Failed to put to world state. %s", err.Error())
}
}
return nil
}
// Uploads new data to the world state with given details
func (s *SmartContract) uploadData(ctx contractapi.TransactionContextInterface, dataID string, owner string, filelocation string, filechunknumber string) error {
//Uploads the filechunk to the cloud storage
_, dir := filepath.Split(filelocation)
dir_1 := strings.Split(dir,"---")
filechunk := dir_1[0]+"_"+ filechunknumber
filechunklocation := filepath.Join(filelocation, filechunk)
uploadlocation := owner + "/" + dir + "/" + filechunk
err := uploadGCS(owner, filechunklocation, uploadlocation)
if err != nil {
fmt.Println(err.Error())
return err
}
//Creates SHA256 hash of the file chunk
f, err := os.Open(filechunklocation)
if err != nil {
log.Fatal(err)
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
data := Data{
Owner: owner,
File: dir_1[0]+"."+dir_1[1],
FileChunkNumber: filechunknumber,
SHA256: hex.EncodeToString(h.Sum(nil)),
}
dataAsBytes, _ := json.Marshal(data)
return ctx.GetStub().PutState(dataID, dataAsBytes)
}
func main() {
chaincode, err := contractapi.NewChaincode(new(SmartContract))
if err != nil {
fmt.Printf("Error create cloud chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting cloud chaincode: %s", err.Error())
}
}
This is something I got after executing this chaincode terminal result