From 59e1e47bd0aa6f8287d5d679ff7964c11e7e28e3 Mon Sep 17 00:00:00 2001 From: r2roC Date: Wed, 8 Jul 2020 10:11:52 -0400 Subject: [PATCH] Update asset_transfer_ledger_chaincode.go Small off-by-1 bug fix. Signed-off-by: r2roC run fabcar go (#232) * add go/runfabcar.sh Signed-off-by: Acmefocus <107723772@qq.com> * add set hosts and env in go Signed-off-by: Acmefocus <107723772@qq.com> * Update fabcar/startFabric.sh Co-authored-by: Sijo Cherian Signed-off-by: Acmefocus <107723772@qq.com> * Update startFabric.sh delete set /etc/hosts Signed-off-by: Acmefocus <107723772@qq.com> * add environment variable DISCOVERY_AS_LOCALHOST Signed-off-by: Acmefocus <107723772@qq.com> Co-authored-by: Sijo Cherian Fix asset transfer go chaincode functions for CreateAsset and UpdateAsset. Signed-off-by: Chris Gabriel Add param types. Signed-off-by: Chris Gabriel Update smartcontract.go and smartcontract_test.go Signed-off-by: Chris Gabriel --- .../chaincode-go/assetTransfer.go | 190 ++++++++++++++++++ .../chaincode-go/chaincode/smartcontract.go | 4 +- .../chaincode/smartcontract_test.go | 12 +- .../asset_transfer_ledger_chaincode.go | 2 +- fabcar/go/fabcar.go | 1 + fabcar/go/runfabcar.sh | 15 ++ 6 files changed, 215 insertions(+), 9 deletions(-) create mode 100755 fabcar/go/runfabcar.sh diff --git a/asset-transfer-basic/chaincode-go/assetTransfer.go b/asset-transfer-basic/chaincode-go/assetTransfer.go index 9c619d56..8a9b3d13 100644 --- a/asset-transfer-basic/chaincode-go/assetTransfer.go +++ b/asset-transfer-basic/chaincode-go/assetTransfer.go @@ -11,6 +11,196 @@ import ( "github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode" ) +// SmartContract provides functions for managing an Asset +type SmartContract struct { + contractapi.Contract +} + +// Asset describes basic details of what makes up a simple asset +type Asset struct { + ID string `json:"ID"` + Color string `json:"color"` + Size int `json:"size"` + Owner string `json:"owner"` + AppraisedValue int `json:"appraisedValue"` +} + +// QueryResult structure used for handling result of query +type QueryResult struct { + Key string `json:"Key"` + Record *Asset +} + +// InitLedger adds a base set of assets to the ledger +func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error { + assets := []Asset{ + Asset{ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300}, + Asset{ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400}, + Asset{ID: "asset3", Color: "green", Size: 10, Owner: "Jin Soo", AppraisedValue: 500}, + Asset{ID: "asset4", Color: "yellow", Size: 10, Owner: "Max", AppraisedValue: 600}, + Asset{ID: "asset5", Color: "black", Size: 15, Owner: "Adriana", AppraisedValue: 700}, + Asset{ID: "asset6", Color: "white", Size: 15, Owner: "Michel", AppraisedValue: 800}, + } + + for _, asset := range assets { + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + err = ctx.GetStub().PutState(asset.ID, assetJSON) + if err != nil { + return fmt.Errorf("Failed to put to world state. %s", err.Error()) + } + } + + return nil +} + +// CreateAsset issues a new asset to the world state with given details. +func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if exists { + return fmt.Errorf("The asset %s already exists", id) + } + + asset := Asset{ + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + } + + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// ReadAsset returns the asset stored in the world state with given id. +func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return nil, fmt.Errorf("Failed to read from world state. %s", err.Error()) + } + if assetJSON == nil { + return nil, fmt.Errorf("The asset %s does not exist", id) + } + + asset := new(Asset) + err = json.Unmarshal(assetJSON, asset) + if err != nil { + return nil, err + } + + return asset, nil +} + +// UpdateAsset updates an existing asset in the world state with provided parameters. +func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("The asset %s does not exist", id) + } + + // overwritting original asset with new asset + asset := Asset{ + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + } + + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// DeleteAsset deletes an given asset from the world state. +func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("The asset %s does not exist", id) + } + + return ctx.GetStub().DelState(id) +} + +// AssetExists returns true when asset with given ID exists in world state +func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return false, fmt.Errorf("Failed to read from world state. %s", err.Error()) + } + + return assetJSON != nil, nil +} + +// TransferAsset updates the owner field of asset with given id in world state. +func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) error { + asset, err := s.ReadAsset(ctx, id) + if err != nil { + return err + } + + asset.Owner = newOwner + + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// GetAllAssets returns all assets found in world state +func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) { + // range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace. + resultsIterator, err := ctx.GetStub().GetStateByRange("", "") + + if err != nil { + return nil, err + } + defer resultsIterator.Close() + + results := []QueryResult{} + + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + + if err != nil { + return nil, err + } + + asset := new(Asset) + err = json.Unmarshal(queryResponse.Value, asset) + if err != nil { + return nil, err + } + + queryResult := QueryResult{Key: queryResponse.Key, Record: asset} + results = append(results, queryResult) + } + + return results, nil +} + func main() { assetChaincode, err := contractapi.NewChaincode(&chaincode.SmartContract{}) if err != nil { diff --git a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go index 862634e8..a2b9b169 100644 --- a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go +++ b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go @@ -54,7 +54,7 @@ func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) } // CreateAsset issues a new asset to the world state with given details. -func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { +func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error { exists, err := s.AssetExists(ctx, id) if err != nil { return err @@ -98,7 +98,7 @@ func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, i } // UpdateAsset updates an existing asset in the world state with provided parameters. -func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { +func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error { exists, err := s.AssetExists(ctx, id) if err != nil { return err diff --git a/asset-transfer-basic/chaincode-go/chaincode/smartcontract_test.go b/asset-transfer-basic/chaincode-go/chaincode/smartcontract_test.go index 1127517c..ef6e2921 100644 --- a/asset-transfer-basic/chaincode-go/chaincode/smartcontract_test.go +++ b/asset-transfer-basic/chaincode-go/chaincode/smartcontract_test.go @@ -48,15 +48,15 @@ func TestCreateAsset(t *testing.T) { transactionContext.GetStubReturns(chaincodeStub) assetTransfer := chaincode.SmartContract{} - err := assetTransfer.CreateAsset(transactionContext, "", "", "", 0, 0) + err := assetTransfer.CreateAsset(transactionContext, "", "", 0, "", 0) require.NoError(t, err) chaincodeStub.GetStateReturns([]byte{}, nil) - err = assetTransfer.CreateAsset(transactionContext, "asset1", "", "", 0, 0) + err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "the asset asset1 already exists") chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) - err = assetTransfer.CreateAsset(transactionContext, "asset1", "", "", 0, 0) + err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "failed to read from world state: unable to retrieve asset") } @@ -96,15 +96,15 @@ func TestUpdateAsset(t *testing.T) { chaincodeStub.GetStateReturns(bytes, nil) assetTransfer := chaincode.SmartContract{} - err = assetTransfer.UpdateAsset(transactionContext, "", "", "", 0, 0) + err = assetTransfer.UpdateAsset(transactionContext, "", "", 0, "", 0) require.NoError(t, err) chaincodeStub.GetStateReturns(nil, nil) - err = assetTransfer.UpdateAsset(transactionContext, "asset1", "", "", 0, 0) + err = assetTransfer.UpdateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "the asset asset1 does not exist") chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) - err = assetTransfer.UpdateAsset(transactionContext, "asset1", "", "", 0, 0) + err = assetTransfer.UpdateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "failed to read from world state: unable to retrieve asset") } diff --git a/asset-transfer-ledger-queries/chaincode-go/asset_transfer_ledger_chaincode.go b/asset-transfer-ledger-queries/chaincode-go/asset_transfer_ledger_chaincode.go index cb56627e..ac6daeb7 100644 --- a/asset-transfer-ledger-queries/chaincode-go/asset_transfer_ledger_chaincode.go +++ b/asset-transfer-ledger-queries/chaincode-go/asset_transfer_ledger_chaincode.go @@ -293,7 +293,7 @@ func (t *SimpleChaincode) TransferAssetBasedOnColor(ctx contractapi.TransactionC return fmt.Errorf(err.Error()) } - if len(compositeKeyParts) > 2 { + if len(compositeKeyParts) > 1 { returnedAssetID := compositeKeyParts[1] // Now call the transfer function for the found asset. diff --git a/fabcar/go/fabcar.go b/fabcar/go/fabcar.go index f75c6dd3..0b1ffb93 100644 --- a/fabcar/go/fabcar.go +++ b/fabcar/go/fabcar.go @@ -18,6 +18,7 @@ import ( ) func main() { + os.Setenv("DISCOVERY_AS_LOCALHOST", "true") wallet, err := gateway.NewFileSystemWallet("wallet") if err != nil { fmt.Printf("Failed to create wallet: %s\n", err) diff --git a/fabcar/go/runfabcar.sh b/fabcar/go/runfabcar.sh new file mode 100755 index 00000000..13792521 --- /dev/null +++ b/fabcar/go/runfabcar.sh @@ -0,0 +1,15 @@ + +ENV_DAL=`echo $DISCOVERY_AS_LOCALHOST` + +echo "ENV_DAL:"$DISCOVERY_AS_LOCALHOST + +if [ "$ENV_DAL" != "true" ] +then + export DISCOVERY_AS_LOCALHOST=true +fi + +echo "DISCOVERY_AS_LOCALHOST="$DISCOVERY_AS_LOCALHOST + +echo "run fabcar..." + +go run fabcar.go