github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/consensus_pbft/helper/helper.go (about)

     1  /*
     2  Copyright IBM Corp. 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 helper
    18  
    19  import (
    20  	"fmt"
    21  
    22  
    23  	"github.com/ethereum/go-ethereum/consensus_pbft"
    24  	"github.com/ethereum/go-ethereum/consensus_pbft/executor"
    25  //	"github.com/ethereum/go-ethereum/consensus_pbft/persist"
    26  	"github.com/ethereum/go-ethereum/consensus_pbft/peer"
    27  	"github.com/ethereum/go-ethereum/consensus_pbft/consensusInterface"
    28  	"github.com/ethereum/go-ethereum/log"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/consensus_pbft/pbftTypes"
    31  	"github.com/ethereum/go-ethereum/consensus_pbft/message"
    32  	"github.com/ethereum/go-ethereum/consensus_pbft/helper/persist"
    33  )
    34  
    35  // Helper contains the reference to the peer's MessageHandlerCoordinator
    36  type Helper struct {
    37  	consenter    consensus_pbft.Consenter
    38  	coordinator  peer.MessageHandlerCoordinator
    39  	identify 	consensusInterface.ValidatorIdentifyInterface
    40  	secOn        bool
    41  	valid        bool // Whether we believe the state is up to date
    42  	Node	    consensusInterface.NodeInterface
    43  	curBatch     []*types.Transaction       // TODO, remove after issue 579
    44  //	curBatchErrs []*types.TransactionResult // TODO, remove after issue 579
    45  	persist.Helper
    46  
    47  	executor consensus_pbft.Executor
    48  }
    49  
    50  // NewHelper constructs the consensus helper object
    51  func NewHelper(mhc peer.MessageHandlerCoordinator) *Helper {
    52  	h := &Helper{
    53  		coordinator: mhc,
    54  		secOn:       false,//viper.GetBool("security.enabled"),
    55  		Node:   mhc.GetChainNode(),
    56  		valid:       true, // Assume our state is consistent until we are told otherwise, actual consensus (pbft) will invalidate this immediately, but noops will not
    57  	}
    58  
    59  	h.executor = executor.NewImpl(h, mhc)
    60  	return h
    61  }
    62  
    63  func (h *Helper) setConsenter(c consensus_pbft.Consenter) {
    64  	h.consenter = c
    65  	h.executor.Start() // The consenter may be expecting a callback from the executor because of state transfer completing, it will miss this if we start the executor too early
    66  }
    67  
    68  // GetNetworkInfo returns the PeerEndpoints of the current validator and the entire validating network
    69  func (h *Helper) GetNetworkNodes() (self pbftTypes.Peer, network []pbftTypes.Peer, err error) {
    70  	ep := h.coordinator.(pbftTypes.Peer)
    71  	self = ep
    72  
    73  	peers, err := h.coordinator.GetPeers()
    74  	if err != nil {
    75  		return self, network, fmt.Errorf("Couldn't retrieve list of peers: %v", err)
    76  	}
    77  //	peers := peersMsg()
    78  	for _, endpoint := range peers {
    79  		if true { //endpoint.Type == peer.PeerEndpoint_VALIDATOR {
    80  			network = append(network, endpoint)
    81  		}
    82  	}
    83  	network = append(network, self)
    84  
    85  	return
    86  }
    87  
    88  // GetNetworkHandles returns the PeerIDs of the current validator and the entire validating network
    89  func (h *Helper) GetNetworkNodeIDs() (self *pbftTypes.PeerID, network []*pbftTypes.PeerID, err error) {
    90  	selfEP, networkEP, err := h.GetNetworkNodes()
    91  	if err != nil {
    92  		return self, network, fmt.Errorf("Couldn't retrieve validating network's endpoints: %v", err)
    93  	}
    94  
    95  	self = selfEP.GetPeerId()
    96  
    97  	for _, endpoint := range networkEP {
    98  		network = append(network, endpoint.GetPeerId())
    99  	}
   100  	network = append(network, self)
   101  
   102  	return
   103  }
   104  
   105  // Broadcast sends a message to all validating peers
   106  func (h *Helper) Broadcast(msg *message.Message, peerType consensusInterface.PeerEndpoint_Type) error {
   107  	errors := h.coordinator.Broadcast(msg, peerType)
   108  	if len(errors) > 0 {
   109  		return fmt.Errorf("Couldn't broadcast successfully")
   110  	}
   111  	return nil
   112  }
   113  
   114  // Unicast sends a message to a specified receiver
   115  func (h *Helper) Unicast(msg *message.Message, receiver *pbftTypes.PeerID) error {
   116  	return h.coordinator.Unicast(msg, receiver)
   117  }
   118  
   119  // Sign a message with this validator's signing key
   120  func (h *Helper) Sign(msg []byte) ([]byte, error) {
   121  //	if h.secOn {
   122  //		return h.secHelper.Sign(msg)
   123  //	}
   124  	log.Debug("Security is disabled")
   125  	return msg, nil
   126  }
   127  
   128  // Verify that the given signature is valid under the given replicaID's verification key
   129  // If replicaID is nil, use this validator's verification key
   130  // If the signature is valid, the function should return nil
   131  func (h *Helper) Verify(replicaID pbftTypes.ReplicaID, signature []byte, message []byte) error {
   132  	if !h.secOn {
   133  		log.Debug("Security is disabled")
   134  		return nil
   135  	}
   136  
   137  	log.Debug("Verify message from: %v", replicaID)
   138  	_, network, err := h.GetNetworkNodeIDs()
   139  	if err != nil {
   140  		return fmt.Errorf("Couldn't retrieve validating network's endpoints: %v", err)
   141  	}
   142  
   143  	// check that the sender is a valid replica
   144  	// if so, call crypto verify() with that endpoint's pkiID
   145  	for _, endpoint := range network {
   146  		log.Debug("Endpoint name: %v", endpoint)
   147  		endId,_ := h.identify.GetValidatorID(endpoint)
   148  		if replicaID == endId {
   149  			return h.Node.Verify(endpoint, signature, message)
   150  		}
   151  	}
   152  	return fmt.Errorf("Could not verify message from %s (unknown peer)", replicaID)
   153  }
   154  
   155  // BeginTxBatch gets invoked when the next round
   156  // of transaction-batch execution begins
   157  func (h *Helper) BeginTaskBatch(id interface{}) error {
   158  /*	ledger, err := ledger.GetLedger()
   159  	if err != nil {
   160  		return fmt.Errorf("Failed to get the ledger: %v", err)
   161  	}
   162  	if err := ledger.BeginTxBatch(id); err != nil {
   163  		return fmt.Errorf("Failed to begin transaction with the ledger: %v", err)
   164  	}
   165  	h.curBatch = nil     // TODO, remove after issue 579
   166  	h.curBatchErrs = nil // TODO, remove after issue 579
   167  */
   168  	return nil
   169  }
   170  
   171  // ExecTxs executes all the transactions listed in the txs array
   172  // one-by-one. If all the executions are successful, it returns
   173  // the candidate global state hash, and nil error array.
   174  func (h *Helper) ExecTasks(id interface{}, txs []*message.Task) ([]*message.Result, error) {
   175  	// TODO id is currently ignored, fix once the underlying implementation accepts id
   176  
   177  	// The secHelper is set during creat ChaincodeSupport, so we don't need this step
   178  	// cxt := context.WithValue(context.Background(), "security", h.coordinator.GetSecHelper())
   179  	// TODO return directly once underlying implementation no longer returns []error
   180  /*
   181  	succeededTxs, res, ccevents, txerrs, err := chaincode.ExecuteTransactions(context.Background(), chaincode.DefaultChain, txs)
   182  
   183  	h.curBatch = append(h.curBatch, succeededTxs...) // TODO, remove after issue 579
   184  
   185  	//copy errs to result
   186  	txresults := make([]*pb.TransactionResult, len(txerrs))
   187  
   188  	//process errors for each transaction
   189  	for i, e := range txerrs {
   190  		//NOTE- it'll be nice if we can have error values. For now success == 0, error == 1
   191  		if txerrs[i] != nil {
   192  			txresults[i] = &pb.TransactionResult{Txid: txs[i].Hash(), Error: e.Error(), ErrorCode: 1, ChaincodeEvent: ccevents[i]}
   193  		} else {
   194  			txresults[i] = &pb.TransactionResult{Txid: txs[i].Hash(), ChaincodeEvent: ccevents[i]}
   195  		}
   196  	}
   197  	h.curBatchErrs = append(h.curBatchErrs, txresults...) // TODO, remove after issue 579
   198  
   199  	return res, err
   200  */
   201  	return nil,nil
   202  }
   203  
   204  // CommitTxBatch gets invoked when the current transaction-batch needs
   205  // to be committed. This function returns successfully iff the
   206  // transactions details and state changes (that may have happened
   207  // during execution of this transaction-batch) have been committed to
   208  // permanent storage.
   209  func (h *Helper) CommitTaskBatch(id interface{}, metadata []byte) (*message.StateInfo, error) {
   210  	/*
   211  	ledger, err := ledger.GetLedger()
   212  	if err != nil {
   213  		return nil, fmt.Errorf("Failed to get the ledger: %v", err)
   214  	}
   215  	// TODO fix this one the ledger has been fixed to implement
   216  	if err := ledger.CommitTxBatch(id, h.curBatch, h.curBatchErrs, metadata); err != nil {
   217  		return nil, fmt.Errorf("Failed to commit transaction to the ledger: %v", err)
   218  	}
   219  
   220  	size := ledger.GetBlockchainSize()
   221  	defer func() {
   222  		h.curBatch = nil     // TODO, remove after issue 579
   223  		h.curBatchErrs = nil // TODO, remove after issue 579
   224  	}()
   225  
   226  	block, err := ledger.GetBlockByNumber(size - 1)
   227  	if err != nil {
   228  		return nil, fmt.Errorf("Failed to get the block at the head of the chain: %v", err)
   229  	}
   230  
   231  	logger.Debugf("Committed block with %d transactions, intended to include %d", len(block.Transactions), len(h.curBatch))
   232  
   233  	return block, nil
   234  	*/
   235  	return nil,nil
   236  }
   237  
   238  // RollbackTxBatch discards all the state changes that may have taken
   239  // place during the execution of current transaction-batch
   240  func (h *Helper) RollbackTaskBatch(id interface{}) error {
   241  	/*
   242  	ledger, err := ledger.GetLedger()
   243  	if err != nil {
   244  		return fmt.Errorf("Failed to get the ledger: %v", err)
   245  	}
   246  	if err := ledger.RollbackTxBatch(id); err != nil {
   247  		return fmt.Errorf("Failed to rollback transaction with the ledger: %v", err)
   248  	}
   249  	h.curBatch = nil     // TODO, remove after issue 579
   250  	h.curBatchErrs = nil // TODO, remove after issue 579
   251  	return nil
   252  	*/
   253  	return nil
   254  }
   255  
   256  // PreviewCommitTxBatch retrieves a preview of the block info blob (as
   257  // returned by GetBlockchainInfoBlob) that would describe the
   258  // blockchain if CommitTxBatch were invoked.  The blockinfo will
   259  // change if additional ExecTXs calls are invoked.
   260  func (h *Helper) PreviewCommitTaskBatch(id interface{}, metadata []byte) ([]byte, error) {
   261  	/*
   262  	ledger, err := ledger.GetLedger()
   263  	if err != nil {
   264  		return nil, fmt.Errorf("Failed to get the ledger: %v", err)
   265  	}
   266  	// TODO fix this once the underlying API is fixed
   267  	blockInfo, err := ledger.GetTXBatchPreviewBlockInfo(id, h.curBatch, metadata)
   268  	if err != nil {
   269  		return nil, fmt.Errorf("Failed to preview commit: %v", err)
   270  	}
   271  	rawInfo, _ := proto.Marshal(blockInfo)
   272  	return rawInfo, nil
   273  	*/
   274  	return nil,nil
   275  }
   276  
   277  // GetBlock returns a block from the chain
   278  func (h *Helper) GetState(blockNumber uint64) (state *message.StateInfo, err error) {
   279  	/*
   280  	ledger, err := ledger.GetLedger()
   281  	if err != nil {
   282  		return nil, fmt.Errorf("Failed to get the ledger :%v", err)
   283  	}
   284  	return ledger.GetBlockByNumber(blockNumber)
   285  	*/
   286  	return nil,nil
   287  }
   288  
   289  // GetCurrentStateHash returns the current/temporary state hash
   290  func (h *Helper) GetCurrentStateHash() (stateHash []byte, err error) {
   291  	/*
   292  	ledger, err := ledger.GetLedger()
   293  	if err != nil {
   294  		return nil, fmt.Errorf("Failed to get the ledger :%v", err)
   295  	}
   296  	return ledger.GetTempStateHash()
   297  	*/
   298  	return nil,nil
   299  }
   300  
   301  // GetBlockchainInfoBlob marshals a ledger's BlockchainInfo into a protobuf
   302  func (h *Helper) GetBlockchainInfoBlob() []byte {
   303  	/*
   304  	ledger, _ := ledger.GetLedger()
   305  	info, _ := ledger.GetBlockchainInfo()
   306  	rawInfo, _ := proto.Marshal(info)
   307  	return rawInfo*/
   308  	return nil
   309  }
   310  
   311  // GetBlockHeadMetadata returns metadata from block at the head of the blockchain
   312  func (h *Helper) GetBlockHeadMetadata() ([]byte, error) {
   313  	/*
   314  	ledger, err := ledger.GetLedger()
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	head := ledger.GetBlockchainSize()
   319  	block, err := ledger.GetBlockByNumber(head - 1)
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  	return block.ConsensusMetadata, nil*/
   324  	return nil,nil
   325  }
   326  
   327  // InvalidateState is invoked to tell us that consensus realizes the ledger is out of sync
   328  func (h *Helper) InvalidateState() {
   329  	log.Debug("Invalidating the current state")
   330  	h.valid = false
   331  }
   332  
   333  // ValidateState is invoked to tell us that consensus has the ledger back in sync
   334  func (h *Helper) ValidateState() {
   335  	log.Debug("Validating the current state")
   336  	h.valid = true
   337  }
   338  
   339  // Execute will execute a set of transactions, this may be called in succession
   340  func (h *Helper) Execute(tag interface{}, txs []*message.Task) {
   341  	h.executor.Execute(tag, txs)
   342  }
   343  
   344  // Commit will commit whatever transactions have been executed
   345  func (h *Helper) Commit(tag interface{}, metadata []byte) {
   346  	h.executor.Commit(tag, metadata)
   347  }
   348  
   349  // Rollback will roll back whatever transactions have been executed
   350  func (h *Helper) Rollback(tag interface{}) {
   351  	h.executor.Rollback(tag)
   352  }
   353  
   354  // UpdateState attempts to synchronize state to a particular target, implicitly calls rollback if needed
   355  func (h *Helper) UpdateState(tag interface{}, target *message.StateInfo, peers []*pbftTypes.PeerID) {
   356  	if h.valid {
   357  		log.Warn("State transfer is being called for, but the state has not been invalidated")
   358  	}
   359  
   360  	h.executor.UpdateState(tag, target, peers)
   361  }
   362  
   363  // Executed is called whenever Execute completes
   364  func (h *Helper) Executed(tag interface{}) {
   365  	if h.consenter != nil {
   366  		h.consenter.Executed(tag)
   367  	}
   368  }
   369  
   370  // Committed is called whenever Commit completes
   371  func (h *Helper) Committed(tag interface{}, target* message.StateInfo) {
   372  	if h.consenter != nil {
   373  		h.consenter.Committed(tag, target)
   374  	}
   375  }
   376  
   377  // RolledBack is called whenever a Rollback completes
   378  func (h *Helper) RolledBack(tag interface{}) {
   379  	if h.consenter != nil {
   380  		h.consenter.RolledBack(tag)
   381  	}
   382  }
   383  
   384  // StateUpdated is called when state transfer completes, if target is nil, this indicates a failure and a new target should be supplied
   385  func (h *Helper) StateUpdated(tag interface{}, target* message.StateInfo) {
   386  	if h.consenter != nil {
   387  		h.consenter.StateUpdated(tag, target)
   388  	}
   389  }
   390  
   391  // Start his is a byproduct of the consensus API needing some cleaning, for now it's a no-op
   392  func (h *Helper) Start() {}
   393  
   394  // Halt is a byproduct of the consensus API needing some cleaning, for now it's a no-op
   395  func (h *Helper) Halt() {}