github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/transaction.go (about)

     1  package dpoa
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/sixexorg/magnetic-ring/common"
     9  	"github.com/sixexorg/magnetic-ring/log"
    10  
    11  	//"github.com/sixexorg/magnetic-ring/core/signature"
    12  	//"github.com/ontio/ontology-crypto/keypair"
    13  	actorTypes "github.com/sixexorg/magnetic-ring/consense/actor"
    14  	"github.com/sixexorg/magnetic-ring/consense/dpoa/comm"
    15  	p2pmsg "github.com/sixexorg/magnetic-ring/p2pserver/common"
    16  	msgpack "github.com/sixexorg/magnetic-ring/p2pserver/message"
    17  	"time"
    18  )
    19  
    20  
    21  
    22  type TransAction struct {
    23  	msgpool  *MsgPool
    24  	peerpool *PeerPool
    25  	stateMgr *StateMgr
    26  	dpoaMgr  *DpoaMgr
    27  	p2p      *actorTypes.P2PActor
    28  	msgSendC chan *SendMsgEvent
    29  	msgRecvC map[string]chan *comm.P2pMsgPayload
    30  	cfg      *Config
    31  	quitWg   sync.WaitGroup
    32  	quitC    chan struct{}
    33  }
    34  
    35  func NewtransAction(msgpool *MsgPool, peerpool *PeerPool, stateMgr *StateMgr, dpoaMgr *DpoaMgr, p2p *actorTypes.P2PActor, cfg *Config) *TransAction {
    36  	return &TransAction{msgpool: msgpool, peerpool: peerpool, stateMgr: stateMgr, dpoaMgr: dpoaMgr, p2p: p2p, cfg: cfg,
    37  		msgRecvC: make(map[string]chan *comm.P2pMsgPayload), msgSendC: make(chan *SendMsgEvent, 16)}
    38  }
    39  
    40  func (t *TransAction) start() {
    41  	go t.sendLoop()
    42  	t.receiveLoop()
    43  }
    44  
    45  func (t *TransAction) sendLoop() {
    46  	t.quitWg.Add(1)
    47  	defer t.quitWg.Done()
    48  
    49  	for {
    50  		select {
    51  		case evt := <-t.msgSendC:
    52  			payload, err := SerializeVbftMsg(evt.Msg)
    53  			if err != nil {
    54  				log.Error("server %d failed to serialized msg (type: %d): %s", t.cfg.accountStr, evt.Msg.Type(), err)
    55  				continue
    56  			}
    57  			//log.Info("func dpoa transaction sendLoop", "msg type", evt.Msg.Type())
    58  			if evt.ToPeer == comm.BroadCast {
    59  				// broadcast
    60  				if err := t.broadcastToAll(payload); err != nil {
    61  					log.Error("server %v xmit msg (type %d): %s",
    62  						t.cfg.accountStr, evt.Msg.Type(), err)
    63  				}
    64  			} else {
    65  				if err := t.sendToPeer(evt.ToPeer, payload); err != nil {
    66  					log.Error("server %v xmit to peer %v failed: %s", t.cfg.accountStr, evt.ToPeer, err)
    67  				}
    68  			}
    69  		case <-t.quitC:
    70  			log.Info("server %d msgSendLoop quit", t.cfg.accountStr)
    71  			return
    72  		}
    73  	}
    74  }
    75  
    76  func (t *TransAction) broadcastToAll(data []byte) error {
    77  	msg := &p2pmsg.ConsensusPayload{
    78  		Data:  data,
    79  		Owner: t.cfg.account.PublicKey(),
    80  	}
    81  
    82  	buf := new(bytes.Buffer)
    83  	if err := msg.SerializeUnsigned(buf); err != nil {
    84  		return fmt.Errorf("failed to serialize consensus msg", "err", err)
    85  	}
    86  	var err error
    87  	msg.Signature, err = t.cfg.account.Sign(common.Sha256(buf.Bytes()))
    88  	if err != nil {
    89  		log.Error("sign transaction transaction91 occured error","error",err)
    90  		return err
    91  	}
    92  	t.p2p.Broadcast(msg)
    93  	return nil
    94  }
    95  
    96  func (t *TransAction) sendToPeer(peerIdx string, data []byte) error {
    97  	peer := t.peerpool.getPeer(peerIdx)
    98  	if peer == nil {
    99  		return fmt.Errorf("send peer failed: failed to get peer", "peerIdx", peerIdx)
   100  	}
   101  	msg := &p2pmsg.ConsensusPayload{
   102  		Data:  data,
   103  		Owner: t.cfg.account.PublicKey(),
   104  	}
   105  
   106  	buf := new(bytes.Buffer)
   107  	if err := msg.SerializeUnsigned(buf); err != nil {
   108  		return fmt.Errorf("failed to serialize consensus msg", "err", err)
   109  	}
   110  	var err error
   111  	msg.Signature, err = t.cfg.account.Sign(common.Sha256(buf.Bytes()))
   112  
   113  	if err != nil {
   114  		log.Error("t.cfg.account.sign transaction116",)
   115  		return err
   116  	}
   117  
   118  	cons := msgpack.NewConsensus(msg)
   119  	p2pid, present := t.peerpool.getP2pId(peerIdx)
   120  	if present {
   121  		t.p2p.Transmit(p2pid, cons)
   122  	} else {
   123  		log.Error("sendToPeer transmit failed index:", "peerIdx", peerIdx)
   124  	}
   125  	return nil
   126  }
   127  
   128  func (t *TransAction) receiveLoop() {
   129  	for _, p := range t.cfg.Peers {
   130  		if _, present := t.msgRecvC[p]; !present {
   131  			t.msgRecvC[string(p)] = make(chan *comm.P2pMsgPayload, 1024)
   132  		}
   133  
   134  		go func(pname string) {
   135  			if err := t.run(pname); err != nil {
   136  				log.Error("server %d, processor on peer failed: %s",
   137  					"accountStr", t.cfg.accountStr, "err", err)
   138  			}
   139  		}(p)
   140  	}
   141  }
   142  func (t *TransAction) receiveFromPeer(peerIdx string) (string, []byte, error) {
   143  	if C, present := t.msgRecvC[peerIdx]; present {
   144  		select {
   145  		case payload := <-C:
   146  			if payload != nil {
   147  				return payload.FromPeer, payload.Payload.Data, nil
   148  			}
   149  
   150  		case <-t.quitC:
   151  			return "", nil, fmt.Errorf("server %d quit", t.cfg.accountStr)
   152  		}
   153  	}
   154  
   155  	return "", nil, fmt.Errorf("nil consensus payload")
   156  }
   157  
   158  func (t *TransAction) run(peerPubKey string) error {
   159  	// broadcast heartbeat
   160  	t.heartbeat()
   161  
   162  	if err := t.peerpool.waitPeerConnected(peerPubKey); err != nil {
   163  		return err
   164  	}
   165  
   166  	defer func() {
   167  		// TODO: handle peer disconnection here
   168  		log.Warn("server %d: disconnected with peer", "accountStr", t.cfg.accountStr)
   169  		close(t.msgRecvC[peerPubKey])
   170  		delete(t.msgRecvC, peerPubKey)
   171  
   172  		t.peerpool.peerDisconnected(peerPubKey)
   173  		t.stateMgr.StateEventC <- &StateEvent{
   174  			Type: UpdatePeerState,
   175  			peerState: &PeerState{
   176  				peerIdx:   peerPubKey,
   177  				connected: false,
   178  			},
   179  		}
   180  	}()
   181  	errC := make(chan error)
   182  	go func() {
   183  		for {
   184  			fromPeer, msgData, err := t.receiveFromPeer(peerPubKey)
   185  			if err != nil {
   186  				errC <- err
   187  				return
   188  			}
   189  			msg, err := DeserializeVbftMsg(msgData)
   190  
   191  			if err != nil {
   192  				log.Error("server %d failed to deserialize vbft msg (len %d): %s", "accountStr", t.cfg.accountStr, "len(msgData)", len(msgData), "err", err)
   193  			} else {
   194  				pk := t.peerpool.GetPeerPubKey(fromPeer)
   195  				if pk == nil {
   196  					log.Error("server %d failed to get peer %d pubkey", "accountStr", t.cfg.accountStr, "fromPeer", fromPeer)
   197  					continue
   198  				}
   199  
   200  				if err := msg.Verify(pk); err != nil {
   201  					log.Error("server %d failed to verify msg, type %d, err: %s",
   202  						"accountStr", t.cfg.accountStr, "type", msg.Type(), "err", err)
   203  					continue
   204  				}
   205  
   206  				t.handleRecvMsg(fromPeer, msg, hashData(msgData))
   207  			}
   208  		}
   209  	}()
   210  
   211  	return <-errC
   212  }
   213  
   214  func (t *TransAction) handleRecvMsg(peerIdx string, msg comm.ConsensusMsg, msgHash common.Hash) {
   215  	if t.msgpool.HasMsg(msg, msgHash) {
   216  		// dup msg checking
   217  		log.Debug("dup msg with msg type %d from %d", "type", msg.Type(), "peeridx", peerIdx)
   218  		return
   219  	}
   220  
   221  	switch msg.Type() {
   222  	case comm.ConsenseDone:
   223  		t.ConsenseDone(peerIdx, msg, msgHash)
   224  	case comm.ConsensePrepare:
   225  		t.ConsensePrepare(peerIdx, msg, msgHash)
   226  	case comm.ConsensePromise:
   227  		t.ConsensePromise(peerIdx, msg, msgHash)
   228  	case comm.ConsenseProposer:
   229  		t.ConsenseProposer(peerIdx, msg, msgHash)
   230  	case comm.ConsenseAccept:
   231  		t.ConsenseAccept(peerIdx, msg, msgHash)
   232  	case comm.ViewTimeout:
   233  		t.ViewTimeout(peerIdx, msg, msgHash)
   234  	case comm.EvilEvent:
   235  
   236  	case comm.EventFetchMessage:
   237  
   238  	case comm.EventFetchRspMessage:
   239  
   240  	case comm.EvilFetchMessage:
   241  
   242  	case comm.EvilFetchRspMessage:
   243  
   244  	case comm.EarthFetchRspSigs:
   245  		t.EarthFetchRspSigs(peerIdx, msg, msgHash)
   246  	case comm.PeerHeartbeatMessage:
   247  		t.PeerHeartbeatMessage(peerIdx, msg, msgHash)
   248  	case comm.BlockFetchMessage:
   249  
   250  	case comm.BlockFetchRespMessage:
   251  
   252  	case comm.BlockInfoFetchMessage:
   253  		t.BlockInfoFetchMessage(peerIdx, msg, msgHash)
   254  	case comm.BlockInfoFetchRespMessage:
   255  
   256  	case comm.TimeoutFetchMessage:
   257  
   258  	case comm.TimeoutFetchRspMessage:
   259  	}
   260  }
   261  func (t *TransAction) GetCurrentBlockNo() uint64 {
   262  	return t.dpoaMgr.store.db.GetCurrentBlockHeight() + 1
   263  }
   264  
   265  func (t *TransAction) GetCommittedBlockNo() uint64 {
   266  	return t.dpoaMgr.store.getLatestBlockNumber()
   267  }
   268  
   269  func (t *TransAction) heartbeat() {
   270  	fmt.Println("TransActionheartbeat=========>>>>>>>>>>",time.Now().String())
   271  	log.Info("TransActionheartbeat=========>>>>>>>>>>", "time:", time.Now().String())
   272  	//	build heartbeat msg
   273  	msg, err := constructHeartbeatMsg(t.dpoaMgr.store)
   274  	if err != nil {
   275  		log.Error("failed to build heartbeat msg", "err", err)
   276  		return
   277  	}
   278  
   279  	//	send to peer
   280  	t.msgSendC <- &SendMsgEvent{
   281  		ToPeer: comm.BroadCast,
   282  		Msg:    msg,
   283  	}
   284  }
   285  
   286  func (t *TransAction) processHeartbeatMsg(peerIdx string, msg *comm.PeerHeartbeatMsg) error {
   287  
   288  	if err := t.peerpool.peerHeartbeat(peerIdx, msg); err != nil {
   289  		return fmt.Errorf("failed to update peer %d: %s", peerIdx, err)
   290  	}
   291  	//log.Debug("server %v received heartbeat from peer %d, blkNum %d", peerIdx, msg.CommittedBlockNumber)
   292  	t.stateMgr.StateEventC <- &StateEvent{
   293  		Type: UpdatePeerState,
   294  		peerState: &PeerState{
   295  			peerIdx:   peerIdx,
   296  			connected: true,
   297  			//chainConfigView:   msg.ChainConfigView,
   298  			committedBlockNum: msg.CommittedBlockNumber,
   299  		},
   300  	}
   301  
   302  	return nil
   303  }
   304  
   305  func (t *TransAction) recvMsg(peer string, msg *comm.P2pMsgPayload) {
   306  	if C, present := t.msgRecvC[peer]; present {
   307  		C <- msg
   308  	} else {
   309  		log.Error("consensus msg without receiver node", "peerid", peer)
   310  		return
   311  	}
   312  }
   313  
   314  func (t *TransAction) sendMsg(data *SendMsgEvent) {
   315  	t.msgSendC <- data
   316  }