Skip to content

Commit

Permalink
FAB-1022 Call gossip when a peer join channel
Browse files Browse the repository at this point in the history
1/06/17 Fixing cscc and lscc path uniqueness
12/21 Fixing MSP config path to work in both CI and local test
12/19 Fixing PEER_CFG_PATH and config builder loader of certs to avoid CI failures
12/19 Adding port to peer local IP

Beside integrating gossip, this commit also includes:
- changing the package of cscc to avoid import cycle
- calling MSP to set up security configuration for chains
- initializing system chaincodes for each chain
- more unit tests.

Change-Id: I62b3532e3c18ff95567cf5f80450286b63a1e959
Signed-off-by: Binh Q. Nguyen <binhn@us.ibm.com>
  • Loading branch information
binhn committed Jan 6, 2017
1 parent c20fd9d commit 2f6433f
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package cscc (configuration system chaincode) provides functions to manage
// Package chaincode configer provides functions to manage
// configuration transactions as the network is being reconfigured. The
// configuration transactions arrive from the ordering service to the committer
// who calls this chaincode. The chaincode also provides peer configuration
// services such as joining a chain or getting configuration data.
package cscc
package chaincode

import (
"errors"
"fmt"

// "github.com/golang/protobuf/proto"
"github.com/op/go-logging"

"github.com/hyperledger/fabric/core/chaincode/shim"
Expand All @@ -39,7 +38,7 @@ import (
type PeerConfiger struct {
}

var logger = logging.MustGetLogger("cscc")
var cnflogger = logging.MustGetLogger("chaincode")

// These are function names from Invoke first parameter
const (
Expand All @@ -52,7 +51,7 @@ const (
// This allows the chaincode to initialize any variables on the ledger prior
// to any transaction execution on the chain.
func (e *PeerConfiger) Init(stub shim.ChaincodeStubInterface) ([]byte, error) {
logger.Info("Init CSCC")
cnflogger.Info("Init CSCC")

return nil, nil
}
Expand All @@ -75,7 +74,7 @@ func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error)
}
fname := string(args[0])

logger.Debugf("Invoke function: %s", fname)
cnflogger.Debugf("Invoke function: %s", fname)

// TODO: Handle ACL

Expand Down Expand Up @@ -103,11 +102,20 @@ func joinChain(blockBytes []byte) ([]byte, error) {
return nil, fmt.Errorf("Failed to reconstruct the genesis block, %s", err)
}

if err := peer.CreateChainFromBlock(block); err != nil {
if err = peer.CreateChainFromBlock(block); err != nil {
return nil, err
}

return nil, nil
chainID, err := utils.GetChainIDFromBlock(block)
if err != nil {
return nil, fmt.Errorf("Failed to get the chain ID from the configuration block, %s", err)
}

// Initialize all system chainodes on this chain
// TODO: Fix this code to initialize instead of deploy chaincodes
DeploySysCCs(chainID)

return []byte("200"), nil
}

func updateConfigBlock(blockBytes []byte) ([]byte, error) {
Expand All @@ -127,9 +135,7 @@ func updateConfigBlock(blockBytes []byte) ([]byte, error) {
return nil, err
}

// TODO: would committer get ledger and update ?

return nil, nil
return []byte("200"), nil
}

// Return the current configuration block for the specified chainID. If the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@ 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 cscc
package chaincode

import (
"fmt"
"net"
"os"
"testing"
"time"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/peer"
"github.com/hyperledger/fabric/gossip/service"
"github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
)

func TestInit(t *testing.T) {
func TestConfigerInit(t *testing.T) {
e := new(PeerConfiger)
stub := shim.NewMockStub("PeerConfiger", e)

Expand All @@ -42,27 +45,48 @@ func TestInit(t *testing.T) {
}
}

func TestInvokeJoinChainMissingParams(t *testing.T) {
func setupEndpoint(t *testing.T) {
peerAddress := peer.GetLocalIP()
if peerAddress == "" {
peerAddress = "0.0.0.0"
}
peerAddress = peerAddress + ":21213"
t.Logf("Local peer IP address: %s", peerAddress)
var opts []grpc.ServerOption
grpcServer := grpc.NewServer(opts...)
getPeerEndpoint := func() (*pb.PeerEndpoint, error) {
return &pb.PeerEndpoint{ID: &pb.PeerID{Name: "cscctestpeer"}, Address: peerAddress}, nil
}
ccStartupTimeout := time.Duration(30000) * time.Millisecond
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
}

func TestConfigerInvokeJoinChainMissingParams(t *testing.T) {
//t.Skip("Test CI build")
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/")
defer os.RemoveAll("/var/hyperledger/test/")

e := new(PeerConfiger)
stub := shim.NewMockStub("PeerConfiger", e)

setupEndpoint(t)
// Failed path: Not enough parameters
args := [][]byte{[]byte("JoinChain")}
if _, err := stub.MockInvoke("1", args); err == nil {
t.Fatalf("cscc invoke JoinChain should have failed with invalid number of args: %v", args)
}
}

func TestInvokeJoinChainWrongParams(t *testing.T) {
func TestConfigerInvokeJoinChainWrongParams(t *testing.T) {
//t.Skip("Test CI build")
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/")
defer os.RemoveAll("/var/hyperledger/test/")

e := new(PeerConfiger)
stub := shim.NewMockStub("PeerConfiger", e)

setupEndpoint(t)

// Failed path: wrong parameter type
args := [][]byte{[]byte("JoinChain"), []byte("action")}
if _, err := stub.MockInvoke("1", args); err == nil {
Expand All @@ -71,13 +95,16 @@ func TestInvokeJoinChainWrongParams(t *testing.T) {
}
}

func TestInvokeJoinChainCorrectParams(t *testing.T) {
func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) {
//t.Skip("Test CI build")
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/")
defer os.RemoveAll("/var/hyperledger/test/")

e := new(PeerConfiger)
stub := shim.NewMockStub("PeerConfiger", e)

setupEndpoint(t)

// Initialize gossip service
grpcServer := grpc.NewServer()
socket, err := net.Listen("tcp", fmt.Sprintf("%s:%d", "", 13611))
Expand All @@ -92,7 +119,7 @@ func TestInvokeJoinChainCorrectParams(t *testing.T) {
t.Fatalf("cscc invoke JoinChain failed because invalid block")
}
args := [][]byte{[]byte("JoinChain"), blockBytes}
if _, err := stub.MockInvoke("1", args); err != nil {
if _, err = stub.MockInvoke("1", args); err != nil {
t.Fatalf("cscc invoke JoinChain failed with: %v", err)
}

Expand All @@ -103,15 +130,18 @@ func TestInvokeJoinChainCorrectParams(t *testing.T) {
t.Fatalf("cscc invoke JoinChain failed with: %v", err)
}
args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)}
if _, err := stub.MockInvoke("1", args); err != nil {
if _, err = stub.MockInvoke("1", args); err != nil {
t.Fatalf("cscc invoke GetConfigBlock failed with: %v", err)
}
}

func TestInvokeUpdateConfigBlock(t *testing.T) {
func TestConfigerInvokeUpdateConfigBlock(t *testing.T) {
//t.Skip("Test CI build")
e := new(PeerConfiger)
stub := shim.NewMockStub("PeerConfiger", e)

setupEndpoint(t)

// Failed path: Not enough parameters
args := [][]byte{[]byte("UpdateConfigBlock")}
if _, err := stub.MockInvoke("1", args); err == nil {
Expand Down
7 changes: 3 additions & 4 deletions core/chaincode/importsysccs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package chaincode

import (
//import system chain codes here
"github.com/hyperledger/fabric/core/system_chaincode/cscc"
"github.com/hyperledger/fabric/core/system_chaincode/escc"
"github.com/hyperledger/fabric/core/system_chaincode/vscc"
)
Expand All @@ -29,15 +28,15 @@ var systemChaincodes = []*SystemChaincode{
ChainlessCC: true,
Enabled: true,
Name: "cscc",
Path: "github.com/hyperledger/fabric/core/system_chaincode/cscc",
Path: "github.com/hyperledger/fabric/core/chaincode/cscc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &cscc.PeerConfiger{},
Chaincode: &PeerConfiger{},
},
{
ChainlessCC: false,
Enabled: true,
Name: "lccc",
Path: "github.com/hyperledger/fabric/core/chaincode",
Path: "github.com/hyperledger/fabric/core/chaincode/lscc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &LifeCycleSysCC{},
},
Expand Down
17 changes: 6 additions & 11 deletions core/peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ import (
"github.com/op/go-logging"
"github.com/spf13/viper"

// "github.com/hyperledger/fabric/core/chaincode"
"github.com/hyperledger/fabric/core/comm"
"github.com/hyperledger/fabric/core/committer"
"github.com/hyperledger/fabric/core/ledger/kvledger"
// "github.com/hyperledger/fabric/core/peer/msp"
"github.com/hyperledger/fabric/core/peer/msp"
"github.com/hyperledger/fabric/gossip/service"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protos/common"
Expand Down Expand Up @@ -139,22 +138,18 @@ func getCurrConfigBlockFromLedger(ledger *kvledger.KVLedger) (*common.Block, err
func createChain(cid string, ledger *kvledger.KVLedger, cb *common.Block) error {
c := committer.NewLedgerCommitter(ledger)

// TODO: Call MSP to load from config block
// mgr, err := mspmgmt.GetMSPManagerFromBlock(cb)
// if err != nil {
// return err
// }
mgr, err := mspmgmt.GetMSPManagerFromBlock(cb)
if err != nil {
return err
}

if err := service.GetGossipService().JoinChannel(c, cb); err != nil {
return err
}

// Initialize all system chaincodes on this chain
// chaincode.DeploySysCCs(cid)

chains.Lock()
defer chains.Unlock()
chains.list[cid] = &chain{cb: cb, ledger: ledger, mspmgr: nil, committer: c}
chains.list[cid] = &chain{cb: cb, ledger: ledger, mspmgr: mgr, committer: c}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion core/peer/peer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestCreateChainFromBlock(t *testing.T) {

err = CreateChainFromBlock(block)
if err != nil {
t.Fatalf("failed to create chain")
t.Fatalf("failed to create chain %s", err)
}

// Correct ledger
Expand Down
8 changes: 4 additions & 4 deletions msp/configbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ const (
)

func GetLocalMspConfig(dir string) (*msp.MSPConfig, error) {
cacertDir := dir + string(filepath.Separator) + cacerts
signcertDir := dir + string(filepath.Separator) + signcerts
admincertDir := dir + string(filepath.Separator) + admincerts
keystoreDir := dir + string(filepath.Separator) + keystore
cacertDir := filepath.Join(dir, cacerts)
signcertDir := filepath.Join(dir, signcerts)
admincertDir := filepath.Join(dir, admincerts)
keystoreDir := filepath.Join(dir, keystore)

cacerts, err := getPemMaterialFromDir(cacertDir)
if err != nil || len(cacerts) == 0 {
Expand Down
29 changes: 29 additions & 0 deletions protos/utils/blockutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ package utils

import (
"fmt"
"io/ioutil"
"os"

"github.com/golang/protobuf/proto"

"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/common/configtx"
"github.com/hyperledger/fabric/msp"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
)
Expand Down Expand Up @@ -82,6 +85,7 @@ func MakeConfigurationBlock(testChainID string) (*cb.Block, error) {
encodeConsensusType(testChainID),
encodeBatchSize(testChainID),
lockDefaultModificationPolicy(testChainID),
encodeMSP(testChainID),
)
payloadChainHeader := MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION,
configItemChainHeader.Version, testChainID, epoch)
Expand Down Expand Up @@ -111,6 +115,7 @@ const (
lastModified = uint64(0)
consensusTypeKey = "ConsensusType"
batchSizeKey = "BatchSize"
mspKey = "MSP"
)

func createSignedConfigItem(chainID string,
Expand Down Expand Up @@ -149,3 +154,27 @@ func lockDefaultModificationPolicy(testChainID string) *cb.SignedConfigurationIt
MarshalOrPanic(MakePolicyOrPanic(cauthdsl.RejectAllPolicy)),
configtx.DefaultModificationPolicyID)
}

// This function is needed to locate the MSP test configuration when running
// in CI build env or local with "make unit-test". A better way to manage this
// is to define a config path in yaml that may point to test or production
// location of the config
func getTESTMSPConfigPath() string {
cfgPath := os.Getenv("PEER_CFG_PATH") + "/msp/sampleconfig/"
if _, err := ioutil.ReadDir(cfgPath); err != nil {
cfgPath = os.Getenv("GOPATH") + "/src/github.com/hyperledger/fabric/msp/sampleconfig/"
}
return cfgPath
}

func encodeMSP(testChainID string) *cb.SignedConfigurationItem {
cfgPath := getTESTMSPConfigPath()
conf, err := msp.GetLocalMspConfig(cfgPath)
if err != nil {
panic(fmt.Sprintf("GetLocalMspConfig failed, err %s", err))
}
return createSignedConfigItem(testChainID,
mspKey,
MarshalOrPanic(conf),
configtx.DefaultModificationPolicyID)
}

0 comments on commit 2f6433f

Please sign in to comment.