Skip to content

Commit

Permalink
[FAB-2899] Added create channel functionality
Browse files Browse the repository at this point in the history
Change-Id: Ib0d42f86de45f893124a076e740237b9bfa6efed
Signed-off-by: Divyank Katira <divyank.katira@securekey.com>
  • Loading branch information
d1vyank committed Mar 28, 2017
1 parent 2da9bb7 commit 9b8d2c0
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 47 deletions.
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type fabricCAConfig struct {
var myViper = viper.New()
var log = logging.MustGetLogger("fabric_sdk_go")
var format = logging.MustStringFormatter(
`%{color}%{time:15:04:05.000} [%{module}] %{level:.4s} : %{message}`,
`%{color}%{time:15:04:05.000} [%{module}] %{level:.4s} : %{color:reset} %{message}`,
)

// InitConfig ...
Expand Down
5 changes: 4 additions & 1 deletion fabric-ca-client/fabricca.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type services struct {
fabricCAClient *fabric_ca.Client
}

// RegistrationRequest defines the attributes required to register a user with the CA
type RegistrationRequest struct {
// Name is the unique name of the identity
Name string
Expand All @@ -58,6 +59,7 @@ type RegistrationRequest struct {
Attributes []Attribute
}

// RevocationRequest defines the attributes required to revoke credentials with the CA
type RevocationRequest struct {
// Name of the identity whose certificates should be revoked
// If this field is omitted, then Serial and AKI must be specified.
Expand All @@ -72,6 +74,7 @@ type RevocationRequest struct {
Reason int
}

// Attribute defines additional attributes that may be passed along during registration
type Attribute struct {
Key string
Value string
Expand Down Expand Up @@ -144,7 +147,7 @@ func (fabricCAServices *services) Register(registrar fabricclient.User,
}
// Contruct request for Fabric CA client
var attributes []api.Attribute
for i, _ := range request.Attributes {
for i := range request.Attributes {
attributes = append(attributes, api.Attribute{Name: request.
Attributes[i].Key, Value: request.Attributes[i].Value})
}
Expand Down
58 changes: 46 additions & 12 deletions fabric-client/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type Chain interface {
AddOrderer(orderer Orderer)
RemoveOrderer(orderer Orderer)
GetOrderers() []Orderer
InitializeChain() bool
CreateChannel(request CreateChannelRequest) error
UpdateChain() bool
IsReadonly() bool
QueryInfo() (*common.BlockchainInfo, error)
Expand Down Expand Up @@ -138,6 +138,12 @@ type SignedEnvelope struct {
signature []byte
}

// CreateChannelRequest requests channel creation on the network
type CreateChannelRequest struct {
// Contains channel configuration (ConfigTx)
ConfigData []byte
}

// NewChain ...
/**
* @param {string} name to identify different chain instances. The naming of chain instances
Expand Down Expand Up @@ -335,17 +341,45 @@ func (c *chain) GetOrderers() []Orderer {
return orderersArray
}

// InitializeChain ...
/**
* Calls the orderer(s) to start building the new chain, which is a combination
* of opening new message stream and connecting the list of participating peers.
* This is a long-running process. Only one of the application instances needs
* to call this method. Once the chain is successfully created, other application
* instances only need to call getChain() to obtain the information about this chain.
* @returns {bool} Whether the chain initialization process was successful.
*/
func (c *chain) InitializeChain() bool {
return false
// CreateChannel calls the an orderer to create a channel on the network
// @param {CreateChannelRequest} request Contains cofiguration information
// @returns {bool} result of the channel creation
func (c *chain) CreateChannel(request CreateChannelRequest) error {
var failureCount int
// Validate request
if request.ConfigData == nil {
return fmt.Errorf("Configuration is required to create a chanel")
}

signedEnvelope := &common.Envelope{}
err := proto.Unmarshal(request.ConfigData, signedEnvelope)
if err != nil {
return fmt.Errorf("Error unmarshalling channel configuration data: %s",
err.Error())
}
// Send request
responseMap, err := c.broadcastEnvelope(&SignedEnvelope{
signature: signedEnvelope.Signature,
Payload: signedEnvelope.Payload,
})
if err != nil {
return fmt.Errorf("Error broadcasting channel configuration: %s", err.Error())
}

for URL, resp := range responseMap {
if resp.Err != nil {
logger.Warningf("Could not broadcast to orderer: %s", URL)
failureCount++
}
}
// If all orderers returned error, the operation failed
if failureCount == len(responseMap) {
return fmt.Errorf(
"Broadcast failed: Received error from all configured orderers: %s",
responseMap[0].Err)
}

return nil
}

// UpdateChain ...
Expand Down
27 changes: 27 additions & 0 deletions fabric-client/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package fabricclient

import (
"fmt"
"io/ioutil"
"testing"

mocks "github.com/hyperledger/fabric-sdk-go/fabric-client/mocks"
Expand Down Expand Up @@ -148,6 +149,32 @@ func TestPrimaryPeer(t *testing.T) {

}

func TestCreateChain(t *testing.T) {
client := NewClient()
chain, err := NewChain("testChain", client)
if err != nil {
t.Fatalf(err.Error())
}
// Create channel without configuration
err = chain.CreateChannel(CreateChannelRequest{})
if err == nil {
t.Fatalf("Expected error creating channel without config tx")
}

configTx, err := ioutil.ReadFile("../test/fixtures/channel/testchannel.tx")
if err != nil {
t.Fatalf(err.Error())
}
// Setup mock orderer
orderer := mockOrderer{fmt.Sprintf("0.0.0.0:1234"), nil}
chain.AddOrderer(&orderer)
// Test with valid cofiguration
err = chain.CreateChannel(CreateChannelRequest{ConfigData: configTx})
if err != nil {
t.Fatalf("Did not expect error from create channel. Got error: %s", err.Error())
}
}

func TestConcurrentPeers(t *testing.T) {
const numPeers = 10000
chain, err := setupMassiveTestChain(numPeers, 0)
Expand Down
2 changes: 1 addition & 1 deletion fabric-client/orderer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestOrdererViaChain(t *testing.T) {
if err != nil {
t.Fatalf("error from NewChain %v", err)
}
orderer, err := CreateNewOrderer("localhost:7050", "", "")
orderer, _ := CreateNewOrderer("localhost:7050", "", "")
chain.AddOrderer(orderer)

orderers := chain.GetOrderers()
Expand Down
40 changes: 20 additions & 20 deletions test/fixtures/channel/configtx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Profiles:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Application:
Application:
<<: *ApplicationDefaults
Organizations:
- *Org0
Expand Down Expand Up @@ -43,9 +43,9 @@ Organizations:
# MSPDir is the filesystem path which contains the MSP configuration
#########################################################################
# FIXME: this path needs to be fixed to point to the actual location of #
# the project 'fabric-sdk-node' in the file system #
# the project 'fabric-sdk-go' in the file system #
#########################################################################
MSPDir: /fabric-sdk-node/test/fixtures/channel/crypto-config/ordererOrganizations/ordererOrg1/msp
MSPDir: /fabric-sdk-go/test/fixtures/channel/crypto-config/ordererOrganizations/ordererOrg1/msp

# BCCSP (Blockchain crypto provider): Select which crypto implementation or
# library to use
Expand All @@ -54,11 +54,11 @@ Organizations:
SW:
Hash: SHA2
Security: 256
# Location of Key Store. If this is unset, a location will
# Location of Key Store. If this is unset, a location will
# be chosen using 'MSPDir'/keystore
FileKeyStore:
KeyStore:
FileKeyStore:
KeyStore:

- &Org0
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Expand All @@ -70,9 +70,9 @@ Organizations:
# MSPDir is the filesystem path which contains the MSP configuration
#########################################################################
# FIXME: this path needs to be fixed to point to the actual location of #
# the project 'fabric-sdk-node' in the file system #
# the project 'fabric-sdk-go' in the file system #
#########################################################################
MSPDir: /fabric-sdk-node/test/fixtures/channel/crypto-config/peerOrganizations/peerOrg1/msp/
MSPDir: /fabric-sdk-go/test/fixtures/channel/crypto-config/peerOrganizations/peerOrg1/msp/

# BCCSP (Blockchain crypto provider): Select which crypto implementation or
# library to use
Expand All @@ -81,11 +81,11 @@ Organizations:
SW:
Hash: SHA2
Security: 256
# Location of Key Store. If this is unset, a location will
# Location of Key Store. If this is unset, a location will
# be chosen using 'MSPDir'/keystore
FileKeyStore:
KeyStore:
FileKeyStore:
KeyStore:

AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
Expand All @@ -106,9 +106,9 @@ Organizations:
# MSPDir is the filesystem path which contains the MSP configuration
#########################################################################
# FIXME: this path needs to be fixed to point to the actual location of #
# the project 'fabric-sdk-node' in the file system #
# the project 'fabric-sdk-go' in the file system #
#########################################################################
MSPDir: /fabric-sdk-node/test/fixtures/channel/crypto-config/peerOrganizations/peerOrg2/msp/
MSPDir: /fabric-sdk-go/test/fixtures/channel/crypto-config/peerOrganizations/peerOrg2/msp/

# BCCSP (Blockchain crypto provider): Select which crypto implementation or
# library to use
Expand All @@ -117,11 +117,11 @@ Organizations:
SW:
Hash: SHA2
Security: 256
# Location of Key Store. If this is unset, a location will
# Location of Key Store. If this is unset, a location will
# be chosen using 'MSPDir'/keystore
FileKeyStore:
KeyStore:
FileKeyStore:
KeyStore:

AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
Expand Down Expand Up @@ -149,7 +149,7 @@ Orderer: &OrdererDefaults
- orderer0:7050

# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 10s
BatchTimeout: 1s

# Batch Size: Controls the number of messages batched into a block
BatchSize:
Expand Down
Binary file not shown.
8 changes: 0 additions & 8 deletions test/fixtures/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,3 @@ services:
depends_on:
- orderer0
- peer2

couchdb:
container_name: couchdb
image: couchdb
ports:
- 5984:5984
environment:
DB_URL: http://localhost:5984/member_db
2 changes: 1 addition & 1 deletion test/integration/chain_queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,6 @@ func TestChainQueries(t *testing.T) {
// Test Query Block - retrieve block by non-existent number
block, err = chain.QueryBlock(2147483647)
if err == nil {
t.Fatalf("QueryBlock return error: %v", err)
t.Fatalf("QueryBlock non-existent didn't return an error")
}
}
55 changes: 55 additions & 0 deletions test/integration/channel_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
Licensed 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.
*/

package integration

import (
"io/ioutil"
"testing"

"github.com/hyperledger/fabric-sdk-go/config"
"github.com/hyperledger/fabric-sdk-go/fabric-client"
)

func TestChannelCreation(t *testing.T) {
initializeConfiguration(t)

testSetup := BaseSetupImpl{}
invokeChain, err := testSetup.GetChain()
if err != nil {
t.Fatal(err)
}
configTx, err := ioutil.ReadFile("../fixtures/channel/testchannel.tx")
if err != nil {
t.Fatalf("Error reading config file: %s", err.Error())
}

request := fabricclient.CreateChannelRequest{ConfigData: configTx}
err = invokeChain.CreateChannel(request)
if err != nil {
t.Fatalf(err.Error())
}
}

func initializeConfiguration(t *testing.T) {
err := config.InitConfig("../fixtures/config/config_test.yaml")
if err != nil {
t.Fatalf(err.Error())
}
}
7 changes: 4 additions & 3 deletions test/integration/install_chaincode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var chain fabricClient.Chain
func TestChaincodeInstallUsingChaincodePath(t *testing.T) {
testSetup := BaseSetupImpl{}

chainCodeVersion := "v0" + strconv.Itoa(rand.Intn(100))
chainCodeVersion := getRandomCCVersion()
err := testSetup.InstallCC(chain, "install", chainCodePath, chainCodeVersion, nil, nil)
if err != nil {
t.Fatalf("installCC return error: %v", err)
Expand All @@ -59,7 +59,7 @@ func TestChaincodeInstallUsingChaincodePath(t *testing.T) {
func TestChaincodeInstallUsingChaincodePackage(t *testing.T) {
testSetup := BaseSetupImpl{}

chainCodeVersion := "v0" + strconv.Itoa(rand.Intn(100))
chainCodeVersion := getRandomCCVersion()
testSetup.ChangeGOPATHToDeploy()
chaincodePackage, err := fabricClient.PackageCC(chainCodePath, "")
if err != nil {
Expand Down Expand Up @@ -96,6 +96,7 @@ func TestMain(m *testing.M) {
os.Exit(code)
}

func init() {
func getRandomCCVersion() string {
rand.Seed(time.Now().UnixNano())
return "v0" + strconv.Itoa(rand.Intn(10000000))
}

0 comments on commit 9b8d2c0

Please sign in to comment.