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() {}