github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/orderer/sample_clients/single_tx_client/single_tx_client.go (about)

     1  /*
     2  Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
    24  	cb "github.com/hyperledger/fabric/protos/common"
    25  	ab "github.com/hyperledger/fabric/protos/orderer"
    26  	"github.com/hyperledger/fabric/protos/utils"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  	"github.com/op/go-logging"
    30  	"golang.org/x/net/context"
    31  	"google.golang.org/grpc"
    32  )
    33  
    34  var logger = logging.MustGetLogger("single_tx_client")
    35  
    36  var UPDATE byte = 0
    37  var SEND byte = 1
    38  
    39  var NEEDED_UPDATES = 2
    40  var NEEDED_SENT = 1
    41  
    42  func main() {
    43  	logger.Info("Creating an Atomic Broadcast GRPC connection.")
    44  	timeout := 4 * time.Second
    45  	clientconn, err := grpc.Dial(":7101", grpc.WithBlock(), grpc.WithTimeout(timeout), grpc.WithInsecure())
    46  	if err != nil {
    47  		logger.Errorf("Failed to connect to GRPC: %s", err)
    48  		return
    49  	}
    50  	client := ab.NewAtomicBroadcastClient(clientconn)
    51  
    52  	resultch := make(chan byte)
    53  	errorch := make(chan error)
    54  
    55  	logger.Info("Starting a goroutine waiting for ledger updates.")
    56  	go updateReceiver(resultch, errorch, client)
    57  
    58  	logger.Info("Starting a single broadcast sender goroutine.")
    59  	go broadcastSender(resultch, errorch, client)
    60  
    61  	checkResults(resultch, errorch)
    62  }
    63  
    64  func checkResults(resultch chan byte, errorch chan error) {
    65  	l := len(errorch)
    66  	for i := 0; i < l; i++ {
    67  		errres := <-errorch
    68  		logger.Error(errres)
    69  	}
    70  
    71  	updates := 0
    72  	sentBroadcast := 0
    73  	for i := 0; i < 3; i++ {
    74  		select {
    75  		case result := <-resultch:
    76  			switch result {
    77  			case UPDATE:
    78  				updates++
    79  			case SEND:
    80  				sentBroadcast++
    81  			}
    82  		case <-time.After(30 * time.Second):
    83  			continue
    84  		}
    85  	}
    86  	if updates != NEEDED_UPDATES {
    87  		logger.Errorf("We did not get all the ledger updates.")
    88  	} else if sentBroadcast != NEEDED_SENT {
    89  		logger.Errorf("We were unable to send all the broadcasts.")
    90  	} else {
    91  		logger.Info("Successfully sent and received everything.")
    92  	}
    93  }
    94  
    95  func updateReceiver(resultch chan byte, errorch chan error, client ab.AtomicBroadcastClient) {
    96  	logger.Info("{Update Receiver} Creating a ledger update delivery stream.")
    97  	dstream, err := client.Deliver(context.Background())
    98  	if err != nil {
    99  		errorch <- fmt.Errorf("Failed to get Deliver stream: %s", err)
   100  		return
   101  	}
   102  	dstream.Send(&cb.Envelope{
   103  		Payload: utils.MarshalOrPanic(&cb.Payload{
   104  			Header: &cb.Header{
   105  				ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   106  					ChannelId: provisional.TestChainID,
   107  				}),
   108  				SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{}),
   109  			},
   110  			Data: utils.MarshalOrPanic(&ab.SeekInfo{
   111  				Start:    &ab.SeekPosition{Type: &ab.SeekPosition_Newest{}},
   112  				Stop:     &ab.SeekPosition{Type: &ab.SeekPosition_Newest{}},
   113  				Behavior: ab.SeekInfo_BLOCK_UNTIL_READY,
   114  			}),
   115  		}),
   116  	})
   117  
   118  	logger.Info("{Update Receiver} Listening to ledger updates.")
   119  	for i := 0; i < 2; i++ {
   120  		m, inerr := dstream.Recv()
   121  		if inerr != nil {
   122  			errorch <- fmt.Errorf("Failed to receive consensus: %s", inerr)
   123  			return
   124  		}
   125  		b := m.Type.(*ab.DeliverResponse_Block)
   126  		logger.Info("{Update Receiver} Received a ledger update.")
   127  		for i, tx := range b.Block.Data.Data {
   128  			pl := &cb.Payload{}
   129  			e := &cb.Envelope{}
   130  			merr1 := proto.Unmarshal(tx, e)
   131  			merr2 := proto.Unmarshal(e.Payload, pl)
   132  			if merr1 == nil && merr2 == nil {
   133  				logger.Infof("{Update Receiver} %d - %v", i+1, pl.Data)
   134  			}
   135  		}
   136  		resultch <- UPDATE
   137  	}
   138  	logger.Info("{Update Receiver} Exiting...")
   139  }
   140  
   141  func broadcastSender(resultch chan byte, errorch chan error, client ab.AtomicBroadcastClient) {
   142  	logger.Info("{Broadcast Sender} Waiting before sending.")
   143  	<-time.After(5 * time.Second)
   144  	bstream, err := client.Broadcast(context.Background())
   145  	if err != nil {
   146  		errorch <- fmt.Errorf("Failed to get broadcast stream: %s", err)
   147  		return
   148  	}
   149  	bs := []byte{0, 1, 2, 3}
   150  	pl := &cb.Payload{
   151  		Header: &cb.Header{
   152  			ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
   153  				ChannelId: provisional.TestChainID,
   154  			}),
   155  		},
   156  		Data: bs,
   157  	}
   158  	mpl, err := proto.Marshal(pl)
   159  	if err != nil {
   160  		panic("Failed to marshal payload.")
   161  	}
   162  	bstream.Send(&cb.Envelope{Payload: mpl})
   163  	logger.Infof("{Broadcast Sender} Broadcast sent: %v", bs)
   164  	logger.Info("{Broadcast Sender} Exiting...")
   165  	resultch <- SEND
   166  }