-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge "[FAB-4430] - WYFA scripts and node code"
- Loading branch information
Showing
65 changed files
with
1,227 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
/* | ||
* The sample smart contract for documentation topic: | ||
* Writing Your First Blockchain Application | ||
*/ | ||
|
||
package main | ||
|
||
/* Imports | ||
* 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation | ||
* 2 specific Hyperledger Fabric specific libraries for Smart Contracts | ||
*/ | ||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
sc "github.com/hyperledger/fabric/protos/peer" | ||
) | ||
|
||
// Define the Smart Contract structure | ||
type SmartContract struct { | ||
} | ||
|
||
// Define the car structure, with 4 properties. Structure tags are used by encoding/json library | ||
type Car struct { | ||
Make string `json:"make"` | ||
Model string `json:"model"` | ||
Colour string `json:"colour"` | ||
Owner string `json:"owner"` | ||
} | ||
|
||
/* | ||
* The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network | ||
* Best practice is to have any Ledger initialization in separate function -- see initLedger() | ||
*/ | ||
func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response { | ||
return shim.Success(nil) | ||
} | ||
|
||
/* | ||
* The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" | ||
* The calling application program has also specified the particular smart contract function to be called, with arguments | ||
*/ | ||
func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { | ||
|
||
// Retrieve the requested Smart Contract function and arguments | ||
function, args := APIstub.GetFunctionAndParameters() | ||
// Route to the appropriate handler function to interact with the ledger appropriately | ||
if function == "queryCar" { | ||
return s.queryCar(APIstub, args) | ||
} else if function == "initLedger" { | ||
return s.initLedger(APIstub) | ||
} else if function == "createCar" { | ||
return s.createCar(APIstub, args) | ||
} else if function == "queryAllCars" { | ||
return s.queryAllCars(APIstub) | ||
} else if function == "changeCarOwner" { | ||
return s.changeCarOwner(APIstub, args) | ||
} | ||
|
||
return shim.Error("Invalid Smart Contract function name.") | ||
} | ||
|
||
func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | ||
|
||
if len(args) != 1 { | ||
return shim.Error("Incorrect number of arguments. Expecting 1") | ||
} | ||
|
||
carAsBytes, _ := APIstub.GetState(args[0]) | ||
return shim.Success(carAsBytes) | ||
} | ||
|
||
func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response { | ||
cars := []Car{ | ||
Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"}, | ||
Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"}, | ||
Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"}, | ||
Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"}, | ||
Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"}, | ||
Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"}, | ||
Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"}, | ||
Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"}, | ||
Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"}, | ||
Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"}, | ||
} | ||
|
||
i := 0 | ||
for i < len(cars) { | ||
fmt.Println("i is ", i) | ||
carAsBytes, _ := json.Marshal(cars[i]) | ||
APIstub.PutState("CAR"+strconv.Itoa(i), carAsBytes) | ||
fmt.Println("Added", cars[i]) | ||
i = i + 1 | ||
} | ||
|
||
return shim.Success(nil) | ||
} | ||
|
||
func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | ||
|
||
if len(args) != 5 { | ||
return shim.Error("Incorrect number of arguments. Expecting 5") | ||
} | ||
|
||
var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]} | ||
|
||
carAsBytes, _ := json.Marshal(car) | ||
APIstub.PutState(args[0], carAsBytes) | ||
|
||
return shim.Success(nil) | ||
} | ||
|
||
func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { | ||
|
||
startKey := "CAR0" | ||
endKey := "CAR999" | ||
|
||
resultsIterator, err := APIstub.GetStateByRange(startKey, endKey) | ||
if err != nil { | ||
return shim.Error(err.Error()) | ||
} | ||
defer resultsIterator.Close() | ||
|
||
// buffer is a JSON array containing QueryResults | ||
var buffer bytes.Buffer | ||
buffer.WriteString("[") | ||
|
||
bArrayMemberAlreadyWritten := false | ||
for resultsIterator.HasNext() { | ||
queryResponse, err := resultsIterator.Next() | ||
if err != nil { | ||
return shim.Error(err.Error()) | ||
} | ||
// Add a comma before array members, suppress it for the first array member | ||
if bArrayMemberAlreadyWritten == true { | ||
buffer.WriteString(",") | ||
} | ||
buffer.WriteString("{\"Key\":") | ||
buffer.WriteString("\"") | ||
buffer.WriteString(queryResponse.Key) | ||
buffer.WriteString("\"") | ||
|
||
buffer.WriteString(", \"Record\":") | ||
// Record is a JSON object, so we write as-is | ||
buffer.WriteString(string(queryResponse.Value)) | ||
buffer.WriteString("}") | ||
bArrayMemberAlreadyWritten = true | ||
} | ||
buffer.WriteString("]") | ||
|
||
fmt.Printf("- queryAllCars:\n%s\n", buffer.String()) | ||
|
||
return shim.Success(buffer.Bytes()) | ||
} | ||
|
||
func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | ||
|
||
if len(args) != 2 { | ||
return shim.Error("Incorrect number of arguments. Expecting 2") | ||
} | ||
|
||
carAsBytes, _ := APIstub.GetState(args[0]) | ||
car := Car{} | ||
|
||
json.Unmarshal(carAsBytes, &car) | ||
car.Owner = args[1] | ||
|
||
carAsBytes, _ = json.Marshal(car) | ||
APIstub.PutState(args[0], carAsBytes) | ||
|
||
return shim.Success(nil) | ||
} | ||
|
||
// The main function is only relevant in unit test mode. Only included here for completeness. | ||
func main() { | ||
|
||
// Create a new Smart Contract | ||
err := shim.Start(new(SmartContract)) | ||
if err != nil { | ||
fmt.Printf("Error creating new Smart Contract: %s", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
'use strict'; | ||
|
||
/* | ||
* Chaincode Invoke | ||
*/ | ||
|
||
var hfc = require('fabric-client'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
|
||
var options = { | ||
wallet_path: path.join(__dirname, './network/creds'), | ||
user_id: 'PeerAdmin', | ||
channel_id: 'mychannel', | ||
chaincode_id: 'fabcar', | ||
peer_url: 'grpc://localhost:7051', | ||
event_url: 'grpc://localhost:7053', | ||
orderer_url: 'grpc://localhost:7050' | ||
}; | ||
|
||
var channel = {}; | ||
var client = null; | ||
var targets = []; | ||
var tx_id = null; | ||
Promise.resolve().then(() => { | ||
console.log("Create a client and set the wallet location"); | ||
client = new hfc(); | ||
return hfc.newDefaultKeyValueStore({ path: options.wallet_path }); | ||
}).then((wallet) => { | ||
console.log("Set wallet path, and associate user ", options.user_id, " with application"); | ||
client.setStateStore(wallet); | ||
return client.getUserContext(options.user_id, true); | ||
}).then((user) => { | ||
console.log("Check user is enrolled, and set a query URL in the network"); | ||
if (user === undefined || user.isEnrolled() === false) { | ||
console.error("User not defined, or not enrolled - error"); | ||
} | ||
channel = client.newChannel(options.channel_id); | ||
var peerObj = client.newPeer(options.peer_url); | ||
channel.addPeer(peerObj); | ||
channel.addOrderer(client.newOrderer(options.orderer_url)); | ||
targets.push(peerObj); | ||
return; | ||
}).then(() => { | ||
//console.log("send Invoke with function name :"+fcn); | ||
tx_id = client.newTransactionID(); | ||
console.log("Assigning transaction_id: ", tx_id._transaction_id); | ||
// createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'], | ||
// changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'], | ||
// send proposal to endorser | ||
var request = { | ||
targets: targets, | ||
chaincodeId: options.chaincode_id, | ||
fcn: '', | ||
args: [''], | ||
chainId: options.channel_id, | ||
txId: tx_id | ||
}; | ||
return channel.sendTransactionProposal(request); | ||
}).then((results) => { | ||
var proposalResponses = results[0]; | ||
var proposal = results[1]; | ||
var header = results[2]; | ||
let isProposalGood = false; | ||
if (proposalResponses && proposalResponses[0].response && | ||
proposalResponses[0].response.status === 200) { | ||
isProposalGood = true; | ||
console.log('transaction proposal was good'); | ||
} else { | ||
console.error('transaction proposal was bad'); | ||
} | ||
if (isProposalGood) { | ||
console.log(util.format( | ||
'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s', | ||
proposalResponses[0].response.status, proposalResponses[0].response.message, | ||
proposalResponses[0].response.payload, proposalResponses[0].endorsement | ||
.signature)); | ||
var request = { | ||
proposalResponses: proposalResponses, | ||
proposal: proposal, | ||
header: header | ||
}; | ||
// set the transaction listener and set a timeout of 30sec | ||
// if the transaction did not get committed within the timeout period, | ||
// fail the test | ||
var transactionID = tx_id.getTransactionID(); | ||
var eventPromises = []; | ||
let eh = client.newEventHub(); | ||
eh.setPeerAddr(options.event_url); | ||
eh.connect(); | ||
|
||
let txPromise = new Promise((resolve, reject) => { | ||
let handle = setTimeout(() => { | ||
eh.disconnect(); | ||
reject(); | ||
}, 30000); | ||
|
||
eh.registerTxEvent(transactionID, (tx, code) => { | ||
clearTimeout(handle); | ||
eh.unregisterTxEvent(transactionID); | ||
eh.disconnect(); | ||
|
||
if (code !== 'VALID') { | ||
console.error( | ||
'The transaction was invalid, code = ' + code); | ||
reject(); | ||
} else { | ||
console.log( | ||
'The transaction has been committed on peer ' + | ||
eh._ep._endpoint.addr); | ||
resolve(); | ||
} | ||
}); | ||
}); | ||
eventPromises.push(txPromise); | ||
var sendPromise = channel.sendTransaction(request); | ||
return Promise.all([sendPromise].concat(eventPromises)).then((results) => { | ||
console.log(' event promise all complete and testing complete'); | ||
return results[0]; // the first returned value is from the 'sendPromise' which is from the 'sendTransaction()' call | ||
}).catch((err) => { | ||
console.error( | ||
'Failed to send transaction and get notifications within the timeout period.' | ||
); | ||
return 'Failed to send transaction and get notifications within the timeout period.'; | ||
}); | ||
} else { | ||
console.error( | ||
'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...' | ||
); | ||
return 'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'; | ||
} | ||
}, (err) => { | ||
console.error('Failed to send proposal due to error: ' + err.stack ? err.stack : | ||
err); | ||
return 'Failed to send proposal due to error: ' + err.stack ? err.stack : | ||
err; | ||
}).then((response) => { | ||
if (response.status === 'SUCCESS') { | ||
console.log('Successfully sent transaction to the orderer.'); | ||
return tx_id.getTransactionID(); | ||
} else { | ||
console.error('Failed to order the transaction. Error code: ' + response.status); | ||
return 'Failed to order the transaction. Error code: ' + response.status; | ||
} | ||
}, (err) => { | ||
console.error('Failed to send transaction due to error: ' + err.stack ? err | ||
.stack : err); | ||
return 'Failed to send transaction due to error: ' + err.stack ? err.stack : | ||
err; | ||
}); |
5 changes: 5 additions & 0 deletions
5
fabcar/network/creds/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9-priv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
-----BEGIN PRIVATE KEY----- | ||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgS0L+WeTBa4vdUW4j | ||
rogLu8JmLSjda0YcA2TWOfaR+8yhRANCAAQO41JsWQE2pt2UZ/DBdIcpa/inDZ4U | ||
54P5VcIdXgISsEqdRcGLBz+cvvrpTNedaeyNRSndk5LMIJ/npw2Qua/p | ||
-----END PRIVATE KEY----- |
4 changes: 4 additions & 0 deletions
4
fabcar/network/creds/9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9-pub
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-----BEGIN PUBLIC KEY----- | ||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDuNSbFkBNqbdlGfwwXSHKWv4pw2e | ||
FOeD+VXCHV4CErBKnUXBiwc/nL766UzXnWnsjUUp3ZOSzCCf56cNkLmv6Q== | ||
-----END PUBLIC KEY----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"name":"PeerAdmin","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"9022d671ceedbb24af3ea69b5a8136cc64203df6b9920e26f48123fcfcb1d2e9","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICKjCCAdGgAwIBAgIQIVQ6HvVnJP1qZ5YKfh50hzAKBggqhkjOPQQDAjBwMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEZMBcGA1UEAxMQb3Jn\nMS5leGFtcGxlLmNvbTAeFw0xNzA0MjIxMjAyNTZaFw0yNzA0MjAxMjAyNTZaMFsx\nCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g\nRnJhbmNpc2NvMR8wHQYDVQQDDBZBZG1pbkBvcmcxLmV4YW1wbGUuY29tMFkwEwYH\nKoZIzj0CAQYIKoZIzj0DAQcDQgAEDuNSbFkBNqbdlGfwwXSHKWv4pw2eFOeD+VXC\nHV4CErBKnUXBiwc/nL766UzXnWnsjUUp3ZOSzCCf56cNkLmv6aNiMGAwDgYDVR0P\nAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKwYD\nVR0jBCQwIoAgoi2vNWsqq1eS6lPjX2b8zvHX8aorOiuS2/v5akSOomowCgYIKoZI\nzj0EAwIDRwAwRAIgbEqKoKrFuYQG0ndiX7dT7GKGlF17Skf8DYil9cqbp00CID5T\nURQPp0/vJ3tldK0z9xjFvsSecj8aqnDvZvGz07/v\n-----END CERTIFICATE-----\n"}}} |
5 changes: 5 additions & 0 deletions
5
...ations/example.com/ca/eaade59087c6d97fcf350e94f37ad9f2c692bb66f182148ce58940de70ade9ce_sk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
-----BEGIN PRIVATE KEY----- | ||
MIGHAgEBMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgMOKUs/EytOuKG/kW | ||
qZ8OHBb1aJ4zodJVqYWwcpH5FluhRANCAARD2rvgyAmhn8hpu82kAjX3QUg2iqCU | ||
PEe1Q5CzD5MVv/dK5wrRgkcoMhJLe4HPxYbjV3rodm5Pwi5m3zMGkqNQ | ||
-----END PRIVATE KEY----- |
14 changes: 14 additions & 0 deletions
14
fabcar/network/crypto-config/ordererOrganizations/example.com/ca/example.com-cert.pem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIICNDCCAdqgAwIBAgIRAIBOtq8vZiC0+uLSi2MIS4swCgYIKoZIzj0EAwIwZjEL | ||
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG | ||
cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRQwEgYDVQQDEwtleGFtcGxl | ||
LmNvbTAeFw0xNzA0MjIxMjAyNTZaFw0yNzA0MjAxMjAyNTZaMGYxCzAJBgNVBAYT | ||
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv | ||
MRQwEgYDVQQKEwtleGFtcGxlLmNvbTEUMBIGA1UEAxMLZXhhbXBsZS5jb20wWTAT | ||
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARD2rvgyAmhn8hpu82kAjX3QUg2iqCUPEe1 | ||
Q5CzD5MVv/dK5wrRgkcoMhJLe4HPxYbjV3rodm5Pwi5m3zMGkqNQo2kwZzAOBgNV | ||
HQ8BAf8EBAMCAaYwGQYDVR0lBBIwEAYEVR0lAAYIKwYBBQUHAwEwDwYDVR0TAQH/ | ||
BAUwAwEB/zApBgNVHQ4EIgQg6q3lkIfG2X/PNQ6U83rZ8saSu2bxghSM5YlA3nCt | ||
6c4wCgYIKoZIzj0EAwIDSAAwRQIhAL5Lgy7jZ2W74L6i0B23a3JD0W8TSYlTcqXb | ||
RMSXlLIoAiB2glBl0wM/ITn5+tnHOnq2wrIGuYIiNbLK5oq2zf+gtA== | ||
-----END CERTIFICATE----- |
Oops, something went wrong.