Skip to content

Commit

Permalink
[FAB-8124] Move genesis block + joinchan to resource
Browse files Browse the repository at this point in the history
This patch moves the orderer-based Genesis Block and
JoinChannel to the resource package.

Change-Id: I70899775f5ce9c851b0b3a8b24581be7b7f1a719
Signed-off-by: Troy Ronda <troy@troyronda.com>
  • Loading branch information
troyronda committed Feb 7, 2018
1 parent 578506b commit dbcc63a
Show file tree
Hide file tree
Showing 20 changed files with 409 additions and 419 deletions.
1 change: 1 addition & 0 deletions api/apicore/fabric.go
Expand Up @@ -24,5 +24,6 @@ type FabricProvider interface {

NewPeer(url string, certificate *x509.Certificate, serverHostOverride string) (apifabclient.Peer, error)
NewPeerFromConfig(peerCfg *apiconfig.NetworkPeer) (apifabclient.Peer, error)
NewOrdererFromConfig(cfg *apiconfig.OrdererConfig) (apifabclient.Orderer, error)
NewUser(name string, signingIdentity *apifabclient.SigningIdentity) (apifabclient.User, error)
}
15 changes: 2 additions & 13 deletions api/apifabclient/channel.go
Expand Up @@ -28,12 +28,13 @@ type Channel interface {

Name() string
ChannelConfig() (*common.ConfigEnvelope, error)

SendInstantiateProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope,
collConfig []*common.CollectionConfig, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error)
SendUpgradeProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error)

// Network
// TODO: Use PeerEndorser
// Deprecated: getters/setters are deprecated from interface.
AddPeer(peer Peer) error
RemovePeer(peer Peer)
Peers() []Peer
Expand All @@ -47,12 +48,6 @@ type Channel interface {
MSPManager() msp.MSPManager
OrganizationUnits() ([]string, error)

// Channel Info
GenesisBlock() (*common.Block, error)
JoinChannel(request *JoinChannelRequest) error
UpdateChannel() bool
IsReadonly() bool

// Query
QueryInfo() (*common.BlockchainInfo, error)
QueryBlock(blockNumber int) (*common.Block, error)
Expand All @@ -70,9 +65,3 @@ type OrgAnchorPeer struct {
Host string
Port int32
}

// JoinChannelRequest allows a set of peers to transact on a channel on the network
type JoinChannelRequest struct {
Targets []Peer
GenesisBlock *common.Block
}
11 changes: 11 additions & 0 deletions api/apifabclient/resource.go
Expand Up @@ -18,6 +18,9 @@ type Resource interface {
QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error)
QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error)

GenesisBlockFromOrderer(channelName string, orderer Orderer) (*common.Block, error)
JoinChannel(request JoinChannelRequest) error

// TODO - the following methods are utilities
ExtractChannelConfig(configEnvelope []byte) ([]byte, error)
SignChannelConfig(config []byte, signer IdentityContext) (*common.ConfigSignature, error)
Expand Down Expand Up @@ -66,3 +69,11 @@ type CCPackage struct {
Type pb.ChaincodeSpec_Type
Code []byte
}

// JoinChannelRequest allows a set of peers to transact on a channel on the network
type JoinChannelRequest struct {
// The name of the channel to be joined.
Name string
GenesisBlock *common.Block
Targets []ProposalProcessor
}
83 changes: 1 addition & 82 deletions pkg/fabric-client/channel/block.go
Expand Up @@ -11,93 +11,12 @@ import (

ab "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/protos/orderer"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
protos_utils "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/utils"

ccomm "github.com/hyperledger/fabric-sdk-go/pkg/config/comm"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/txn"
"github.com/pkg/errors"
)

// GenesisBlock returns the genesis block from the defined orderer that may be
// used in a join request
// request: An object containing the following fields:
// `txId` : required - String of the transaction id
// `nonce` : required - Integer of the once time number
//
// See /protos/peer/proposal_response.proto
func (c *Channel) GenesisBlock() (*common.Block, error) {
logger.Debug("GenesisBlock - start")

// verify that we have an orderer configured
if len(c.Orderers()) == 0 {
return nil, errors.New("GenesisBlock missing orderer assigned to this channel for the GenesisBlock request")
}

txnID, err := txn.NewID(c.clientContext)
if err != nil {
return nil, errors.WithMessage(err, "failed to calculate transaction id")
}

// now build the seek info , will be used once the channel is created
// to get the genesis block back
seekStart := newSpecificSeekPosition(0)
seekStop := newSpecificSeekPosition(0)
seekInfo := &ab.SeekInfo{
Start: seekStart,
Stop: seekStop,
Behavior: ab.SeekInfo_BLOCK_UNTIL_READY,
}

tlsCertHash := ccomm.TLSCertHash(c.clientContext.Config())
channelHeaderOpts := txn.ChannelHeaderOpts{
ChannelID: c.Name(),
TxnID: txnID,
TLSCertHash: tlsCertHash,
}
seekInfoHeader, err := txn.CreateChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, channelHeaderOpts)
if err != nil {
return nil, errors.Wrap(err, "BuildChannelHeader failed")
}
seekHeader, err := txn.CreateHeader(c.clientContext, seekInfoHeader, txnID)
if err != nil {
return nil, errors.Wrap(err, "BuildHeader failed")
}
seekPayload := &common.Payload{
Header: seekHeader,
Data: protos_utils.MarshalOrPanic(seekInfo),
}
seekPayloadBytes := protos_utils.MarshalOrPanic(seekPayload)

signedEnvelope, err := txn.SignPayload(c.clientContext, seekPayloadBytes)
if err != nil {
return nil, errors.WithMessage(err, "SignPayload failed")
}

block, err := txn.SendEnvelope(c.clientContext, signedEnvelope, c.Orderers())
if err != nil {
return nil, errors.WithMessage(err, "SendEnvelope failed")
}
return block, nil
}

// createSeekGenesisBlockRequest creates a seek request for block 0 on the specified
// channel. This request is sent to the ordering service to request blocks
func createSeekGenesisBlockRequest(channelName string, creator []byte) []byte {
return protos_utils.MarshalOrPanic(&common.Payload{
Header: &common.Header{
ChannelHeader: protos_utils.MarshalOrPanic(&common.ChannelHeader{
ChannelId: channelName,
}),
SignatureHeader: protos_utils.MarshalOrPanic(&common.SignatureHeader{Creator: creator}),
},
Data: protos_utils.MarshalOrPanic(&ab.SeekInfo{
Start: &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 0}}},
Stop: &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 0}}},
Behavior: ab.SeekInfo_BLOCK_UNTIL_READY,
}),
})
}

// block retrieves the block at the given position
func (c *Channel) block(pos *ab.SeekPosition) (*common.Block, error) {

Expand All @@ -112,7 +31,7 @@ func (c *Channel) block(pos *ab.SeekPosition) (*common.Block, error) {
}

channelHeaderOpts := txn.ChannelHeaderOpts{
ChannelID: c.Name(),
ChannelID: c.name,
TxnID: txnID,
TLSCertHash: ccomm.TLSCertHash(c.clientContext.Config()),
}
Expand Down
59 changes: 0 additions & 59 deletions pkg/fabric-client/channel/block_test.go

This file was deleted.

100 changes: 0 additions & 100 deletions pkg/fabric-client/channel/txn.go
Expand Up @@ -7,9 +7,6 @@ SPDX-License-Identifier: Apache-2.0
package channel

import (
"fmt"
"net/http"

"github.com/golang/protobuf/proto"
"github.com/pkg/errors"

Expand Down Expand Up @@ -62,103 +59,6 @@ func (c *Channel) SendTransactionProposal(request fab.ChaincodeInvokeRequest, ta
return tpr, tp.TxnID, nil
}

// JoinChannel sends a join channel proposal to one or more endorsing peers
// Will get the genesis block from the defined orderer to be used
// in the proposal.
// request: An object containing the following fields:
// `targets` : required - An array of `Peer` objects that will join
// this channel
// `block` : the genesis block of the channel
// see GenesisBlock() method
// See /protos/peer/proposal_response.proto
func (c *Channel) JoinChannel(request *fab.JoinChannelRequest) error {
logger.Debug("joinChannel - start")

// verify that we have targets (Peers) to join this channel
// defined by the caller
if request == nil {
return errors.New("join channel request is required")
}

// verify that a Peer(s) has been selected to join this channel
if request.Targets == nil {
return errors.New("missing targets input parameter with the peer objects for the join channel proposal")
}

if request.GenesisBlock == nil {
return errors.New("missing block input parameter with the required genesis block")
}

txnID, err := txn.NewID(c.clientContext)
if err != nil {
return errors.WithMessage(err, "failed to calculate transaction id")
}

creator, err := c.clientContext.Identity()
if err != nil {
return errors.WithMessage(err, "getting creator identity failed")
}

genesisBlockBytes, err := proto.Marshal(request.GenesisBlock)
if err != nil {
return errors.Wrap(err, "marshal genesis block failed")
}

// Create join channel transaction proposal for target peers
joinCommand := "JoinChain"
var args [][]byte
args = append(args, []byte(joinCommand))
args = append(args, genesisBlockBytes)
ccSpec := &pb.ChaincodeSpec{
Type: pb.ChaincodeSpec_GOLANG,
ChaincodeId: &pb.ChaincodeID{Name: "cscc"},
Input: &pb.ChaincodeInput{Args: args},
}
cciSpec := &pb.ChaincodeInvocationSpec{
ChaincodeSpec: ccSpec,
}

proposal, _, err := protos_utils.CreateChaincodeProposalWithTxIDNonceAndTransient(txnID.ID, common.HeaderType_ENDORSER_TRANSACTION, "", cciSpec, txnID.Nonce, creator, nil)
if err != nil {
return errors.Wrap(err, "failed to build chaincode proposal")
}
signedProposal, err := txn.SignProposal(c.clientContext, proposal)
if err != nil {
return errors.WithMessage(err, "signing proposal failed")
}
transactionProposal := &fab.TransactionProposal{
TxnID: txnID,
SignedProposal: signedProposal,
Proposal: proposal,
}

targets := peersToTxnProcessors(request.Targets)

// Send join proposal
proposalResponses, err := txn.SendProposal(transactionProposal, targets)
if err != nil {
return errors.WithMessage(err, "sending join transaction proposal failed")
}
// Check responses from target peers for success/failure and join all errors
var joinError string
for _, response := range proposalResponses {
if response.Err != nil {
joinError = joinError +
fmt.Sprintf("join channel proposal response error: %s \n",
response.Err.Error())
} else if response.Status != http.StatusOK {
joinError = joinError +
fmt.Sprintf("join channel proposal HTTP response status: %d \n", response.Status)
}
}

if joinError != "" {
return errors.New(joinError)
}

return nil
}

// SendInstantiateProposal sends an instantiate proposal to one or more endorsing peers.
// chaincodeName: required - The name of the chain.
// args: optional - string Array arguments specific to the chaincode being instantiated
Expand Down

0 comments on commit dbcc63a

Please sign in to comment.