mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
Schema validation working for submitting data to Ledger
This commit is contained in:
parent
4d589074ba
commit
ea2bd84eb8
2 changed files with 75 additions and 71 deletions
|
|
@ -35,12 +35,13 @@ const PDC1 = "PDC1"
|
||||||
const PDC2 = "PDC2"
|
const PDC2 = "PDC2"
|
||||||
|
|
||||||
type Data struct {
|
type Data struct {
|
||||||
Contributor string `json:"Contributor"`
|
OrgName string `json:"OrgName"`
|
||||||
ContributorId string `json:"ContributorId"`
|
ProjectName string `json:"ProjectName"`
|
||||||
ContentHash string `json:"ContentHash"`
|
ContentHash string `json:"ContentHash"`
|
||||||
Id string `json:"Id"`
|
Comment string `json:"Comment"`
|
||||||
Owner string `json:"Owners"`
|
Date string `json:"Date"`
|
||||||
JsonFileContent map[string]interface{}
|
Submitter string `json:Submitter`
|
||||||
|
JsonContent map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrivateSchemaContent struct {
|
type PrivateSchemaContent struct {
|
||||||
|
|
@ -148,9 +149,9 @@ func main() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (s *SmartContract) LastSchemaHash(ctx contractapi.TransactionContextInterface) string {
|
/*func (s *SmartContract) LastSchemaHash(ctx contractapi.TransactionContextInterface) string {
|
||||||
return lastSchemaHash
|
return lastSchemaHash
|
||||||
}
|
*/
|
||||||
|
|
||||||
func (s *SmartContract) Hash(ctx contractapi.TransactionContextInterface, doc string) (string, error) {
|
func (s *SmartContract) Hash(ctx contractapi.TransactionContextInterface, doc string) (string, error) {
|
||||||
|
|
||||||
|
|
@ -217,20 +218,16 @@ func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface
|
||||||
return dataSamples, nil
|
return dataSamples, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SmartContract) SchemaExists(ctx contractapi.TransactionContextInterface, Hash string) (bool, error) {
|
func (s *SmartContract) SchemaExists(ctx contractapi.TransactionContextInterface, SchemaID string) (bool, error) {
|
||||||
assetJSON, err := ctx.GetStub().GetState(Hash)
|
|
||||||
if err != nil {
|
assetJSON, err := s.ReadSchemaFromPDC(ctx, SchemaID)
|
||||||
|
|
||||||
|
if assetJSON == nil {
|
||||||
|
return false, fmt.Errorf("failed to read from world state. Schema doesn't exist: %v", err)
|
||||||
|
} else if err != nil {
|
||||||
return false, fmt.Errorf("failed to read from world state. Schema doesn't exist: %v", err)
|
return false, fmt.Errorf("failed to read from world state. Schema doesn't exist: %v", err)
|
||||||
} else {
|
} else {
|
||||||
var schema map[string]interface{}
|
return true, nil
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +282,7 @@ func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterf
|
||||||
|
|
||||||
// GetAllSchemas returns all schemas found in world state
|
// GetAllSchemas returns all schemas found in world state
|
||||||
|
|
||||||
func (s *SmartContract) GetAllSchemas(ctx contractapi.TransactionContextInterface) ([]*Schema, error) {
|
/*func (s *SmartContract) GetAllSchemas(ctx contractapi.TransactionContextInterface) ([]*Schema, error) {
|
||||||
// range query with empty string for startKey and endKey does an
|
// range query with empty string for startKey and endKey does an
|
||||||
// open-ended query of all schemas in the chaincode namespace.
|
// open-ended query of all schemas in the chaincode namespace.
|
||||||
resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
|
resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
|
||||||
|
|
@ -318,6 +315,7 @@ func (s *SmartContract) GetAllSchemas(ctx contractapi.TransactionContextInterfac
|
||||||
|
|
||||||
return schemaSamples, nil
|
return schemaSamples, nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// AssetExists returns true when asset with given ID exists in world state
|
// AssetExists returns true when asset with given ID exists in world state
|
||||||
func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, Hash string) (bool, error) {
|
func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, Hash string) (bool, error) {
|
||||||
|
|
@ -329,7 +327,7 @@ func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface,
|
||||||
err2 := json.Unmarshal(assetJSON, &data)
|
err2 := json.Unmarshal(assetJSON, &data)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return false, fmt.Errorf("failed to read from world state: %v", err2)
|
return false, fmt.Errorf("failed to read from world state: %v", err2)
|
||||||
} else if err3, ok := data["Id"]; ok {
|
} else if err3, ok := data["ContentHash"]; ok {
|
||||||
return assetJSON != nil, nil
|
return assetJSON != nil, nil
|
||||||
} else {
|
} else {
|
||||||
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)
|
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)
|
||||||
|
|
@ -341,20 +339,9 @@ func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface,
|
||||||
|
|
||||||
// JSON Validation
|
// JSON Validation
|
||||||
|
|
||||||
func (s *SmartContract) ValidJson(ctx contractapi.TransactionContextInterface, JsonContent string) (bool, error) {
|
func (s *SmartContract) ValidJson(ctx contractapi.TransactionContextInterface, JsonContent string, SchemaID string) (bool, error) {
|
||||||
|
|
||||||
//schemaLoader := gojsonschema.NewReferenceLoader("file:///Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/Schema.json")
|
schema, err := s.ReadSchemaFromPDC(ctx, SchemaID)
|
||||||
//documentLoader := gojsonschema.NewReferenceLoader("file:////Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/testFile.json")
|
|
||||||
|
|
||||||
//schemaLoader := gojsonschema.NewReferenceLoader("file:///home/chaincode/Schema.json")
|
|
||||||
//documentLoader := gojsonschema.NewReferenceLoader("file:////home/chaincode/testFile.json")
|
|
||||||
|
|
||||||
// PATH Needs to be absolute path (From root '/'). Add something that takes care of that.
|
|
||||||
|
|
||||||
//m := schemas[len(schemas) - 1].JsonFileContent
|
|
||||||
|
|
||||||
CurrentSchemaHash := s.LastSchemaHash(ctx)
|
|
||||||
schema, _ := s.ReadSchema(ctx, CurrentSchemaHash)
|
|
||||||
|
|
||||||
schemaLoader := gojsonschema.NewGoLoader(schema.JsonSchemaContent)
|
schemaLoader := gojsonschema.NewGoLoader(schema.JsonSchemaContent)
|
||||||
documentLoader := gojsonschema.NewStringLoader(JsonContent)
|
documentLoader := gojsonschema.NewStringLoader(JsonContent)
|
||||||
|
|
@ -378,9 +365,20 @@ func (s *SmartContract) ValidJson(ctx contractapi.TransactionContextInterface, J
|
||||||
|
|
||||||
// CreateDataSample issues a new Data Sample to the world state with given details.
|
// CreateDataSample issues a new Data Sample to the world state with given details.
|
||||||
func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInterface,
|
func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInterface,
|
||||||
Contributor string, ContributorId string, Id string, Owner string, JsonFileContent string, AnonymousFunder string, AssetValue string) error {
|
OrgName string, ProjectName string, Comment string, Date string, Submitter string, JsonFileContent string, SchemaID string) error {
|
||||||
|
|
||||||
ContentHash, _ := s.Hash(ctx, JsonFileContent)
|
SchemaExists, err := s.SchemaExists(ctx, SchemaID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !SchemaExists {
|
||||||
|
return fmt.Errorf("the Schema with Id %s doesn't exists", SchemaID)
|
||||||
|
}
|
||||||
|
ContentHash, err := s.Hash(ctx, JsonFileContent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
exists, err := s.AssetExists(ctx, ContentHash)
|
exists, err := s.AssetExists(ctx, ContentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -389,7 +387,7 @@ func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInter
|
||||||
return fmt.Errorf("the asset %s already exists", ContentHash)
|
return fmt.Errorf("the asset %s already exists", ContentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
valid, err := s.ValidJson(ctx, JsonFileContent)
|
valid, err := s.ValidJson(ctx, JsonFileContent, SchemaID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -401,12 +399,13 @@ func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInter
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
data := Data{
|
data := Data{
|
||||||
Contributor: Contributor,
|
OrgName: OrgName,
|
||||||
ContributorId: ContributorId,
|
ProjectName: ProjectName,
|
||||||
ContentHash: ContentHash,
|
ContentHash: ContentHash,
|
||||||
Id: Id,
|
Comment: Comment,
|
||||||
Owner: Owner,
|
Date: Date,
|
||||||
JsonFileContent: jsonFileContent,
|
Submitter: Submitter,
|
||||||
|
JsonContent: jsonFileContent,
|
||||||
}
|
}
|
||||||
|
|
||||||
assetJSON, err := json.Marshal(data)
|
assetJSON, err := json.Marshal(data)
|
||||||
|
|
@ -494,7 +493,7 @@ func (s *SmartContract) ReadUser(ctx contractapi.TransactionContextInterface, UU
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SmartContract) ReadSchema(ctx contractapi.TransactionContextInterface, hash string) (*Schema, error) {
|
/*func (s *SmartContract) ReadSchema(ctx contractapi.TransactionContextInterface, hash string) (*Schema, error) {
|
||||||
assetJSON, err := ctx.GetStub().GetState(hash)
|
assetJSON, err := ctx.GetStub().GetState(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read from world state: %v", err)
|
return nil, fmt.Errorf("failed to read from world state: %v", err)
|
||||||
|
|
@ -511,28 +510,9 @@ func (s *SmartContract) ReadSchema(ctx contractapi.TransactionContextInterface,
|
||||||
|
|
||||||
return &schema, nil
|
return &schema, nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
|
// TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
|
||||||
func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, Id string, newOwner string) (string, error) {
|
|
||||||
data, err := s.ReadAsset(ctx, Id)
|
|
||||||
if err != nil {
|
|
||||||
return "Read Asset function failed excecution", err
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Owner = newOwner
|
|
||||||
|
|
||||||
assetJSON, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return "Marshal of Data not one", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ctx.GetStub().PutState(Id, assetJSON)
|
|
||||||
if err != nil {
|
|
||||||
return "Unable to update asset", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.Owner, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SmartContract) contains(ctx contractapi.TransactionContextInterface, st []string, str string) bool {
|
func (s *SmartContract) contains(ctx contractapi.TransactionContextInterface, st []string, str string) bool {
|
||||||
for _, v := range st {
|
for _, v := range st {
|
||||||
|
|
@ -923,13 +903,13 @@ func (s *SmartContract) ReadSchemaFromPDC(ctx contractapi.TransactionContextInte
|
||||||
log.Printf("ReadSchemaFromPDC: collection %v, ID %v", PDC1, SchemaID)
|
log.Printf("ReadSchemaFromPDC: collection %v, ID %v", PDC1, SchemaID)
|
||||||
assetJSON, err := ctx.GetStub().GetPrivateData(PDC1, SchemaID) //get the asset from chaincode state
|
assetJSON, err := ctx.GetStub().GetPrivateData(PDC1, SchemaID) //get the asset from chaincode state
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read asset: %v", err)
|
return nil, fmt.Errorf("failed to read Schema: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//No Asset found, return empty response
|
//No Asset found, return empty response
|
||||||
if assetJSON == nil {
|
if assetJSON == nil {
|
||||||
log.Printf("%v does not exist in collection %v", SchemaID, PDC1)
|
log.Printf("%v does not exist in collection %v", SchemaID, PDC1)
|
||||||
return nil, nil
|
return nil, fmt.Errorf("%v does not exist in collection %v", SchemaID, PDC1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var schema *Schema
|
var schema *Schema
|
||||||
|
|
@ -942,7 +922,7 @@ func (s *SmartContract) ReadSchemaFromPDC(ctx contractapi.TransactionContextInte
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SmartContract) GetAllPDCSchemas(ctx contractapi.TransactionContextInterface, SchemaID string) ([]*Schema, error) {
|
func (s *SmartContract) GetAllPDCSchemas(ctx contractapi.TransactionContextInterface) ([]*Schema, error) {
|
||||||
log.Printf("GetAllPDCSchemas: collection %v ", PDC1)
|
log.Printf("GetAllPDCSchemas: collection %v ", PDC1)
|
||||||
|
|
||||||
resultsIterator, err := ctx.GetStub().GetPrivateDataByRange(PDC1, "", "")
|
resultsIterator, err := ctx.GetStub().GetPrivateDataByRange(PDC1, "", "")
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,13 @@ echo "========= CC Query: Get all DataSamples ==========="
|
||||||
|
|
||||||
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
|
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
echo "========= Setting Up Network with PDC and SmartContract ==========="
|
echo "========= Setting Up Network with PDC and SmartContract ==========="
|
||||||
|
|
||||||
./monitordocker.sh fabric_test
|
./monitordocker.sh fabric_test
|
||||||
|
|
@ -245,11 +252,28 @@ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.e
|
||||||
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp
|
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp
|
||||||
export CORE_PEER_ADDRESS=localhost:7051
|
export CORE_PEER_ADDRESS=localhost:7051
|
||||||
|
|
||||||
export ASSET_PROPERTIES=$(echo -n "{\"SchemaId\":\"Project1.Schema1\",\"Project\":\"Project1\",\"JsonSchemaContent\":{\"type\": \"object\", \"properties\": { \"number\": { \"type\": \"number\" }, \"street_name\": { \"type\": \"string\" }, \"street_type\": { \"enum\": [\"Street\", \"Avenue\",\"Boulevard\"] }}, \"additionalProperties\": false, \"required\": [ \"number\", \"street_name\"]}}" | base64 | tr -d \\n)
|
export ASSET_PROPERTIES=$(echo -n "{\"SchemaId\":\"Project1.Schema1\",\"Project\":\"Project1\",\"JsonSchemaContent\":{\"type\": \"object\", \"properties\": { \"number\": { \"type\": \"number\" }, \"street_name\": { \"type\": \"string\" }, \"street_type\": { \"enum\": [\"Street\", \"Avenue\",\"Boulevard\"] }}, \"additionalProperties\": true, \"required\": [ \"number\", \"street_name\"]}}" | base64 | tr -d \\n)
|
||||||
|
|
||||||
|
|
||||||
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 private -c '{"function":"WriteSchemaToPDC","Args":[]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
|
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 private -c '{"function":"WriteSchemaToPDC","Args":[]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
|
||||||
|
|
||||||
|
export ASSET_PROPERTIES=$(echo -n "{\"SchemaId\":\"Project1.Schema2\",\"Project\":\"Project1\",\"JsonSchemaContent\":{\"type\": \"object\", \"properties\": { \"number\": { \"type\": \"number\" }, \"street_name\": { \"type\": \"string\" }, \"street_type\": { \"enum\": [\"Street\", \"Avenue\",\"Boulevard\"] }}, \"additionalProperties\": true, \"required\": [ \"number\", \"street_name\"]}}" | base64 | tr -d \\n)
|
||||||
|
|
||||||
|
|
||||||
|
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 private -c '{"function":"WriteSchemaToPDC","Args":[]}' --transient "{\"asset_properties\":\"$ASSET_PROPERTIES\"}"
|
||||||
|
|
||||||
|
|
||||||
echo "========= CC Invoke: Reading of Schema in PDC ==========="
|
echo "========= CC Invoke: Reading of Schema in PDC ==========="
|
||||||
|
|
||||||
peer chaincode query -C mychannel -n private -c '{"function":"ReadAsset","Args":["Project1.Schema1"]}'
|
peer chaincode query -C mychannel -n private -c '{"function":"ReadSchemaFromPDC","Args":["Project2.Schema1"]}'
|
||||||
|
|
||||||
|
peer chaincode query -C mychannel -n private -c '{"function":"ReadSchemaFromPDC","Args":["Project1.Schema2"]}'
|
||||||
|
|
||||||
|
|
||||||
|
echo "========= CC Invoke: Reading all Schemas in PDC ==========="
|
||||||
|
|
||||||
|
peer chaincode query -C mychannel -n private -c '{"function":"GetAllPDCSchemas","Args":["1"]}'
|
||||||
|
|
||||||
|
echo "========= CC Invoke: Creation of DataSample ==========="
|
||||||
|
|
||||||
|
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":["CIA Org", "Project 1", "Comment: Proof of live in Mars", "13/13/13", "Project1.Schema1", "{ \"number\": 1603, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\"}"]}'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue