diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index 7463bd9801a..62d7e1079f1 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -61,7 +61,8 @@ func getTxSimulator(context context.Context) ledger.TxSimulator { if txsim, ok := context.Value(TXSimulatorKey).(ledger.TxSimulator); ok { return txsim } - panic("!!!---Not Using ledgernext---!!!") + //chaincode will not allow state operations + return nil } //CCContext pass this around instead of string of args diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index a49c70719ed..21897cbca0d 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -31,7 +31,6 @@ import ( "github.com/hyperledger/fabric/core/container" "github.com/hyperledger/fabric/core/container/ccintf" "github.com/hyperledger/fabric/core/ledger" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/util" pb "github.com/hyperledger/fabric/protos/peer" @@ -60,6 +59,9 @@ func getNowMillis() int64 { func initPeer(chainIDs ...string) (net.Listener, error) { //start clean finitPeer(nil, chainIDs...) + + peer.MockInitialize() + var opts []grpc.ServerOption if viper.GetBool("peer.tls.enabled") { creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file")) @@ -70,10 +72,6 @@ func initPeer(chainIDs ...string) (net.Listener, error) { } grpcServer := grpc.NewServer(opts...) - ledgerPath := viper.GetString("peer.fileSystemPath") - - kvledger.Initialize(ledgerPath) - peerAddress, err := peer.GetLocalAddress() if err != nil { return nil, fmt.Errorf("Error obtaining peer address: %s", err) @@ -93,7 +91,10 @@ func initPeer(chainIDs ...string) (net.Listener, error) { RegisterSysCCs() for _, id := range chainIDs { - kvledger.CreateLedger(id) + if err = peer.MockCreateChain(id); err != nil { + closeListenerAndSleep(lis) + return nil, err + } DeploySysCCs(id) } @@ -106,7 +107,7 @@ func finitPeer(lis net.Listener, chainIDs ...string) { if lis != nil { for _, c := range chainIDs { deRegisterSysCCs(c) - if lgr := kvledger.GetLedger(c); lgr != nil { + if lgr := peer.GetLedger(c); lgr != nil { lgr.Close() } } @@ -119,7 +120,7 @@ func finitPeer(lis net.Listener, chainIDs ...string) { } func startTxSimulation(ctxt context.Context, chainID string) (context.Context, ledger.TxSimulator, error) { - lgr := kvledger.GetLedger(chainID) + lgr := peer.GetLedger(chainID) txsim, err := lgr.NewTxSimulator() if err != nil { return nil, nil, err @@ -161,7 +162,7 @@ func endTxSimulationCIS(chainID string, txid string, txsim ledger.TxSimulator, p func endTxSimulation(chainID string, txsim ledger.TxSimulator, payload []byte, commit bool, prop *pb.Proposal) error { txsim.Done() - if lgr := kvledger.GetLedger(chainID); lgr != nil { + if lgr := peer.GetLedger(chainID); lgr != nil { if commit { var txSimulationResults []byte var err error diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 8be4816056b..fa00be725a7 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -480,6 +480,18 @@ func (handler *Handler) afterGetState(e *fsm.Event, state string) { handler.handleGetState(msg) } +// is this a txid for which there is a valid txsim +func (handler *Handler) isValidTxSim(txid string, fmtStr string, args ...interface{}) (*transactionContext, *pb.ChaincodeMessage) { + txContext := handler.getTxContext(txid) + if txContext == nil || txContext.txsimulator == nil { + // Send error msg back to chaincode. No ledger context + errStr := fmt.Sprintf(fmtStr, args...) + chaincodeLogger.Errorf(errStr) + return nil, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(errStr), Txid: txid} + } + return txContext, nil +} + // Handles query to ledger to get state func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { // The defer followed by triggering a go routine dance is needed to ensure that the previous state transition @@ -509,8 +521,13 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { var res []byte var err error + var txContext *transactionContext + + txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetState. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + if txContext == nil { + return + } - txContext := handler.getTxContext(msg.Txid) res, err = txContext.txsimulator.GetState(chaincodeID, key) if err != nil { @@ -579,8 +596,13 @@ func (handler *Handler) handleRangeQueryState(msg *pb.ChaincodeMessage) { } iterID := util.GenerateUUID() - txContext := handler.getTxContext(msg.Txid) + var txContext *transactionContext + + txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for RangeQueryState. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + if txContext == nil { + return + } chaincodeID := handler.ChaincodeID.Name rangeIter, err := txContext.txsimulator.GetStateRangeScanIterator(chaincodeID, rangeQueryState.StartKey, rangeQueryState.EndKey) @@ -864,6 +886,13 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { var err error var res []byte + var txContext *transactionContext + + txContext, triggerNextStateMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for %s. Sending %s", shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_ERROR) + if txContext == nil { + return + } + if msg.Type.String() == pb.ChaincodeMessage_PUT_STATE.String() { putStateInfo := &pb.PutStateInfo{} unmarshalErr := proto.Unmarshal(msg.Payload, putStateInfo) @@ -874,13 +903,10 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { return } - // Invoke ledger to put state - txContext := handler.getTxContext(msg.Txid) err = txContext.txsimulator.SetState(chaincodeID, putStateInfo.Key, putStateInfo.Value) } else if msg.Type.String() == pb.ChaincodeMessage_DEL_STATE.String() { // Invoke ledger to delete state key := string(msg.Payload) - txContext := handler.getTxContext(msg.Txid) err = txContext.txsimulator.DeleteState(chaincodeID, key) } else if msg.Type.String() == pb.ChaincodeMessage_INVOKE_CHAINCODE.String() { //check and prohibit C-call-C for CONFIDENTIAL txs @@ -902,7 +928,6 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { newChaincodeID := chaincodeSpec.ChaincodeID.Name chaincodeLogger.Debugf("[%s] C-call-C %s", shorttxid(msg.Txid), newChaincodeID) - txContext := handler.getTxContext(msg.Txid) ctxt := context.Background() ctxt = context.WithValue(ctxt, TXSimulatorKey, txContext.txsimulator) diff --git a/core/chaincode/importsysccs.go b/core/chaincode/importsysccs.go index 96699108622..317d8831ffc 100644 --- a/core/chaincode/importsysccs.go +++ b/core/chaincode/importsysccs.go @@ -26,32 +26,36 @@ import ( //see systemchaincode_test.go for an example using "sample_syscc" var systemChaincodes = []*SystemChaincode{ { - Enabled: true, - Name: "lccc", - Path: "github.com/hyperledger/fabric/core/chaincode", - InitArgs: [][]byte{[]byte("")}, - Chaincode: &LifeCycleSysCC{}, + ChainlessCC: true, + Enabled: true, + Name: "cscc", + Path: "github.com/hyperledger/fabric/core/system_chaincode/cscc", + InitArgs: [][]byte{[]byte("")}, + Chaincode: &cscc.PeerConfiger{}, }, { - Enabled: true, - Name: "escc", - Path: "github.com/hyperledger/fabric/core/system_chaincode/escc", - InitArgs: [][]byte{[]byte("")}, - Chaincode: &escc.EndorserOneValidSignature{}, + ChainlessCC: false, + Enabled: true, + Name: "lccc", + Path: "github.com/hyperledger/fabric/core/chaincode", + InitArgs: [][]byte{[]byte("")}, + Chaincode: &LifeCycleSysCC{}, }, { - Enabled: true, - Name: "vscc", - Path: "github.com/hyperledger/fabric/core/system_chaincode/vscc", - InitArgs: [][]byte{[]byte("")}, - Chaincode: &vscc.ValidatorOneValidSignature{}, + ChainlessCC: false, + Enabled: true, + Name: "escc", + Path: "github.com/hyperledger/fabric/core/system_chaincode/escc", + InitArgs: [][]byte{[]byte("")}, + Chaincode: &escc.EndorserOneValidSignature{}, }, { - Enabled: true, - Name: "cscc", - Path: "github.com/hyperledger/fabric/core/system_chaincode/cscc", - InitArgs: [][]byte{[]byte("")}, - Chaincode: &cscc.PeerConfiger{}, + ChainlessCC: false, + Enabled: true, + Name: "vscc", + Path: "github.com/hyperledger/fabric/core/system_chaincode/vscc", + InitArgs: [][]byte{[]byte("")}, + Chaincode: &vscc.ValidatorOneValidSignature{}, }} //RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric @@ -66,7 +70,19 @@ func RegisterSysCCs() { //note the chaincode must still be deployed and launched like a user chaincode will be func DeploySysCCs(chainID string) { for _, sysCC := range systemChaincodes { - DeploySysCC(chainID, sysCC) + if !sysCC.ChainlessCC { + deploySysCC(chainID, sysCC) + } + } +} + +//DeployChainlessSysCCs is the hook for deploying chainless system chaincodes +//these chaincodes cannot make any ledger calls +func DeployChainlessSysCCs() { + for _, sysCC := range systemChaincodes { + if sysCC.ChainlessCC { + deploySysCC("", sysCC) + } } } @@ -75,7 +91,9 @@ func DeploySysCCs(chainID string) { //in the same process func deRegisterSysCCs(chainID string) { for _, sysCC := range systemChaincodes { - deregisterSysCC(chainID, sysCC) + if !sysCC.ChainlessCC { + deregisterSysCC(chainID, sysCC) + } } } @@ -89,3 +107,14 @@ func IsSysCC(name string) bool { } return false } + +//IsChainlessSysCC returns true if the name matches a chainless system chaincode's +//system chaincode names are system, chain wide +func IsChainlessSysCC(name string) bool { + for _, sysCC := range systemChaincodes { + if sysCC.Name == name && sysCC.ChainlessCC { + return true + } + } + return false +} diff --git a/core/chaincode/lccc.go b/core/chaincode/lccc.go index 99ec9792998..4e60f6426b6 100644 --- a/core/chaincode/lccc.go +++ b/core/chaincode/lccc.go @@ -23,7 +23,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/ledger" - "github.com/hyperledger/fabric/core/ledger/kvledger" + "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/util" pb "github.com/hyperledger/fabric/protos/peer" "github.com/op/go-logging" @@ -277,7 +277,7 @@ func (lccc *LifeCycleSysCC) deploy(stub shim.ChaincodeStubInterface, chainname s // 1) don't allow state initialization on deploy // 2) combine both LCCC and the called chaincodes into one RW set // 3) just drop the second - lgr := kvledger.GetLedger(chainname) + lgr := peer.GetLedger(chainname) var dummytxsim ledger.TxSimulator var err error diff --git a/core/chaincode/sysccapi.go b/core/chaincode/sysccapi.go index 8a6244640c6..bd19b504eea 100644 --- a/core/chaincode/sysccapi.go +++ b/core/chaincode/sysccapi.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/container/inproccontroller" "github.com/hyperledger/fabric/core/ledger" - "github.com/hyperledger/fabric/core/ledger/kvledger" + "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/util" "github.com/op/go-logging" "github.com/spf13/viper" @@ -38,6 +38,10 @@ var sysccLogger = logging.MustGetLogger("sysccapi") // when the fabric comes up. SystemChaincodes are installed by adding an // entry in importsysccs.go type SystemChaincode struct { + //Global, once only not tied to chains. Such chaincodes cannot + //save state in the ledger. CSCC is an example + ChainlessCC bool + // Enabled a convenient switch to enable/disable system chaincode without // having to remove entry from importsysccs.go Enabled bool @@ -76,28 +80,37 @@ func RegisterSysCC(syscc *SystemChaincode) error { return err } -// DeploySysCC deploys the given system chaincode on a chain -func DeploySysCC(chainID string, syscc *SystemChaincode) error { +// deploySysCC deploys the given system chaincode on a chain +func deploySysCC(chainID string, syscc *SystemChaincode) error { if !syscc.Enabled || !isWhitelisted(syscc) { sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path)) return nil } + if chainID == "" && !syscc.ChainlessCC { + return fmt.Errorf("cannot deploy system chaincode %s without chain id", syscc.Name) + } else if chainID != "" && syscc.ChainlessCC { + return fmt.Errorf("cannot deploy chainless system chaincode %s with chain id %s", syscc.Name, chainID) + } + var err error - lgr := kvledger.GetLedger(chainID) - var txsim ledger.TxSimulator - if txsim, err = lgr.NewTxSimulator(); err != nil { - return err - } + ctxt := context.Background() + if !syscc.ChainlessCC { + lgr := peer.GetLedger(chainID) + var txsim ledger.TxSimulator + if txsim, err = lgr.NewTxSimulator(); err != nil { + return err + } + + ctxt = context.WithValue(ctxt, TXSimulatorKey, txsim) - defer txsim.Done() + defer txsim.Done() + } chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name} spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: syscc.InitArgs}} - ctxt := context.WithValue(context.Background(), TXSimulatorKey, txsim) - // First build and get the deployment spec chaincodeDeploymentSpec, err := buildSysCC(ctxt, spec) diff --git a/core/chaincode/systemchaincode_test.go b/core/chaincode/systemchaincode_test.go index 93de7e9a902..4b8755ac85f 100644 --- a/core/chaincode/systemchaincode_test.go +++ b/core/chaincode/systemchaincode_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "github.com/hyperledger/fabric/core/ledger/kvledger" + "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/system_chaincode/samplesyscc" "github.com/hyperledger/fabric/core/util" pb "github.com/hyperledger/fabric/protos/peer" @@ -70,9 +70,10 @@ func TestExecuteDeploySysChaincode(t *testing.T) { var opts []grpc.ServerOption grpcServer := grpc.NewServer(opts...) viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb") - kvledger.Initialize("/var/hyperledger/test/tmpdb") defer os.RemoveAll("/var/hyperledger/test/tmpdb") + peer.MockInitialize() + //use a different address than what we usually use for "peer" //we override the peerAddress set in chaincode_support.go // FIXME: Use peer.GetLocalAddress() @@ -115,7 +116,10 @@ func TestExecuteDeploySysChaincode(t *testing.T) { /////^^^ system initialization completed ^^^ - kvledger.CreateLedger(chainID) + if err = peer.MockCreateChain(chainID); err != nil { + closeListenerAndSleep(lis) + return + } err = deploySampleSysCC(t, ctxt, chainID) if err != nil { @@ -132,9 +136,10 @@ func TestMultichains(t *testing.T) { var opts []grpc.ServerOption grpcServer := grpc.NewServer(opts...) viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb") - kvledger.Initialize("/var/hyperledger/test/tmpdb") defer os.RemoveAll("/var/hyperledger/test/tmpdb") + peer.MockInitialize() + //use a different address than what we usually use for "peer" //we override the peerAddress set in chaincode_support.go // FIXME: Use peer.GetLocalAddress() @@ -177,7 +182,10 @@ func TestMultichains(t *testing.T) { chainID := "chain1" - kvledger.CreateLedger(chainID) + if err = peer.MockCreateChain(chainID); err != nil { + closeListenerAndSleep(lis) + return + } err = deploySampleSysCC(t, ctxt, chainID) if err != nil { @@ -188,7 +196,10 @@ func TestMultichains(t *testing.T) { chainID = "chain2" - kvledger.CreateLedger(chainID) + if err = peer.MockCreateChain(chainID); err != nil { + closeListenerAndSleep(lis) + return + } err = deploySampleSysCC(t, ctxt, chainID) if err != nil { diff --git a/core/committer/noopssinglechain/client.go b/core/committer/noopssinglechain/client.go index c794e8c0eb0..1cb53758ea4 100644 --- a/core/committer/noopssinglechain/client.go +++ b/core/committer/noopssinglechain/client.go @@ -23,7 +23,6 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/committer" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/hyperledger/fabric/events/producer" "github.com/hyperledger/fabric/protos/common" "github.com/hyperledger/fabric/protos/orderer" @@ -149,11 +148,8 @@ func (d *DeliverService) Stop() { d.stopDeliver() } -func (d *DeliverService) JoinChannel(committer committer.Committer, configBlock *common.Block) { - if err := service.GetGossipService().JoinChannel(committer, configBlock); err != nil { - panic("Cannot join channel, exiting") - } - +// Start delivery service +func (d *DeliverService) Start(committer committer.Committer) { go d.checkLeaderAndRunDeliver(committer) } @@ -218,7 +214,7 @@ func isTxValidForVscc(payload *common.Payload, envBytes []byte) error { // get context for the chaincode execution var txsim ledger.TxSimulator - lgr := kvledger.GetLedger(chainName) + lgr := peer.GetLedger(chainName) txsim, err = lgr.NewTxSimulator() if err != nil { logger.Errorf("Cannot obtain tx simulator, err %s\n", err) diff --git a/core/container/ccintf/ccintf.go b/core/container/ccintf/ccintf.go index e25226c18b8..886eb774178 100644 --- a/core/container/ccintf/ccintf.go +++ b/core/container/ccintf/ccintf.go @@ -58,13 +58,13 @@ func (ccid *CCID) GetName() string { if ccid.ChaincodeSpec == nil { panic("nil chaincode spec") } - if ccid.ChainID == "" { - panic("chain id not specified") - } - - hash := util.ComputeCryptoHash([]byte(ccid.ChainID)) - hexstr := hex.EncodeToString(hash[:]) + //this better be chainless system chaincode! + if ccid.ChainID != "" { + hash := util.ComputeCryptoHash([]byte(ccid.ChainID)) + hexstr := hex.EncodeToString(hash[:]) + return ccid.ChaincodeSpec.ChaincodeID.Name + "-" + hexstr + } - return ccid.ChaincodeSpec.ChaincodeID.Name + "-" + hexstr + return ccid.ChaincodeSpec.ChaincodeID.Name } diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index fc3bfe9a89c..b1964f4eef8 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -25,7 +25,6 @@ import ( "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/ledger" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/msp" "github.com/hyperledger/fabric/protos/common" @@ -59,7 +58,10 @@ func (*Endorser) checkEsccAndVscc(prop *pb.Proposal) error { } func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error) { - lgr := kvledger.GetLedger(ledgername) + lgr := peer.GetLedger(ledgername) + if lgr == nil { + return nil, fmt.Errorf("chain does not exist(%s)", ledgername) + } return lgr.NewTxSimulator() } @@ -90,7 +92,9 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, txid stri var b []byte var ccevent *pb.ChaincodeEvent - ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim) + if txsim != nil { + ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim) + } //is this a system chaincode syscc := chaincode.IsSysCC(cid.Name) @@ -163,25 +167,31 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st return nil, nil, nil, err } - if simResult, err = txsim.GetTxSimulationResults(); err != nil { - return nil, nil, nil, err + if txsim != nil { + if simResult, err = txsim.GetTxSimulationResults(); err != nil { + return nil, nil, nil, err + } } return resp, simResult, ccevent, nil } func (e *Endorser) getCDSFromLCCC(ctx context.Context, chainID string, txid string, prop *pb.Proposal, chaincodeID string, txsim ledger.TxSimulator) ([]byte, error) { - ctxt := context.WithValue(ctx, chaincode.TXSimulatorKey, txsim) + ctxt := ctx + if txsim != nil { + ctxt = context.WithValue(ctx, chaincode.TXSimulatorKey, txsim) + } + return chaincode.GetCDSFromLCCC(ctxt, txid, prop, chainID, chaincodeID) } //endorse the proposal by calling the ESCC -func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, proposal *pb.Proposal, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator) ([]byte, error) { +func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, proposal *pb.Proposal, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.ProposalResponse, error) { endorserLogger.Infof("endorseProposal starts for chainID %s, ccid %s", chainID, ccid) // 1) extract the chaincodeDeploymentSpec for the chaincode we are invoking; we need it to get the escc var escc string - if ccid.Name != "lccc" { + if !chaincode.IsSysCC(ccid.Name) { depPayload, err := e.getCDSFromLCCC(ctx, chainID, txid, proposal, ccid.Name, txsim) if err != nil { return nil, fmt.Errorf("failed to obtain cds for %s - %s", ccid, err) @@ -235,7 +245,13 @@ func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid str // from other ESCCs, which would stand in the way of the // endorsement process. - return prBytes, nil + //3 -- respond + pResp, err := putils.GetProposalResponse(prBytes) + if err != nil { + return nil, err + } + + return pResp, nil } // ProcessProposal process the Proposal @@ -252,15 +268,19 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro } chainID := hdr.ChainHeader.ChainID - if chainID == "" { - err = fmt.Errorf("chainID not provided") - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err - } - //TODO check join call checks go here + //chainless MSPs have "" chain name + ischainless := chaincode.IsChainlessSysCC(hdrExt.ChaincodeID.Name) - //OK... this is not a join proposal, just a regular one...the chain is there and the peer has joined - //lets proceed with the proposal processing + //chainID should be empty for chainless SysCC (such as CSCC for Join proposal) and for + //nothing else + if chainID == "" && !ischainless { + err = fmt.Errorf("chainID not provided for chaincode %s", hdrExt.ChaincodeID.Name) + return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + } else if chainID != "" && ischainless { + err = fmt.Errorf("chainID %s provided for a chainless syscc", hdrExt.ChaincodeID.Name) + return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + } //TODO check for uniqueness of prop.TxID with ledger @@ -270,14 +290,16 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err } - // obtaining once the tx simulator for this proposal + // obtaining once the tx simulator for this proposal. This will be nil + // for chainless proposals var txsim ledger.TxSimulator - //TODO - get chainname from the proposal when defined - chainName := hdr.ChainHeader.ChainID - if txsim, err = e.getTxSimulator(chainName); err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + if chainID != "" { + if txsim, err = e.getTxSimulator(chainID); err != nil { + return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + } + defer txsim.Done() } - defer txsim.Done() + //this could be a request to a chainless SysCC // TODO: if the proposal has an extension, it will be of type ChaincodeAction; // if it's present it means that no simulation is to be performed because @@ -293,18 +315,20 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro } //2 -- endorse and get a marshalled ProposalResponse message - //TODO what do we do with response ? We need it for Invoke responses for sure - prBytes, err := e.endorseProposal(ctx, chainID, txid, prop, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeID, txsim) - if err != nil { - return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err - } + var pResp *pb.ProposalResponse - //3 -- respond - pResp, err := putils.GetProposalResponse(prBytes) - if err != nil { - return nil, err + //TODO till we implement global ESCC, CSCC for system chaincodes + //chainless proposals (such as CSCC) don't have to be endorsed + if ischainless { + pResp = &pb.ProposalResponse{Response: &pb.Response{}} + } else { + pResp, err = e.endorseProposal(ctx, chainID, txid, prop, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeID, txsim) + if err != nil { + return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err + } } + //TODO what do we do with response ? We need it for Invoke responses for sure // Set the proposal response payload - it // contains the "return value" from the // chaincode invocation @@ -322,7 +346,7 @@ func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID string, sig return err } - lgr := kvledger.GetLedger(chainID) + lgr := peer.GetLedger(chainID) if lgr == nil { return fmt.Errorf("failure while looking up the ledger") } diff --git a/core/endorser/endorser_test.go b/core/endorser/endorser_test.go index df8b0f20225..a36c4a5beb3 100644 --- a/core/endorser/endorser_test.go +++ b/core/endorser/endorser_test.go @@ -29,7 +29,6 @@ import ( "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/container" "github.com/hyperledger/fabric/core/crypto/primitives" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/peer/msp" "github.com/hyperledger/fabric/core/util" @@ -72,8 +71,7 @@ func initPeer(chainID string) (net.Listener, error) { } //initialize ledger - lpath := viper.GetString("peer.fileSystemPath") - kvledger.Initialize(lpath) + peer.MockInitialize() getPeerEndpoint := func() (*pb.PeerEndpoint, error) { return &pb.PeerEndpoint{ID: &pb.PeerID{Name: "testpeer"}, Address: peerAddress}, nil @@ -96,7 +94,10 @@ func initPeer(chainID string) (net.Listener, error) { chaincode.RegisterSysCCs() - kvledger.CreateLedger(chainID) + if err = peer.MockCreateChain(chainID); err != nil { + closeListenerAndSleep(lis) + return nil, err + } chaincode.DeploySysCCs(chainID) diff --git a/core/ledger/kvledger/kv_ledgers.go b/core/ledger/kvledger/kv_ledgers.go deleted file mode 100644 index f8ea46739d1..00000000000 --- a/core/ledger/kvledger/kv_ledgers.go +++ /dev/null @@ -1,128 +0,0 @@ -/* -Copyright IBM Corp. 2016 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 kvledger - -import ( - "fmt" - "strings" - "sync" -) - -//--!!!!IMPORTANT!!!--!!!IMPORTANT!!!---!!!IMPORTANT!!!----------- -// -//Three things about this code -// -// 1. This code is TEMPORARY - it can go away when (sub) ledgers -// management is implemented -// 2. This code is PLACEHOLDER - in lieu of proper (sub) ledgers -// management, we need a mechanism to hold onto ledger handles -// This merely does that -// 3. Do NOT add any function related to subledgers till it has -// been agreed upon -//----------------------------------------------------------------- - -//-------- initialization -------- -var lManager *ledgerManager - -//Initialize kv ledgers -func Initialize(lpath string) { - if lpath == "" { - panic("DB path not specified") - } - if !strings.HasSuffix(lpath, "/") { - lpath = lpath + "/" - } - - //TODO - when we don't need 0.5 DB, we can remove this - lpath = lpath + "ledger/" - - lManager = &ledgerManager{ledgerPath: lpath, ledgers: make(map[string]*KVLedger)} -} - -//--------- errors ----------- - -//LedgerNotInitializedErr exists error -type LedgerNotInitializedErr string - -func (l LedgerNotInitializedErr) Error() string { - return fmt.Sprintf("ledger manager not inialized") -} - -//LedgerExistsErr exists error -type LedgerExistsErr string - -func (l LedgerExistsErr) Error() string { - return fmt.Sprintf("ledger exists %s", string(l)) -} - -//LedgerCreateErr exists error -type LedgerCreateErr string - -func (l LedgerCreateErr) Error() string { - return fmt.Sprintf("ledger creation failed %s", string(l)) -} - -//--------- ledger manager --------- -// just a container for ledgers -type ledgerManager struct { - sync.RWMutex - ledgerPath string - ledgers map[string]*KVLedger -} - -//CreateLedger creates a ledger if one does not exist -func CreateLedger(name string) (*KVLedger, error) { - lManager.Lock() - defer lManager.Unlock() - - lPath := lManager.ledgerPath + name - lgr, _ := lManager.ledgers[lPath] - if lgr != nil { - return lgr, LedgerExistsErr(name) - } - - var err error - - ledgerConf := NewConf(lPath, 0) - if lgr, err = NewKVLedger(ledgerConf); err != nil || lgr == nil { - return nil, LedgerCreateErr(name) - } - - lManager.ledgers[lPath] = lgr - - return lgr, nil -} - -//GetLedger returns a kvledger -//it will panic if ledger does not exist -func GetLedger(name string) *KVLedger { - //We should never have an empty ledgername when we do multichannel - if name == "" { - panic("empty naame") - } - - lManager.Lock() - defer lManager.Unlock() - - lPath := lManager.ledgerPath + name - lgr, _ := lManager.ledgers[lPath] - if lgr == nil { - panic("ledger " + name + " does not exist") - } - - return lgr -} diff --git a/core/ledger/kvledger/kv_ledgers_test.go b/core/ledger/kvledger/kv_ledgers_test.go deleted file mode 100644 index e1e819fac25..00000000000 --- a/core/ledger/kvledger/kv_ledgers_test.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright IBM Corp. 2016 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 kvledger - -import ( - "os" - "testing" -) - -func TestCreate(t *testing.T) { - lpath := "/tmp/ledgerstest" - os.RemoveAll(lpath) - - //init - Initialize(lpath) - - defer os.RemoveAll(lpath) - - func() { - defer func() { - //we expect a panic - if r := recover(); r == nil { - t.FailNow() - } - }() - //create once - if lgr := GetLedger("test"); lgr == nil { - t.FailNow() - } - }() - - //create it - if lgr, _ := CreateLedger("test"); lgr == nil { - t.FailNow() - } - - //get it again - if lgr := GetLedger("test"); lgr == nil { - t.FailNow() - } -} diff --git a/core/peer/msgvalidation.go b/core/peer/msgvalidation.go index e4087c48876..1fb409593a3 100644 --- a/core/peer/msgvalidation.go +++ b/core/peer/msgvalidation.go @@ -53,7 +53,7 @@ func validateChaincodeProposalMessage(prop *pb.Proposal, hdr *common.Header) (*p return chaincodeHdrExt, nil } -// validateProposalMessage checks the validity of a SignedProposal message +// ValidateProposalMessage checks the validity of a SignedProposal message // this function returns Header and ChaincodeHeaderExtension messages since they // have been unmarshalled and validated func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) { @@ -113,8 +113,13 @@ func checkSignatureFromCreator(creatorBytes []byte, sig []byte, msg []byte, Chai return fmt.Errorf("Nil arguments") } + mspObj := mspmgmt.GetMSPCommon(ChainID) + if mspObj == nil { + return fmt.Errorf("could not get msp for chain [%s]", ChainID) + } + // get the identity of the creator - creator, err := mspmgmt.GetManagerForChain(ChainID).DeserializeIdentity(creatorBytes) + creator, err := mspObj.DeserializeIdentity(creatorBytes) if err != nil { return fmt.Errorf("Failed to deserialize creator identity, err %s", err) } diff --git a/core/peer/msp/mgmt.go b/core/peer/msp/mgmt.go index 158e30c74ff..0066c8456d8 100644 --- a/core/peer/msp/mgmt.go +++ b/core/peer/msp/mgmt.go @@ -71,3 +71,12 @@ func GetLocalMSP() msp.MSP { return lclMsp } + +//GetMSPCommon returns the common interface +func GetMSPCommon(chainID string) msp.Common { + if chainID == "" { + return GetLocalMSP() + } + + return GetManagerForChain(chainID) +} diff --git a/core/peer/peer.go b/core/peer/peer.go index 65ffa2e7e44..eb140ecb15a 100644 --- a/core/peer/peer.go +++ b/core/peer/peer.go @@ -56,11 +56,19 @@ var chains = struct { list map[string]*chain }{list: make(map[string]*chain)} +//MockInitialize resets chains for test env +func MockInitialize() { + chains.list = nil + chains.list = make(map[string]*chain) +} + // Initialize sets up any chains that the peer has from the persistence. This // function should be called at the start up when the ledger and gossip // ready func Initialize() { + //Till JoinChain works, we continue to use default chain path := getLedgerPath("") + peerLogger.Infof("Init peer by loading chains from %s", path) files, err := ioutil.ReadDir(path) if err != nil { @@ -164,6 +172,22 @@ func CreateChainFromBlock(cb *common.Block) error { return createChain(cid, ledger, cb) } +// MockCreateChain used for creating a ledger for a chain for tests +// without havin to join +func MockCreateChain(cid string) error { + var ledger *kvledger.KVLedger + var err error + if ledger, err = createLedger(cid); err != nil { + return err + } + + chains.Lock() + defer chains.Unlock() + chains.list[cid] = &chain{ledger: ledger} + + return nil +} + // GetLedger returns the ledger of the chain with chain ID. Note that this // call returns nil if chain cid has not been created. func GetLedger(cid string) *kvledger.KVLedger { @@ -175,6 +199,17 @@ func GetLedger(cid string) *kvledger.KVLedger { return nil } +// GetCommitter returns the committer of the chain with chain ID. Note that this +// call returns nil if chain cid has not been created. +func GetCommitter(cid string) committer.Committer { + chains.RLock() + defer chains.RUnlock() + if c, ok := chains.list[cid]; ok { + return c.committer + } + return nil +} + // GetCurrConfigBlock returns the cached config block of the specified chain. // Note that this call returns nil if chain cid has not been created. func GetCurrConfigBlock(cid string) *common.Block { diff --git a/msp/msp.go b/msp/msp.go index b7e623210da..7996878e51e 100644 --- a/msp/msp.go +++ b/msp/msp.go @@ -22,6 +22,12 @@ import "github.com/hyperledger/fabric/protos/msp" // FIXME: we need better comments on the interfaces!! // FIXME: we need better comments on the interfaces!! +//Common is implemented by both MSPManger and MSP +type Common interface { + // DeserializeIdentity deserializes an identity + DeserializeIdentity(serializedIdentity []byte) (Identity, error) +} + // Membership service provider APIs for Hyperledger Fabric: // // By "membership service provider" we refer to an abstract component of the @@ -43,20 +49,23 @@ import "github.com/hyperledger/fabric/protos/msp" // This object is immutable, it is initialized once and never changed. type MSPManager interface { + // Common interface needs to be implemented by MSPManager + Common + // Setup the MSP manager instance according to configuration information Setup(msps []*msp.MSPConfig) error // GetMSPs Provides a list of Membership Service providers GetMSPs() (map[string]MSP, error) - - // DeserializeIdentity deserializes an identity - DeserializeIdentity(serializedIdentity []byte) (Identity, error) } // MSP is the minimal Membership Service Provider Interface to be implemented // to accommodate peer functionality type MSP interface { + // Common interface needs to be implemented by MSP + Common + // Setup the MSP instance according to configuration information Setup(config *msp.MSPConfig) error @@ -72,9 +81,6 @@ type MSP interface { // GetDefaultSigningIdentity returns the default signing identity GetDefaultSigningIdentity() (SigningIdentity, error) - // DeserializeIdentity deserializes an identity - DeserializeIdentity(serializedIdentity []byte) (Identity, error) - // Validate checks whether the supplied identity is valid Validate(id Identity) error } diff --git a/peer/core.yaml b/peer/core.yaml index ca6e50eef84..d3f620cf254 100644 --- a/peer/core.yaml +++ b/peer/core.yaml @@ -350,6 +350,7 @@ chaincode: # system chaincodes whitelist. To add system chaincode "myscc" to the # whitelist, add "myscc: enable" to the list system: + cscc: enable lccc: enable escc: enable vscc: enable diff --git a/peer/node/join.go b/peer/node/join.go new file mode 100755 index 00000000000..9cb72acf0cd --- /dev/null +++ b/peer/node/join.go @@ -0,0 +1,163 @@ +/* +Copyright IBM Corp. 2016 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 node + +import ( + "fmt" + "io/ioutil" + + cutil "github.com/hyperledger/fabric/core/util" + "github.com/hyperledger/fabric/msp" + "github.com/hyperledger/fabric/peer/common" + pb "github.com/hyperledger/fabric/protos/peer" + putils "github.com/hyperledger/fabric/protos/utils" + "github.com/spf13/cobra" + "golang.org/x/net/context" +) + +// join-related variables. +var ( + genesisBlockPath string +) + +// JoinCmdFactory holds the clients used by JoinCmd +type JoinCmdFactory struct { + EndorserClient pb.EndorserClient + Signer msp.SigningIdentity +} + +// initCmdFactory init the ChaincodeCmdFactory with default clients +func initCmdFactory() (*JoinCmdFactory, error) { + endorserClient, err := common.GetEndorserClient() + if err != nil { + return nil, fmt.Errorf("Error getting endorser client : %s", err) + } + + signer, err := common.GetDefaultSigner() + if err != nil { + return nil, fmt.Errorf("Error getting default signer: %s", err) + } + + return &JoinCmdFactory{ + EndorserClient: endorserClient, + Signer: signer, + }, nil +} + +func joinCmd() *cobra.Command { + // Set the flags on the node start command. + flags := nodeJoinCmd.Flags() + flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, + "Whether peer in chaincode development mode") + flags.StringVarP(&genesisBlockPath, "path", "b", common.UndefinedParamValue, + "Path to file containing genesis block") + + return nodeJoinCmd +} + +var nodeJoinCmd = &cobra.Command{ + Use: "join", + Short: "Joins the peer to a chain.", + Long: `Joins the peer to a chain.`, + RunE: func(cmd *cobra.Command, args []string) error { + return join(args) + }, +} + +func getJoinCCSpec() (*pb.ChaincodeSpec, error) { + if genesisBlockPath == common.UndefinedParamValue { + return nil, fmt.Errorf("Must supply genesis block file.\n") + } + + gb, err := ioutil.ReadFile(genesisBlockPath) + if err != nil { + return nil, err + } + + spec := &pb.ChaincodeSpec{} + + // Build the spec + input := &pb.ChaincodeInput{Args: [][]byte{[]byte("JoinChain"), gb}} + + spec = &pb.ChaincodeSpec{ + Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), + ChaincodeID: &pb.ChaincodeID{Name: "cscc"}, + CtorMsg: input, + } + + return spec, nil +} + +func executeJoin(cf *JoinCmdFactory) (err error) { + spec, err := getJoinCCSpec() + if err != nil { + return err + } + + // Build the ChaincodeInvocationSpec message + invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} + + creator, err := cf.Signer.Serialize() + if err != nil { + return fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.GetIdentifier(), err) + } + + uuid := cutil.GenerateUUID() + + var prop *pb.Proposal + prop, err = putils.CreateProposalFromCIS(uuid, "", invocation, creator) + if err != nil { + return fmt.Errorf("Error creating proposal for join %s\n", err) + } + + var signedProp *pb.SignedProposal + signedProp, err = putils.GetSignedProposal(prop, cf.Signer) + if err != nil { + return fmt.Errorf("Error creating signed proposal %s\n", err) + } + + var proposalResp *pb.ProposalResponse + proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp) + if err != nil { + return fmt.Errorf("Error endorsing %s\n", err) + } + + if proposalResp == nil { + return fmt.Errorf("Error on join by endorsing: %s\n", err) + } + + fmt.Printf("Join Result: %s\n", string(proposalResp.Response.Payload)) + + return nil +} + +func join(args []string) error { + // Parameter overrides must be processed before any paramaters are + // cached. Failures to cache cause the server to terminate immediately. + if chaincodeDevMode { + errStr := fmt.Sprintf("Chaincode development mode not implemented for join") + logger.Info(errStr) + return fmt.Errorf(errStr) + } + + cf, err := initCmdFactory() + if err != nil { + return err + } + + return executeJoin(cf) +} diff --git a/peer/node/node.go b/peer/node/node.go index 5bfc08c8a3a..82c9c1a56f6 100755 --- a/peer/node/node.go +++ b/peer/node/node.go @@ -19,11 +19,8 @@ package node import ( "fmt" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/op/go-logging" - "github.com/spf13/cobra" - "github.com/spf13/viper" ) const nodeFuncName = "node" @@ -35,13 +32,10 @@ var logger = logging.MustGetLogger("nodeCmd") // Cmd returns the cobra command for Node func Cmd() *cobra.Command { - //initialize the ledger sub-system - lpath := viper.GetString("peer.fileSystemPath") - kvledger.Initialize(lpath) - nodeCmd.AddCommand(startCmd()) nodeCmd.AddCommand(statusCmd()) nodeCmd.AddCommand(stopCmd()) + nodeCmd.AddCommand(joinCmd()) return nodeCmd } diff --git a/peer/node/start.go b/peer/node/start.go index f8f9b8151f3..84ec3102927 100755 --- a/peer/node/start.go +++ b/peer/node/start.go @@ -31,17 +31,15 @@ import ( "github.com/hyperledger/fabric/core" "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/comm" - "github.com/hyperledger/fabric/core/committer" "github.com/hyperledger/fabric/core/committer/noopssinglechain" "github.com/hyperledger/fabric/core/endorser" - "github.com/hyperledger/fabric/core/ledger/kvledger" "github.com/hyperledger/fabric/core/peer" "github.com/hyperledger/fabric/core/util" "github.com/hyperledger/fabric/events/producer" "github.com/hyperledger/fabric/gossip/service" "github.com/hyperledger/fabric/peer/common" pb "github.com/hyperledger/fabric/protos/peer" - "github.com/hyperledger/fabric/protos/utils" + pbutils "github.com/hyperledger/fabric/protos/utils" "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" @@ -50,12 +48,15 @@ import ( ) var chaincodeDevMode bool +var peerDefaultChain bool func startCmd() *cobra.Command { // Set the flags on the node start command. flags := nodeStartCmd.Flags() flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, "Whether peer in chaincode development mode") + flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", true, + "Whether to start peer with chain **TEST_CHAINID**") return nodeStartCmd } @@ -72,15 +73,10 @@ var nodeStartCmd = &cobra.Command{ //!!!!!----IMPORTANT----IMPORTANT---IMPORTANT------!!!! //This is a place holder for multichain work. Currently //user to create a single chain and initialize it -func createChain(chainID string) { - //create the ledger. Without this all GetLedger - //calls will panic now - kvledger.CreateLedger(chainID) - logger.Infof("Created default ledger %s", chainID) - - //deploy the system chaincodes on the chainID - chaincode.DeploySysCCs(chainID) - logger.Infof("Deployed system chaincodes on %s", chainID) +func initChainless() { + //deploy the chainless system chaincodes + chaincode.DeployChainlessSysCCs() + logger.Infof("Deployed chainless system chaincodess") } func serve(args []string) error { @@ -159,32 +155,45 @@ func serve(args []string) error { serverEndorser := endorser.NewEndorserServer() pb.RegisterEndorserServer(grpcServer, serverEndorser) - /******this will go away when we implement join command*****/ - chainID := util.GetTestChainID() - - //create the default chain (pending join) - createChain(chainID) - // Initialize gossip component bootstrap := viper.GetStringSlice("peer.gossip.bootstrap") service.InitGossipService(peerEndpoint.Address, grpcServer, bootstrap...) defer service.GetGossipService().Stop() - //this shoul not need the chainID. Delivery should be - //split up into network part and chain part. This should - //only init the network part...TBD, part of Join work - deliverService := noopssinglechain.NewDeliverService(chainID) - commit := committer.NewLedgerCommitter(kvledger.GetLedger(chainID)) + //initialize the env for chainless startup + initChainless() - // TODO: Should real configuration block - block, err := utils.MakeConfigurationBlock(util.GetTestChainID()) + // Begin startup of default chain + if peerDefaultChain { + chainID := util.GetTestChainID() - if nil != err { - panic(fmt.Sprintf("Unable to create genesis block for [%s] due to [%s]", chainID, err)) - } - deliverService.JoinChannel(commit, block) + block, err := pbutils.MakeConfigurationBlock(chainID) + if nil != err { + panic(fmt.Sprintf("Unable to create genesis block for [%s] due to [%s]", chainID, err)) + } + + //this creates block and calls JoinChannel on gossip service + if err = peer.CreateChainFromBlock(block); err != nil { + panic(fmt.Sprintf("Unable to create chain block for [%s] due to [%s]", chainID, err)) + } - defer noopssinglechain.StopDeliveryService(deliverService) + chaincode.DeploySysCCs(chainID) + logger.Infof("Deployed system chaincodes on %s", chainID) + + commit := peer.GetCommitter(chainID) + if commit == nil { + panic(fmt.Sprintf("Unable to get committer for [%s]", chainID)) + } + + //this shoul not need the chainID. Delivery should be + //split up into network part and chain part. This should + //only init the network part...TBD, part of Join work + deliverService := noopssinglechain.NewDeliverService(chainID) + + deliverService.Start(commit) + + defer noopssinglechain.StopDeliveryService(deliverService) + } logger.Infof("Starting peer with ID=%s, network ID=%s, address=%s, rootnodes=%v, validator=%v", peerEndpoint.ID, viper.GetString("peer.networkId"), peerEndpoint.Address,