A Hyperledger Fabric Private Data Store in Multi Org Network, written in Go Fabric SDK
MIT License
./bin/cryptogen generate --config=./crypto-config.yaml
./bin/configtxgen -profile FourOrgsOrdererGenesis -outputBlock ./artifacts/orderer.genesis.block
./bin/configtxgen -profile FourOrgsChannel -outputCreateChannelTx ./artifacts/privateledger.channel.tx -channelID privateledger
./bin/configtxgen -profile FourOrgsChannel -outputAnchorPeersUpdate ./artifacts/Org1MSPanchors.tx -channelID privateledger -asOrg Org1MSP
./bin/configtxgen -profile FourOrgsChannel -outputAnchorPeersUpdate ./artifacts/Org2MSPanchors.tx -channelID privateledger -asOrg Org2MSP
./bin/configtxgen -profile FourOrgsChannel -outputAnchorPeersUpdate ./artifacts/Org3MSPanchors.tx -channelID privateledger -asOrg Org3MSP
./bin/configtxgen -profile FourOrgsChannel -outputAnchorPeersUpdate ./artifacts/Org4MSPanchors.tx -channelID privateledger -asOrg Org4MSP
req := resmgmt.SaveChannelRequest{
ChannelID: "multiorgledger",
ChannelConfigPath: os.os.Getenv("GOPATH")+"/multiorgledger.channel.tx",
SigningIdentities: []msp.SigningIdentity{Org1SignIdentity, Org2SignIdentity, Org3SignIdentity, Org4SignIdentity},
}
txID, err := s.Resmgmt.SaveChannel(
req, resmgmt.WithOrdererEndpoint(Orderer.OrdererID))
if err != nil || txID.TransactionID == "" {
return errors.WithMessage(err, "failed to save anchor channel for - "+s.OrgName)
}
req := resmgmt.SaveChannelRequest{
ChannelID: "multiorgledger",
ChannelConfigPath: os.os.Getenv("GOPATH")+"/", //Org1MSPanchors.tx or Org2MSPanchors.tx or Org3MSPanchors.tx or Org4MSPanchors.tx
SigningIdentities: []msp.SigningIdentity{Org1SignIdentity or Org2SignIdentity or Org3SignIdentity or Org4SignIdentity},
}
txID, err := s.Resmgmt.SaveChannel(
req, resmgmt.WithOrdererEndpoint(Orderer.OrdererID))
if err != nil || txID.TransactionID == "" {
return errors.WithMessage(err, "failed to save anchor channel for - "+s.OrgName)
}
if err := s.Resmgmt.JoinChannel(s.ChannelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint(Orderer.OrdererID)); err != nil { return errors.WithMessage(err, "failed to make admin join channel") }
resp, err := orgResmgmt.QueryChannels(resmgmt.WithTargets(peer))
if err != nil {
fmt.Println("IsJoinedChannel : failed to Query >>> "+err.Error())
return false, err
}
for _, chInfo := range resp.Channels {
fmt.Println("IsJoinedChannel : "+chInfo.ChannelId+" --- "+s.ChannelID)
if chInfo.ChannelId == s.ChannelID {
return true, nil
}
}
req := resmgmt.InstallCCRequest{
Name: s.ChaincodeId,
Path: s.ChaincodePath,
Version: s.ChainCodeVersion,
Package: ccPkg,
}
_, err = s.Resmgmt.InstallCC(req,
resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
fmt.Println("failed to install chaincode : "+err.Error())
return errors.WithMessage(err, " failed to install chaincode")
}
Policy : "OR ('Org1MSP.member')"
func newCollectionConfig(colName, policy string, reqPeerCount, maxPeerCount int32, blockToLive uint64) (*cb.CollectionConfig, error) {
p, err := cauthdsl.FromString(policy)
if err != nil {
fmt.Println("failed to create newCollectionConfig : "+err.Error())
return nil, err
}
cpc := &cb.CollectionPolicyConfig{
Payload: &cb.CollectionPolicyConfig_SignaturePolicy{
SignaturePolicy: p,
},
}
return &cb.CollectionConfig{
Payload: &cb.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &cb.StaticCollectionConfig{
Name: colName,
MemberOrgsPolicy: cpc,
RequiredPeerCount: reqPeerCount,
MaximumPeerCount: maxPeerCount,
BlockToLive: blockToLive,
},
},
}, nil
}
// The maximum no of block allocated to keep private data alive, after that the data will purge across the network
blockToLive = 1000
// Number of peer required to distribute the private data as a condition of the endorsement of the chaincode peerCount = 0 // This is the maxium number of peers allocated to a collection, if an endorsing peer goes down, then other peers are available maximumPeerCount = 3
collCfg1, _ := newCollectionConfig("collectionOrg1", "OR ('Org1MSP.member')", peerCount, maximumPeerCount, blockToLive) collCfg2, _ := newCollectionConfig("collectionOrg2", "OR ('Org2MSP.member')", peerCount, maximumPeerCount, blockToLive) collCfg3, _ := newCollectionConfig("collectionOrg3", "OR ('Org3MSP.member')", peerCount, maximumPeerCount, blockToLive) collCfg4, _ := newCollectionConfig("collectionOrg4", "OR ('Org4MSP.member')", peerCount, maximumPeerCount, blockToLive)
cfg := []*cb.CollectionConfig{ collCfg1, collCfg2, collCfg3, collCfg4}
policy = "OR ('Org1MSP.member','Org2MSP.member','Org3MSP.member','Org4MSP.member')"
ccPolicy, _ := cauthdsl.FromString(policy) // cauthdsl will convert the policy string to Policy object
resp, err := s.Resmgmt.InstantiateCC(
s.ChannelID,
resmgmt.InstantiateCCRequest{
Name: s.ChaincodeId,
Path: s.ChaincodePath,
Version: s.ChainCodeVersion,
Args: [][]byte{[]byte("init")},
Policy: ccPolicy,
CollConfig: cfg,
},resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithTargets(orgPeers[0], orgPeers[1]))
req := resmgmt.UpgradeCCRequest{
Name: s.ChaincodeId,
Version: s.ChainCodeVersion,
Path: s.ChaincodePath,
Args: [][]byte{[]byte("init")},
Policy: ccPolicy,
CollConfig: cfg,
}
resp, err := s.Resmgmt.UpgradeCC(s.ChannelID, req, resmgmt.WithRetry(retry.DefaultResMgmtOpts),resmgmt.WithTargets(orgPeers[0], orgPeers[1]))
if err != nil {
return errors.WithMessage(err, " >>>> failed to upgrade chaincode")
}
resp, err := resMgmt.QueryInstalledChaincodes(resmgmt.WithTargets(peer))
if err != nil {
return false, errors.WithMessage(err, " QueryInstalledChaincodes for peer [%s] failed : "+peer.URL())
}
found := false
for _, ccInfo := range resp.Chaincodes {
fmt.Println(" "+orgID+" found chaincode "+ccInfo.Name+" --- "+ccName+ " with version "+ ccInfo.Version+" -- "+ccVersion)
if ccInfo.Name == ccName && ccInfo.Version == ccVersion {
found = true
break
}
}
if !found {
fmt.Println(" "+orgID+" chaincode is not installed on peer "+ peer.URL())
installedOnAllPeers = false
}
chaincodeQueryResponse, err := resMgmt.QueryInstantiatedChaincodes(channelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithTargets(peer))
if err != nil {
return false, errors.WithMessage(err, " QueryInstantiatedChaincodes return error")
}
fmt.Println("\n Found instantiated chaincodes on peer "+peer.URL())
found := false
for _, chaincode := range chaincodeQueryResponse.Chaincodes {
fmt.Println(" Found instantiated chaincode Name: "+chaincode.Name+", Version: "+chaincode.Version+", Path: "+chaincode.Path+" on peer "+peer.URL())
if chaincode.Name == ccName && chaincode.Version == ccVersion {
found = true
break
}
}
if !found {
fmt.Println(" "+ccName+" chaincode is not instantiated on peer "+ peer.URL())
installedOnAllPeers = false
}
// to perform the query individual org ca client needs to be used
affl := strings.ToLower(org) + ".department1"
_, err = caClient.AddAffiliation(&caMsp.AffiliationRequest{
Name: affl,
Force: true,
CAName: caid,
})
if err != nil {
return fmt.Errorf("Failed to add affiliation for CA '%s' : %v ", caid, err)
}
fRes, err := caClient.GetAffiliation(affl)
if afRes != nil && err != nil {
fmt.Println("Affiliation Exists")
AfInfo := afRes.AffiliationInfo
CAName := afRes.CAName
fmt.Println("AfInfo : " + AfInfo.Name)
fmt.Println("CAName : " + CAName)
}
PrivateLedger - https://www.dropbox.com/s/ry1jmw0y9xliose/vendor.zip?dl=0
Chaincode - https://www.dropbox.com/s/31nnqflpqwaywoa/vendor.zip?dl=0