Fix while loop bug

pull/108/head
Baohua Yang 2017-11-23 17:17:29 +08:00
parent 504a7ab857
commit 466e37cad0
19 changed files with 1109 additions and 75 deletions

View File

@ -24,7 +24,9 @@ all:
sleep 1
make ready
make lscc qscc
make lscc # test lscc operations
make qscc # test qscc operations
make fetch_blocks # fetch block files
make stop clean
init: # initialize the fabric network
@ -99,18 +101,28 @@ test_cc_peer0: # test single peer
docker exec -it fabric-cli bash -c "cd /tmp; bash scripts/test_cc_peer0.sh"
qscc: # test qscc queries
@echo "Test QSCC query"
docker exec -it fabric-cli bash -c "cd /tmp; bash scripts/test_qscc.sh"
lscc: # test lscc quries
@echo "Test LSCC query"
docker exec -it fabric-cli bash -c "cd /tmp; bash scripts/test_lscc.sh"
fetch_blocks: # test channel fetch
# FIXME: docker doesn't support wildcard in cp right now
fetch_blocks: # test fetching channel blocks fetch
@echo "Test fetching block files"
docker exec -it fabric-cli bash -c "cd /tmp; bash scripts/test_fetch.sh"
docker cp fabric-cli:/tmp/block_0.block kafka/channel-artifacts/
docker cp fabric-cli:/tmp/block_1.block kafka/channel-artifacts/
docker cp fabric-cli:/tmp/block_2.block kafka/channel-artifacts/
docker cp fabric-cli:/tmp/block_3.block kafka/channel-artifacts/
if [ "$(HLF_MODE)" = "kafka" ]; then \
docker cp fabric-cli:/tmp/block_0.block kafka/channel-artifacts; \
docker cp fabric-cli:/tmp/block_1.block kafka/channel-artifacts; \
docker cp fabric-cli:/tmp/block_2.block kafka/channel-artifacts; \
docker cp fabric-cli:/tmp/block_3.block kafka/channel-artifacts; \
else \
docker cp fabric-cli:/tmp/block_0.block solo/channel-artifacts; \
docker cp fabric-cli:/tmp/block_1.block solo/channel-artifacts; \
docker cp fabric-cli:/tmp/block_2.block solo/channel-artifacts; \
docker cp fabric-cli:/tmp/block_3.block solo/channel-artifacts; \
fi
################## Env setup related, no need to see usually ################
@ -158,7 +170,7 @@ gen_solo: # generate solo artifacts
gen_kafka: # generate kafka artifacts
cd kafka && bash gen_artifacts.sh
configtxlator: # run configtxlator
test_configtxlator: # Test change config using configtxlator
cd kafka && bash run_configtxlator.sh
download: # download required images
@ -168,7 +180,6 @@ download: # download required images
docker pull hyperledger/fabric-baseos:x86_64-0.4.2
docker tag yeasy/hyperledger-fabric:latest hyperledger/fabric-ccenv:x86_64-1.1.0
################## chaincode dev mode ################
chaincode_init: # start chaincode in dev mode and do install/instantiate
@echo "Install and instantiate cc example02 on the fabric dev network"

View File

@ -82,7 +82,7 @@ You should see result like the following if the initialization is successful.
==========initialize businesschannel==========
==============================================
Channel name : businesschannel
Channel name: businesschannel
Creating channel...
...

View File

@ -0,0 +1,81 @@
# https://github.com/yeasy/docker-compose-files/tree/master/hyperledger
# This compose file will start a Hyperledger Fabric 1.0 MVE, including
# * 2 ca (not in use now)
# * 1 orderer
# * 4 peers in 2 orgs
# * cli for testing
# * blockchain-explorer
version: '2.0'
services:
# ca.org1.example.com:
# extends:
# file: base-solo.yaml
# service: ca.org1.example.com
# ca.org2.example.com:
# extends:
# file: base-solo.yaml
# service: ca.org2.example.com
cli:
extends:
file: base-solo.yaml
service: cli
orderer.example.com: # There can be multiple orderers
extends:
file: base-solo.yaml
service: orderer.example.com
peer0.org1.example.com:
extends:
file: base-solo.yaml
service: peer0.org1.example.com
peer1.org1.example.com:
extends:
file: base-solo.yaml
service: peer1.org1.example.com
peer0.org2.example.com:
extends:
file: base-solo.yaml
service: peer0.org2.example.com
peer1.org2.example.com:
extends:
file: base-solo.yaml
service: peer1.org2.example.com
explorer:
image: yeasy/blockchain-explorer:latest
container_name: explorer
hostname: explorer
depends_on:
- mysql
volumes:
- ./config.json:/blockchain-explorer/config.json
- ./solo/crypto-config:/blockchain-explorer/first-network/crypto-config
ports:
- "8080:8080" # HTTP port
command: bash -c 'node main.js'
mysql: # mysql service
image: mysql:8.0
container_name: mysql
hostname: mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=fabricexplorer
volumes:
- ./fabricexplorer.sql:/docker-entrypoint-initdb.d/fabricexplorer.sql
expose:
- "3306"
#command: bash -c 'mysqld; sleep 1; mysql -uroot -proot < /tmp/fabricexplorer.sql; while true; do sleep 20171117; done'
#networks:
# default:
# external:
# name: hyperledger_fabric

View File

@ -48,32 +48,6 @@ services:
file: base-solo.yaml
service: peer1.org2.example.com
explorer:
image: yeasy/blockchain-explorer:latest
container_name: explorer
hostname: explorer
depends_on:
- mysql
volumes:
- ./config.json:/blockchain-explorer/config.json
- ./solo/crypto-config:/blockchain-explorer/first-network/crypto-config
ports:
- "8080:8080" # HTTP port
command: bash -c 'node main.js'
mysql: # mysql service
image: mysql:8.0
container_name: mysql
hostname: mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=fabricexplorer
volumes:
- ./fabricexplorer.sql:/docker-entrypoint-initdb.d/fabricexplorer.sql
expose:
- "3306"
#command: bash -c 'mysqld; sleep 1; mysql -uroot -proot < /tmp/fabricexplorer.sql; while true; do sleep 20171117; done'
#networks:
# default:
# external:

View File

@ -14,7 +14,7 @@
################################################################################
Profiles:
TwoOrgsOrdererGenesis:
TwoOrgsOrdererGenesis: # Used to generate genesis block for system channel
Orderer:
<<: *OrdererDefaults
Organizations:
@ -24,7 +24,8 @@ Profiles:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
TwoOrgsChannel: # used for application channel
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
@ -32,6 +33,15 @@ Profiles:
- *Org1
- *Org2
ThreeOrgsChannel: # used for application channel
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
- *Org3
################################################################################
#
# Section: Organizations
@ -89,6 +99,23 @@ Organizations:
- Host: peer0.org2.example.com
Port: 7051
- &Org3
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org3MSP
# ID to load the MSP definition as
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org3.example.com/msp
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org3.example.com
Port: 7051
################################################################################
#
# SECTION: Orderer

View File

@ -1,9 +1,11 @@
#!/bin/bash
# Demo to use configtxlator to modify orderer config
# More details about configtxlator, see http://hlf.readthedocs.io/en/latest/configtxlator.html
CONFIGTXLATOR_IMG=yeasy/hyperledger-fabric:latest
CONFIGTXLATOR_CONTAINER=configtxlator
# Must run `make gen_kafka` to generate artifacts files first
ARTIFACTS_DIR=channel-artifacts
ORDERER_GENESIS_BLOCK=${ARTIFACTS_DIR}/orderer.genesis.block

View File

@ -20,7 +20,7 @@ elif [ -f scripts/variables.sh ]; then
source scripts/variables.sh
fi
# Verify $1 is not 0, then output error msg $2
# Verify $1 is not 0, then output error msg $2 and exit
verifyResult () {
if [ $1 -ne 0 ] ; then
echo_b "$2"
@ -107,23 +107,25 @@ channelCreateAction(){
}
# Use peer0/org1 to create a channel
# channelCreate channel_name
channelCreate() {
local channel=$1
echo_b "=== Create Channel ${channel} === "
local counter=0
local res=1
echo_b "=== Create Channel ${channel}\" === "
setGlobals 0
while [ $counter -lt ${MAX_RETRY} -a ${res} -ne 0 ]; do
res=$(channelCreateAction ${channel})
channelCreateAction ${channel}
local res=$?
while [ ${counter} -lt ${MAX_RETRY} -a ${res} -ne 0 ]; do
echo_b "Failed to create channel $channel, retry after 3s"
sleep 3
channelCreateAction ${channel}
res=$?
let counter=${counter}+1
#COUNTER=` expr $COUNTER + 1`
echo_b "Fail to create channel ${channel}, Retry after 3 seconds"
sleep 3
done
cat log.txt
verifyResult ${res} "Channel creation failed"
echo_g "=== Channel ${channel} is created successfully === "
echo
verifyResult ${res} "Channel ${channel} creation failed"
echo_g "=== Channel ${channel} is created. === "
}
# called by channelJoinWithRetry
@ -138,22 +140,24 @@ channelJoinWithRetry () {
local channel=$1
local peer=$2
local counter=0
local res=1
channelJoinAction ${channel}
local res=$?
while [ ${counter} -lt ${MAX_RETRY} -a ${res} -ne 0 ]; do
res=$(channelJoinAction ${channel})
let counter=$counter+1
echo_b "peer${peer} failed to join the channel, Retry after 2 seconds"
echo_b "peer${peer} failed to join channel ${channel}, retry after 2s"
sleep 2
channelJoinAction ${channel}
res=$?
let counter=${counter}+1
done
cat log.txt
verifyResult $res "After $MAX_RETRY attempts, peer${peer} has failed to Join the Channel"
verifyResult ${res} "After $MAX_RETRY attempts, peer${peer} failed to Join the Channel"
}
# Join given (by default all) peers into the channel
# channelJoin 0 1 2 3
channelJoin () {
local channel=$1
echo_b "=== Join peers into the channel ${channel} === "
echo_b "=== Join peers into channel ${channel} === "
peers_to_join=$(seq 0 3)
if [ $# -gt 1 ]; then
peers_to_join=${@:2}
@ -161,7 +165,7 @@ channelJoin () {
for i in $peers_to_join; do
setGlobals $i
channelJoinWithRetry ${channel} $i
echo_g "=== peer$i joined into the channel \"${channel}\" === "
echo_g "=== peer$i joined into channel ${channel} === "
sleep 1
done
}
@ -191,7 +195,7 @@ updateAnchorPeers() {
res=$?
cat log.txt
verifyResult $res "Anchor peer update failed"
echo_g "=== Anchor peers for org \"$CORE_PEER_LOCALMSPID\" on ${channel} is updated successfully === "
echo_g "=== Anchor peers for org \"$CORE_PEER_LOCALMSPID\" on ${channel} is updated. === "
sleep 2
}
@ -384,19 +388,19 @@ chaincodeUpgrade () {
channelFetch () {
local channel=$1
local peer=$2
local blockNum=$3
echo_b "=== Fetch block $blockNum on peer$peer in channel '$channel' === "
local num=$3
echo_b "=== Fetch block $num on peer$peer in channel '$channel' === "
setGlobals $peer
# while 'peer chaincode' command can get the orderer endpoint from the peer (if join was successful),
# lets supply it directly as we know it using the "-o" option
if [ -z "${CORE_PEER_TLS_ENABLED}" -o "${CORE_PEER_TLS_ENABLED}" = "false" ]; then
peer channel fetch $blockNum block_${blockNum}.block \
peer channel fetch $num ${channel}_block_${num}.block \
-o ${ORDERER_URL} \
-c ${channel} \
>&log.txt
else
peer channel fetch $blockNum block_${blockNum}.block \
peer channel fetch $num block_${num}.block \
-o ${ORDERER_URL} \
-c ${channel} \
--tls \

View File

@ -14,7 +14,7 @@ echo " ==========initialize businesschannel========== "
echo " ============================================== "
echo
echo_b "Channel name : "$CHANNEL_NAME
echo_b "Channel name: "$CHANNEL_NAME
## Create channel
echo_b "Creating channel..."

View File

@ -7,7 +7,7 @@ elif [ -f scripts/func.sh ]; then
source scripts/func.sh
fi
echo_b "Channel name : "$CHANNEL_NAME
echo_b "Channel name: "$CHANNEL_NAME
#Query on chaincode on Peer0/Org1
echo_b "Querying chaincode on peer 3..."

View File

@ -18,31 +18,31 @@ echo_b "LSCC testing"
setGlobals 0
echo_b "Get id"
echo_b "LSCC Get id"
peer chaincode query \
-C "${CHANNEL_NAME}" \
-n lscc \
-c '{"Args":["getid","'${CHANNEL_NAME}'", "mycc"]}'
-c '{"Args":["getid","'${CHANNEL_NAME}'", "'$CC_NAME'"]}'
echo_b "Get cc ChaincodeDeploymentSpec"
echo_b "LSCC Get cc ChaincodeDeploymentSpec"
peer chaincode query \
-C "${CHANNEL_NAME}" \
-n lscc \
-c '{"Args":["getdepspec","'${CHANNEL_NAME}'", "mycc"]}'
-c '{"Args":["getdepspec","'${CHANNEL_NAME}'", "'$CC_NAME'"]}'
echo_b "Get cc bytes"
echo_b "LSCC Get cc bytes"
peer chaincode query \
-C "${CHANNEL_NAME}" \
-n lscc \
-c '{"Args":["getccdata","'${CHANNEL_NAME}'", "mycc"]}'
-c '{"Args":["getccdata","'${CHANNEL_NAME}'", "'$CC_NAME'"]}'
echo_b "Get all chaincodes installed on the channel"
echo_b "LSCC Get all chaincodes installed on the channel"
peer chaincode query \
-C "${CHANNEL_NAME}" \
-n lscc \
-c '{"Args":["getinstalledchaincodes"]}'
echo_b "Get all chaincodes instantiated on the channel"
echo_b "LSCC Get all chaincodes instantiated on the channel"
peer chaincode query \
-C "${CHANNEL_NAME}" \
-n lscc \

View File

@ -9,6 +9,8 @@ elif [ -f scripts/func.sh ]; then
source scripts/func.sh
fi
echo_b "QSCC testing"
setGlobals 0
echo_b "QSCC GetChainInfo"
@ -23,4 +25,4 @@ peer chaincode query \
-n qscc \
-c '{"Args":["GetBlockByNumber","'${CHANNEL_NAME}'","2"]}'
echo_g "Qscc testing done!"
echo_g "QSCC testing done!"

View File

@ -19,7 +19,6 @@ ORG2_PEER0_TLS_ROOTCERT=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypt
ORG1_ADMIN_MSP=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
ORG2_ADMIN_MSP=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
# Node URLS
ORDERER_URL="orderer.example.com:7050"
ORG1_PEER0_URL="peer0.org1.example.com:7051"

View File

@ -0,0 +1,871 @@
package main
import (
//"bytes"
"encoding/json"
"fmt"
//"strconv"
//"strings"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
//=============================================================================================================================================================================
// Structs
//=============================================================================================================================================================================
type SimpleChaincode struct {
}
type user struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
userID string `json:"userid"`
DOB string `json:"dob"`
Email string `json:"email"`
Mobile string `json:"mobile"`
Class string `json:"class"`
ObjectType string `json:"docType"`
}
type RawMaterial struct {
RMID string `json:"rmid"`
Item string `json:"item"`
Creator string `json:"creator"`
Current_Owner string `json:"currentowner"`
ClaimTags string `json:"claimtags"`
Location string `json:"location"`
Date string `json:"date"`
CertID string `json:"certid"`
ObjectType string `json:"docType"`
// add quality
}
type FinishedGood struct {
FPID string `json:"fpid"`
Name string `json:"name"`
Creator string `json:"creator"`
Current_Owner string `json:"currentowner"`
Ingredients string `json:"ingredients"`
//Previous_Owner string `json:"previousowner"`
Certificates string `json:"certificates"`
ClaimTags string `json:"claimtags"`
Location string `json:"location"`
Date string `json:"date"`
CertID string `json:"certid"`
ObjectType string `json:"docType"`
}
type PurchaseOrder struct{
PurchaseOrderID string `json:"purchaseorderid"`
Customer string `json:"customer"`
Vendor string `json:"vendor"`
ProductID string `json:"productid"`
Price string `json:"price"`
Date string `json:"date"`
// Status string `json:"status"`
ObjectType string `json:"docType"`
}
type Certificate struct {
CertID string `json:"certid"`
OrgName string `json:"orgname"`
Supplier string `json:"supplier"`
Status string `json:"status"`
Date_effective string `json:"dateeffective"`
Certifier string `json:"certifier"`
ProductList string `json:"productlist"`
OpDetails string `json:"opdetails"`
Location string `json:"location"`
ExpiryDate string `json:"expdate"`
ObjectType string `json:"docType"`
}
// =============================================================================================================================================================
// MAIN FUNCTIONS
// ==============================================================================================================================================================
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
// Init initializes chaincode
// ===========================
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
var err error
err = stub.PutState("status", []byte("Blockchain online")) //write the variable into the chaincode state
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Invoke - Our entry point for Invocations
// ========================================
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
fmt.Println("invoke is running " + function)
// Handle different functions
if function == "Register" { //create a new user
return t.Register(stub, args)
} else if function == "RegisterRM" {
return t.RegisterRM(stub, args)
} else if function == "RegisterFP" {
return t.RegisterFP(stub, args)
} else if function == "makePurchaseOrder" {
return t.makePurchaseOrder(stub, args)
} else if function == "replyPurchaseOrder" {
return t.replyPurchaseOrder(stub, args)
} else if function == "transferRM" {
return t.transferRM(stub, args)
} else if function == "transferFP" {
return t.transferFP(stub, args)
} else if function == "awardCert" {
return t.awardCert(stub, args)
} else if function == "requestCert" {
return t.requestCert(stub, args)
} else if function == "read" {
return t.read(stub, args)
} else if function == "getHistory" {
return t.getHistory(stub, args)
} else if function == "modifyCert" {
return t.modifyCert(stub, args)
} else if function == "getHistoryFG" {
return t.getHistoryFG(stub, args)
}
fmt.Println("invoke did not find func: " + function) //error
return shim.Error("Received unknown function invocation")
}
//============================================================================================================================================================================
// REGISTRATION CODE BELOW
//=============================================================================================================================================================================
func (t *SimpleChaincode) Register(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// Firstname string `json:"firstname"` 0
// Lastname string `json:"lastname"` 1
// userID string `json:"userid"` 2
// DOB string `json:"dob"` 3
// Email string `json:"email"` 4
// Mobile string `json:"mobile"` 5
// Class string `json:"class"` 6
if len(args) != 7 {
return shim.Error("Incorrect number of arguments. Expecting 7")
}
// ==== Input sanitation ====
fname := args[0]
lname := args[1]
uid := args[2]
userdob := args[3]
useremail := args[4]
usermobile := args[5]
userclass := args[6]
// ==== Check if user already exists ====
fnameAsBytes, err := stub.GetState(uid) //Change this to uid not fname
if err != nil {
return shim.Error("Failed to get user: " + err.Error())
} else if fnameAsBytes != nil {
fmt.Println("This user already exists: " + fname)
return shim.Error("This user already exists: " + fname)
}
// ==== Create user object and marshal to JSON ====
objectType := "user"
user := &user{fname, lname, uid, userdob, useremail, usermobile, userclass, objectType}
userJSONasBytes, err := json.Marshal(user)
if err != nil {
return shim.Error(err.Error())
}
// === Save user to state ===
err = stub.PutState(uid, userJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
//this should be uid based range query, needs to be tested
// Index
indexName := "uid~fname"
uidIndexKey, err := stub.CreateCompositeKey(indexName, []string{user.userID, user.Firstname})
if err != nil {
return shim.Error(err.Error())
}
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the user.
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
value := []byte{0x00}
stub.PutState(uidIndexKey, value)
// ==== user saved and indexed. Return success ====
fmt.Println("- end init user")
return shim.Success(nil)
}
func (t *SimpleChaincode) RegisterRM(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// RMID string `json:"rmid"` 0
// Item string `json:"item"` 1
// Creator string `json:"creator"` 2
// Current_Owner string `json:"currentowner"` 3
// ClaimTags string `json:"claimtags"` 4
// Location string `json:"location"` 5
// Date string `json:"date"` 6
// CertID string `json:"certid"` 7
// ObjectType string `json:"docType"` 8
// ==== Input sanitation ====
rawid := args[0]
item := args[1]
originalcreator := args[2]
cowner := args[3]
claimtags := args[4]
loc := args[5]
dates := args[6]
userclass := args[7]
// ==== Check if RM already exists ====
rawidAsBytes, err := stub.GetState(rawid)
if err != nil {
return shim.Error("Failed to get user: " + err.Error())
} else if rawidAsBytes != nil {
fmt.Println("This user already exists: " + rawid)
return shim.Error("This user already exists: " + rawid)
}
// ==== Create RM object and marshal to JSON ====
objectType := "RawMaterial"
RawMaterial := &RawMaterial{rawid, item, originalcreator, cowner, claimtags, loc, dates, userclass, objectType}
RawMaterialJSONasBytes, err := json.Marshal(RawMaterial)
if err != nil {
return shim.Error(err.Error())
}
// === Save RM to state ===
err = stub.PutState(rawid, RawMaterialJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
// Index
indexName := "rawid~cowner"
rawidIndexKey, err := stub.CreateCompositeKey(indexName, []string{RawMaterial.RMID, RawMaterial.Current_Owner})
if err != nil {
return shim.Error(err.Error())
}
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the user.
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
value := []byte{0x00}
stub.PutState(rawidIndexKey, value)
// ==== RM saved and indexed. Return success ====
fmt.Println("- end init user")
return shim.Success(nil)
}
func (t *SimpleChaincode) RegisterFP(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// ObjectType string `json:"docType"` 0
// FPID string `json:"fpid"` 1
// Name string `json:"name"` 2
// Creator string `json:"creator"` 3
// Current_Owner string `json:"currentowner"` 4
// Ingredients string `json:"ingredients"` 5
////Previous_Owner string `json:"previousowner"` 6
// Certificates string `json:"certificates"` 7
// ClaimTags string `json:"claimtags"` 8
// Location string `json:"location"` 9
// Date string `json:"date"` 10
// CertID string `json:"certid"` 11
// ==== Input sanitation ====
fpid_i := args[0]
name_i := args[1]
originalcreator_i := args[2]
cowner_i := args[3]
ingredients_i := args[4]
certificates_i := args[5]
claimtags_i := args[6]
loc_i := args[7]
dates_i := args[8]
certid_i := args[9]
// ==== Check if FP already exists ====
fpid_iAsBytes, err := stub.GetState(fpid_i)
if err != nil {
return shim.Error("Failed to get user: " + err.Error())
} else if fpid_iAsBytes != nil {
fmt.Println("This user already exists: " + fpid_i)
return shim.Error("This user already exists: " + fpid_i)
}
// ==== Create object and marshal to JSON ====
objectType := "FinishedGood"
FinishedGood := &FinishedGood{fpid_i, name_i, originalcreator_i, cowner_i, ingredients_i, certificates_i, claimtags_i, loc_i, dates_i, certid_i, objectType}
FinishedGoodJSONasBytes, err := json.Marshal(FinishedGood)
if err != nil {
return shim.Error(err.Error())
}
// === Save FP to state ===
err = stub.PutState(fpid_i, FinishedGoodJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
//Index
indexName := "fpid_i~cowner"
fpiIndexKey, err := stub.CreateCompositeKey(indexName, []string{FinishedGood.FPID, FinishedGood.Current_Owner})
if err != nil {
return shim.Error(err.Error())
}
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the user.
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
value := []byte{0x00}
stub.PutState(fpiIndexKey, value)
// ==== FP saved and indexed. Return success ====
fmt.Println("- end init user")
return shim.Success(nil)
}
//=============================================================================================================================================================================
// Purchase Orders
//=============================================================================================================================================================================
func (t *SimpleChaincode) makePurchaseOrder(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// PurchaseOrderID string `json:"purchaseorderid"` 0
// Customer string `json:"customer"` 1
// Vendor string `json:"vendor"` 2
// ProductID string `json:"productid"` 3
// Price string `json:"price"` 4
// Date string `json:"date"` 5
// Status string `json:"status"` Pending
// ObjectType string `json:"docType"` PurchaseOrder
// ==== Input sanitation ====
purchid := args[0]
cust := args[1]
vend := args[2]
prodid := args[3]
price:= args[4]
dat := args[5]
//stat := "Pending"
// ==== Check if order already exists ====
purchAsBytes, err := stub.GetState(purchid)
if err != nil {
return shim.Error("Failed to get product: " + err.Error())
} else if purchAsBytes != nil {
fmt.Println("This product already exists: " + purchid)
return shim.Error("This product already exists: " + purchid)
}
// ==== Create object and marshal to JSON ====
objectType := "PurchaseOrder"
PurchaseOrder := &PurchaseOrder{purchid, cust, vend, prodid, price, dat, objectType}
prodJSONasBytes, err := json.Marshal(PurchaseOrder)
if err != nil {
return shim.Error(err.Error())
}
// === Save order to state ===
err = stub.PutState(purchid, prodJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
// ==== order saved and NOT indexed. Return success ====
fmt.Println("- end init user")
return shim.Success(nil)
}
func (t *SimpleChaincode) replyPurchaseOrder(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
var key, value string
var a = time.Now()
var b = a.Format("20060102150405")
key = args[0]
var body = args[2] //this will be the yes or no
value = args[1] + "-" + b +"-"+ key + " " + body
err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
//===========================================================================================================================================================================
// Transferring
//===========================================================================================================================================================================
func (t *SimpleChaincode) transferRM(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0 1
// "name", "bob"
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
prodid := args[0]
newOwner := args[1]
newLoc := args[2]
newDate := args[3]
assetAsBytes, err := stub.GetState(prodid)
if err != nil {
return shim.Error("Failed to get asset:" + err.Error())
} else if assetAsBytes == nil {
return shim.Error("Assest does not exist")
}
assetToTransfer := RawMaterial{}
err = json.Unmarshal(assetAsBytes, &assetToTransfer) //unmarshal it aka JSON.parse()
if err != nil {
return shim.Error(err.Error())
}
assetToTransfer.Current_Owner = newOwner //change the owner
assetToTransfer.Location = newLoc
assetToTransfer.Date = newDate
assetJSONasBytes, _ := json.Marshal(assetToTransfer)
err = stub.PutState(prodid, assetJSONasBytes) //rewrite the asset
if err != nil {
return shim.Error(err.Error())
}
fmt.Println("- end transferRM (success)")
return shim.Success(nil)
}
func (t *SimpleChaincode) transferFP(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0 1
// "name", "bob"
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
prodid := args[0]
newOwner := args[1]
newLoc := args[2]
newDate := args[3]
assetAsBytes, err := stub.GetState(prodid)
if err != nil {
return shim.Error("Failed to get asset:" + err.Error())
} else if assetAsBytes == nil {
return shim.Error("Assest does not exist")
}
assetToTransfer := FinishedGood{}
err = json.Unmarshal(assetAsBytes, &assetToTransfer) //unmarshal it aka JSON.parse()
if err != nil {
return shim.Error(err.Error())
}
assetToTransfer.Current_Owner = newOwner //change the owner
assetToTransfer.Location = newLoc
assetToTransfer.Date = newDate
assetJSONasBytes, _ := json.Marshal(assetToTransfer)
err = stub.PutState(prodid, assetJSONasBytes) //rewrite the asset
if err != nil {
return shim.Error(err.Error())
}
fmt.Println("- end transferRM (success)")
return shim.Success(nil)
}
//===========================================================================================================================================================================
// Certifying
//===========================================================================================================================================================================
func (t *SimpleChaincode) awardCert(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// CertID string `json:"certid"` 0
// OrgName string `json:"orgname"` 1
// Supplier string `json:"supplier"` 2
// Status string `json:"status"` 3
// Date_effective string `json:"dateeffective"` 4
// Certifier string `json:"certifier"` 5
// ProductList string `json:"productlist"` 6
// OpDetails string `json:"opdetails"` 7
// Location string `json:"location"` 8
// ExpiryDate string `json:"expdate"` 9
// ObjectType string `json:"docType"` 10
// ==== Input sanitation ====
certid := args[0]
oname := args[1]
supplier := args[2]
stat := args[3]
dateeff := args[4]
certifierorg := args[5]
prodlist := args[6]
opdet := args[7]
loc := args[8]
expdat := args[9]
// ==== Check if cert already exists ====
awardAsBytes, err := stub.GetState(certid)
if err != nil {
return shim.Error("Failed to get cert: " + err.Error())
} else if awardAsBytes != nil {
fmt.Println("This cert already exists: " + certid)
return shim.Error("This cert already exists: " + certid)
}
// ==== Create object and marshal to JSON ====
objectType := "Certificate"
Certificate := &Certificate{certid, oname, supplier, stat, dateeff, certifierorg, prodlist, opdet, loc, expdat, objectType}
CertJSONasBytes, err := json.Marshal(Certificate)
if err != nil {
return shim.Error(err.Error())
}
// === Save certificate to state ===
err = stub.PutState(certid, CertJSONasBytes)
if err != nil {
return shim.Error(err.Error())
}
// ==== certificate saved and NOT indexed. Return success ====
fmt.Println("- end init cert")
return shim.Success(nil)
}
func (t *SimpleChaincode) requestCert(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
var key, value string
//arg 0 is the certificate request id which will be UUID generated but for now just input
//arg 1 is the suppliers id who is requesting the certificate
//arg 2 is the name of the certificate
//arg 3 is the products
//arg 4 is the location
var a = time.Now()
var b = a.Format("20060102150405")
key = args[0]
var suppid = args[1]
var name = args[2]
var product = args[3]
var location = args[4]
value = key + "-" + b + " " + suppid + " " + name + " " + product + " " + location
err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
//
// This function should be used to revoke certificates but because of its open input nature can be more flexible and be used for whatever really
//
func (t *SimpleChaincode) modifyCert(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0 1
// "certid", "new status"
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
certid := args[0] // assigning first input to certid
newStatus := args[1] // assigning second input to the new status of the certificate
certAsBytes, err := stub.GetState(certid) //retrieving the certificate from the blockchain using the getstate function
if err != nil {
return shim.Error("Failed to get certificate:" + err.Error())
} else if certAsBytes == nil {
return shim.Error("Certificate does not exist")
}
certToModify := Certificate{}
err = json.Unmarshal(certAsBytes, &certToModify) //unmarshal it aka JSON.parse()
if err != nil {
return shim.Error(err.Error())
}
certToModify.Status = newStatus //change the status
certJSONasBytes, _ := json.Marshal(certToModify)
err = stub.PutState(certid, certJSONasBytes) //rewrite the asset
if err != nil {
return shim.Error(err.Error())
}
fmt.Println("- end revokeCert (success)")
return shim.Success(nil)
}
//===========================================================================================================================================================================
// Reading
//===========================================================================================================================================================================
func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return shim.Error(jsonResp)
}
//jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
//fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}
/*
func (t *SimpleChaincode) queryRMByUID(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 0
// "bob"
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
owner := args[0]
queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"RawMaterial\",\"owner\":\"%s\"}}", owner)
queryResults, err := getQueryResultForQueryString(stub, queryString)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(queryResults)
}
func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) {
fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString)
resultsIterator, err := stub.GetQueryResult(queryString)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
// buffer is a JSON array containing QueryRecords
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
// 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("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String())
return buffer.Bytes(), nil
}
*/
func (t *SimpleChaincode) getHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response {
type AuditHistory struct {
TxId string `json:"txId"`
Value RawMaterial `json:"value"`
}
var history []AuditHistory;
var rawmaterial RawMaterial
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
RMId := args[0]
fmt.Printf("- start getHistoryForMarble: %s\n", RMId)
// Get History
resultsIterator, err := stub.GetHistoryForKey(RMId)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
for resultsIterator.HasNext() {
historyData, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
var tx AuditHistory
tx.TxId = historyData.TxId //copy transaction id over
json.Unmarshal(historyData.Value, &rawmaterial) //un stringify it aka JSON.parse()
if historyData.Value == nil { //marble has been deleted
var emptyRM RawMaterial
tx.Value = emptyRM //copy nil marble
} else {
json.Unmarshal(historyData.Value, &rawmaterial) //un stringify it aka JSON.parse()
tx.Value = rawmaterial //copy marble over
}
history = append(history, tx) //add this tx to the list
}
fmt.Printf("- getHistoryForMarble returning:\n%s", history)
//change to array of bytes
historyAsBytes, _ := json.Marshal(history) //convert to array of bytes
return shim.Success(historyAsBytes)
}
func (t *SimpleChaincode) getHistoryFG(stub shim.ChaincodeStubInterface, args []string) pb.Response {
type AuditHistory struct {
TxId string `json:"txId"`
Value FinishedGood `json:"value"`
}
var history []AuditHistory;
var finishedgood FinishedGood
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
FGId := args[0]
fmt.Printf("- start getHistoryForMarble: %s\n", FGId)
// Get History
resultsIterator, err := stub.GetHistoryForKey(FGId)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
for resultsIterator.HasNext() {
historyData, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
var tx AuditHistory
tx.TxId = historyData.TxId //copy transaction id over
json.Unmarshal(historyData.Value, &finishedgood) //un stringify it aka JSON.parse()
if historyData.Value == nil { //marble has been deleted
var emptyFG FinishedGood
tx.Value = emptyFG //copy nil marble
} else {
json.Unmarshal(historyData.Value, &finishedgood) //un stringify it aka JSON.parse()
tx.Value = finishedgood //copy marble over
}
history = append(history, tx) //add this tx to the list
}
fmt.Printf("- getHistoryForMarble returning:\n%s", history)
//change to array of bytes
historyAsBytes, _ := json.Marshal(history) //convert to array of bytes
return shim.Success(historyAsBytes)
}

View File

@ -0,0 +1,62 @@
#!/bin/bash
# Demo to use configtxlator to modify orderer config
# More details about configtxlator, see http://hlf.readthedocs.io/en/latest/configtxlator.html
CONFIGTXLATOR_IMG=yeasy/hyperledger-fabric:latest
CONFIGTXLATOR_CONTAINER=configtxlator
# Must run `make gen_kafka` to generate artifacts files first
ARTIFACTS_DIR=channel-artifacts
ORDERER_GENESIS_BLOCK=${ARTIFACTS_DIR}/orderer.genesis.block
ORDERER_GENESIS_UPDATED_BLOCK=${ARTIFACTS_DIR}/orderer.genesis.updated.block
ORDERER_GENESIS_JSON=${ARTIFACTS_DIR}/orderer.genesis.json
ORDERER_GENESIS_UPDATED_JSON=${ARTIFACTS_DIR}/orderer.genesis.updated.json
MAXBATCHSIZEPATH=".data.data[0].payload.data.config.channel_group.groups.Orderer.values.BatchSize.value.max_message_count"
echo "Clean potential existing container $CONFIGTXLATOR_CONTAINER"
[ "$(docker ps -a | grep $CONFIGTXLATOR_CONTAINER)" ] && docker rm -f $CONFIGTXLATOR_CONTAINER
echo "Start configtxlator service and listen on port 7059"
docker run \
-d -it \
--name ${CONFIGTXLATOR_CONTAINER} \
-p 127.0.0.1:7059:7059 \
${CONFIGTXLATOR_IMG} \
configtxlator start
sleep 1
if [ -f ${ORDERER_GENESIS_BLOCK} ]; then
echo "Decoding the orderer genesis block to json"
curl -X POST \
--data-binary @${ORDERER_GENESIS_BLOCK} \
http://127.0.0.1:7059/protolator/decode/common.Block \
> ${ORDERER_GENESIS_JSON}
echo "Checking existing Orderer.BatchSize.max_message_count in the genesis json"
jq "$MAXBATCHSIZEPATH" channel-artifacts/orderer.genesis.json
echo "Creating new genesis json with updated Orderer.BatchSize.max_message_count"
jq "$MAXBATCHSIZEPATH=20" ${ORDERER_GENESIS_JSON} > ${ORDERER_GENESIS_UPDATED_JSON}
echo "Re-Encoding the orderer genesis json to block"
curl -X POST \
--data-binary @${ORDERER_GENESIS_UPDATED_JSON} \
http://127.0.0.1:7059/protolator/encode/common.Block \
>${ORDERER_GENESIS_UPDATED_BLOCK}
fi
for i in {0..9}
do
BLOCK_FILE=${ARTIFACTS_DIR}/block_${i}.block
if [ -f ${BLOCK_FILE} ]; then
echo "Decoding block $i of app channel to json"
curl -X POST \
--data-binary @${BLOCK_FILE} \
http://127.0.0.1:7059/protolator/decode/common.Block \
> ${BLOCK_FILE}.json
fi
done
docker rm -f $CONFIGTXLATOR_CONTAINER

View File

@ -152,7 +152,7 @@ This example will explain how to add a new org or peer with changed the basic to
##### all-in-one
We privide some instance in current directory, in this case we add a new organization `Org3` and new peer `peer0.org3.example.com`.
We provide some instance in current directory, in this case we add a new organization `Org3` and new peer `peer0.org3.example.com`.
* 1 Generate necessary config and certs
@ -180,7 +180,8 @@ $ sudo docker-compose -f docker-compose-2orgs-4peers-event.yaml up
* 3 execute auto-test
Throuth this script to test whether the network works.
Throuth this script to test whether the network works.
```bash
$ root@cli: bash ./scripts/test-5-peers.sh newchannel
```
@ -199,7 +200,7 @@ The final output may look like following
* 1 Modify config
modify configtx.yaml, crypto-cnfig.yaml and docker-compose files to adapt new change. and replace old file.
modify configtx.yaml, crypto-cnfig.yaml and docker-compose files to adapt new change. and replace old file.
* 2 Bootstrap network with `docker-compose-2orgs-4peers-event.yaml`