diff --git a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go index 7e25c72a..fdf48ff1 100644 --- a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go +++ b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go @@ -200,23 +200,20 @@ func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface func (s *SmartContract) SchemaExists(ctx contractapi.TransactionContextInterface, Hash string) (bool, error) { assetJSON, err := ctx.GetStub().GetState(Hash) if err != nil { - return false, fmt.Errorf("failed to read from world state: %v", err) + return false, fmt.Errorf("failed to read from world state. Schema doesn't exist: %v", err) + } else { + var schema map[string]interface{} + err2 := json.Unmarshal(assetJSON, &schema) + if err2 != nil { + return false, fmt.Errorf("failed to read from world state: %v", err2) + } else if err3, ok := schema["Hash"]; ok { + return assetJSON != nil, nil + } else { + return false, fmt.Errorf("failed to read from world state. Hash passed as parameter may correspond to a Data struct rather than to a Schema: %v", err3) + } } - - return assetJSON != nil, nil } - -func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterface, - version int, newSchemaContent string) error { - - // We assume this new schema is different from what existed previously - //exists, err := s.AssetExists(ctx, Id) - //if err != nil { - // return err - //} - //if exists { - // return fmt.Errorf("the asset %s already exists", Id) - //} +func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterface, newSchemaContent string) error { jsonFileContent, err := s.JsonReader(ctx, newSchemaContent) if err != nil { @@ -228,22 +225,35 @@ func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterf if exists { return fmt.Errorf("Schema already exists: %v", err) } else { - lastSchemaHash = hashContent - newSchema := Schema{ - Version: version, - Hash: hashContent, - JsonSchemaContent: jsonFileContent, + //get previous schema's id + assetJSON, err := ctx.GetStub().GetState(lastSchemaHash) + if err != nil { + return fmt.Errorf("failed to calculate new schema's version: %v", err) + } else { + var schema Schema + err2 := json.Unmarshal(assetJSON, &schema) + if err2 != nil { + return fmt.Errorf("failed to read from world state. LastSchemaHash var may be corrupted: %v", err2) + } else { + version := schema.Version + 1 + lastSchemaHash = hashContent + newSchema := Schema{ + Version: version, + Hash: hashContent, + JsonSchemaContent: jsonFileContent, + } + assetJSON, err := json.Marshal(newSchema) + if err != nil { + return err + } + + err = ctx.GetStub().PutState(newSchema.Hash, assetJSON) + if err != nil { + return fmt.Errorf("failed to put to world state. %v", err) + } + } } - assetJSON, err := json.Marshal(newSchema) - if err != nil { - return err - } - - err = ctx.GetStub().PutState(newSchema.Hash, assetJSON) - if err != nil { - return fmt.Errorf("failed to put to world state. %v", err) - } } return nil @@ -252,48 +262,57 @@ func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterf // GetAllSchemas returns all schemas found in world state -//func (s *SmartContract) GetAllSchemas(ctx contractapi.TransactionContextInterface) ([]Schema, error) { -// range query with empty string for startKey and endKey does an -// open-ended query of all schemas in the chaincode namespace. -//resultsIterator, err := ctx.GetStub().GetStateByRange("", "") -//if err != nil { -// return nil, err -//} -//defer resultsIterator.Close() +func (s *SmartContract) GetAllSchemas(ctx contractapi.TransactionContextInterface) ([]*Schema, error) { + // range query with empty string for startKey and endKey does an + // open-ended query of all schemas in the chaincode namespace. + resultsIterator, err := ctx.GetStub().GetStateByRange("", "") + if err != nil { + return nil, err + } + defer resultsIterator.Close() -//var schemaSamples []*Schema -//for resultsIterator.HasNext() { -// queryResponse, err := resultsIterator.Next() -// if err != nil { -// return nil, err -// } + var schemaSamples []*Schema + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + if err != nil { + return nil, err + } -// var schm Schema -// err = json.Unmarshal(queryResponse.Value, &schm) -// if err != nil { -// return nil, err -// } -// schemaSamples = append(schemaSamples, &schm) -//} + var schema map[string]interface{} + err = json.Unmarshal(queryResponse.Value, &schema) + if err != nil { + return nil, err + } else if _, ok := schema["Hash"]; ok { + var schemaStruct Schema + err = json.Unmarshal(queryResponse.Value, &schemaStruct) + if err != nil { + return nil, err + } else { + schemaSamples = append(schemaSamples, &schemaStruct) + } + } + } -//return schemas, nil -//} + return schemaSamples, nil +} // AssetExists returns true when asset with given ID exists in world state func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, Hash string) (bool, error) { assetJSON, err := ctx.GetStub().GetState(Hash) if err != nil { - return false, fmt.Errorf("Failed to read from world state. Asset dosen't exist: %v", err) - } else { + return false, fmt.Errorf("failed to read from world state. Asset dosen't exist: %v", err) + } else if assetJSON != nil { var data map[string]interface{} err2 := json.Unmarshal(assetJSON, &data) if err2 != nil { return false, fmt.Errorf("failed to read from world state: %v", err2) - } else if _, ok := data["Id"]; ok { + } else if err3, ok := data["Id"]; ok { return assetJSON != nil, nil } else { - return false, nil + return false, fmt.Errorf("failed to read from world state. Hash passed as parameter may correspond to a Schema struct rather than to a Data Struct: %v", err3) } + } else { + return assetJSON != nil, nil } } diff --git a/test-network/JsonSchemaValidationTests/NewSchema.json b/test-network/JsonSchemaValidationTests/NewSchema.json index 447c8476..4014b1b8 100755 --- a/test-network/JsonSchemaValidationTests/NewSchema.json +++ b/test-network/JsonSchemaValidationTests/NewSchema.json @@ -3,8 +3,12 @@ "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, - "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } + "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }, + "City": {"type": "string"} }, "additionalProperties": false, - "required": [ "number", "street_name", "street_type"] - } \ No newline at end of file + "required": [ "number", "street_name", "street_type", "City"] + } + + + "{\"type\": \"object\", \"properties\": { \"number\": { \"type\": \"number\" }, \"street_name\": { \"type\": \"string\" }, \"street_type\": { \"enum\": [\"Street\", \"Avenue\",\"Boulevard\"] }}, \"additionalProperties\": false, \"required\": [ \"number\", \"street_name\", \"city\"]}" \ No newline at end of file diff --git a/test-network/QuickCCTest.sh b/test-network/QuickCCTest.sh index bb5d0810..cbf78786 100644 --- a/test-network/QuickCCTest.sh +++ b/test-network/QuickCCTest.sh @@ -92,22 +92,31 @@ echo "========= CC Query: Get all Schemas ===========" peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllSchemas"]}' -echo "========= Check if sample with id = '00000' Exists ===========" +echo "========= Check if sample with Hash Exists ===========" -peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"AssetExists","Args":["00000"]}' +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"AssetExists","Args":["c838916abe9a4b5d28d7254d84a9c99b42b47a702120ed4486e0069340b7fe30"]}' + +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"AssetExists","Args":["f59b78913db8949c78129d5afccf155abdd29a4e9a1704463b761c58db64b13d"]}' + + +echo "========= Check if Schema with specific Hash Exists ===========" + +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"SchemaExists","Args":["f59b78913db8949c78129d5afccf155abdd29a4e9a1704463b761c58db64b13d"]}' + +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"SchemaExists","Args":["c838916abe9a4b5d28d7254d84a9c99b42b47a702120ed4486e0069340b7fe30"]}' echo "========= Check creation of a new sample wit id = '00001' ===========" -# peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateDataSample","Args":["docTypeTest2","00001","TestTitle2","Desc2","Neuroscience","TestDOI","www.ncis.edu","TestManifest","TestFootPrint", "Neuroscience, brain", "None", "None", "None","None","None","None","None", "None"]}' +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateDataSample","Args":["juanitoAlimania@blades.com", "Contributor123", "00001", "SDSC", "{ \"number\": 1603, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\"}"]}' -#peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateDataSample","Args":["UCSD-SDSC", "Contributor123", "PhonyHash!@#$$%#@", "00001", ["DOE FER"]]}' -peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateDataSample","Args":["UCSD-SDSC", "Contributor123", "PhonyHash!@#$$%#@", "00001", "/home/chaincode/testFileNewSample.json"]}' +echo "========= CC Query: Get all DataSamples ===========" + +peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' -#peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile \ echo "========= Check creation of a new Schema ===========" -peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateNewSchema","Args":["juanitoAlimania@blades.com", "Contributor123", "00001", "SDSC", "/home/chaincode/NewSchema.json"]}' +peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"CreateNewSchema","Args":[ "{\"type\": \"object\", \"properties\": { \"number\": { \"type\": \"number\" }, \"street_name\": { \"type\": \"string\" }, \"street_type\": { \"enum\": [\"Street\", \"Avenue\",\"Boulevard\"] }}, \"additionalProperties\": false, \"required\": [ \"number\", \"street_name\", \"City\"]}"]}' echo "========= Check creation of a new sample wit id = '00002' based on New Schema ==========="