github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/protos/utils/proputils.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 utils 18 19 import ( 20 "errors" 21 "fmt" 22 23 "encoding/binary" 24 25 "encoding/hex" 26 27 "github.com/golang/protobuf/proto" 28 "github.com/hyperledger/fabric/bccsp" 29 "github.com/hyperledger/fabric/bccsp/factory" 30 "github.com/hyperledger/fabric/core/chaincode/platforms" 31 "github.com/hyperledger/fabric/core/crypto/primitives" 32 "github.com/hyperledger/fabric/protos/common" 33 "github.com/hyperledger/fabric/protos/peer" 34 ) 35 36 // GetChaincodeInvocationSpec get the ChaincodeInvocationSpec from the proposal 37 func GetChaincodeInvocationSpec(prop *peer.Proposal) (*peer.ChaincodeInvocationSpec, error) { 38 txhdr := &common.Header{} 39 err := proto.Unmarshal(prop.Header, txhdr) 40 if err != nil { 41 return nil, err 42 } 43 ccPropPayload := &peer.ChaincodeProposalPayload{} 44 err = proto.Unmarshal(prop.Payload, ccPropPayload) 45 if err != nil { 46 return nil, err 47 } 48 cis := &peer.ChaincodeInvocationSpec{} 49 err = proto.Unmarshal(ccPropPayload.Input, cis) 50 if err != nil { 51 return nil, err 52 } 53 return cis, nil 54 } 55 56 // GetChaincodeProposalContext returns creator and transient 57 func GetChaincodeProposalContext(prop *peer.Proposal) ([]byte, map[string][]byte, error) { 58 if prop == nil { 59 return nil, nil, fmt.Errorf("Proposal is nil") 60 } 61 if len(prop.Header) == 0 { 62 return nil, nil, fmt.Errorf("Proposal's header is nil") 63 } 64 if len(prop.Payload) == 0 { 65 return nil, nil, fmt.Errorf("Proposal's payload is nil") 66 } 67 68 //// get back the header 69 hdr, err := GetHeader(prop.Header) 70 if err != nil { 71 return nil, nil, fmt.Errorf("Could not extract the header from the proposal: %s", err) 72 } 73 if hdr == nil { 74 return nil, nil, fmt.Errorf("Unmarshalled header is nil") 75 } 76 77 chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader) 78 if err != nil { 79 return nil, nil, fmt.Errorf("Could not extract the channel header from the proposal: %s", err) 80 } 81 82 if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION && 83 common.HeaderType(chdr.Type) != common.HeaderType_CONFIG { 84 return nil, nil, fmt.Errorf("Invalid proposal type expected ENDORSER_TRANSACTION or CONFIG. Was: %d", chdr.Type) 85 } 86 87 shdr, err := GetSignatureHeader(hdr.SignatureHeader) 88 if err != nil { 89 return nil, nil, fmt.Errorf("Could not extract the signature header from the proposal: %s", err) 90 } 91 92 ccPropPayload := &peer.ChaincodeProposalPayload{} 93 err = proto.Unmarshal(prop.Payload, ccPropPayload) 94 if err != nil { 95 return nil, nil, err 96 } 97 98 return shdr.Creator, ccPropPayload.TransientMap, nil 99 } 100 101 // GetHeader Get Header from bytes 102 func GetHeader(bytes []byte) (*common.Header, error) { 103 hdr := &common.Header{} 104 err := proto.Unmarshal(bytes, hdr) 105 if err != nil { 106 return nil, err 107 } 108 109 return hdr, nil 110 } 111 112 // GetNonce returns the nonce used in Proposal 113 func GetNonce(prop *peer.Proposal) ([]byte, error) { 114 // get back the header 115 hdr, err := GetHeader(prop.Header) 116 if err != nil { 117 return nil, fmt.Errorf("Could not extract the header from the proposal: %s", err) 118 } 119 120 chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader) 121 if err != nil { 122 return nil, fmt.Errorf("Could not extract the channel header from the proposal: %s", err) 123 } 124 shdr, err := GetSignatureHeader(hdr.SignatureHeader) 125 if err != nil { 126 return nil, fmt.Errorf("Could not extract the signature header from the proposal: %s", err) 127 } 128 129 if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION && 130 common.HeaderType(chdr.Type) != common.HeaderType_CONFIG { 131 return nil, fmt.Errorf("Invalid proposal type expected ENDORSER_TRANSACTION or CONFIG. Was: %d", chdr.Type) 132 } 133 134 if hdr.SignatureHeader == nil { 135 return nil, errors.New("Invalid signature header. It must be different from nil.") 136 } 137 138 ccPropPayload := &peer.ChaincodeProposalPayload{} 139 err = proto.Unmarshal(prop.Payload, ccPropPayload) 140 if err != nil { 141 return nil, err 142 } 143 144 return shdr.Nonce, nil 145 } 146 147 // GetChaincodeHeaderExtension get chaincode header extension given header 148 func GetChaincodeHeaderExtension(hdr *common.Header) (*peer.ChaincodeHeaderExtension, error) { 149 chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader) 150 if err != nil { 151 return nil, err 152 } 153 154 chaincodeHdrExt := &peer.ChaincodeHeaderExtension{} 155 err = proto.Unmarshal(chdr.Extension, chaincodeHdrExt) 156 if err != nil { 157 return nil, err 158 } 159 160 return chaincodeHdrExt, nil 161 } 162 163 // GetProposalResponse given proposal in bytes 164 func GetProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) { 165 proposalResponse := &peer.ProposalResponse{} 166 err := proto.Unmarshal(prBytes, proposalResponse) 167 if err != nil { 168 return nil, err 169 } 170 171 return proposalResponse, nil 172 } 173 174 // GetChaincodeDeploymentSpec returns a ChaincodeDeploymentSpec given args 175 func GetChaincodeDeploymentSpec(code []byte) (*peer.ChaincodeDeploymentSpec, error) { 176 cds := &peer.ChaincodeDeploymentSpec{} 177 err := proto.Unmarshal(code, cds) 178 if err != nil { 179 return nil, err 180 } 181 182 // FAB-2122: Validate the CDS according to platform specific requirements 183 platform, err := platforms.Find(cds.ChaincodeSpec.Type) 184 if err != nil { 185 return nil, err 186 } 187 188 err = platform.ValidateDeploymentSpec(cds) 189 if err != nil { 190 return nil, err 191 } 192 193 return cds, nil 194 } 195 196 // GetChaincodeAction gets the ChaincodeAction given chaicnode action bytes 197 func GetChaincodeAction(caBytes []byte) (*peer.ChaincodeAction, error) { 198 chaincodeAction := &peer.ChaincodeAction{} 199 err := proto.Unmarshal(caBytes, chaincodeAction) 200 if err != nil { 201 return nil, err 202 } 203 204 return chaincodeAction, nil 205 } 206 207 // GetResponse gets the Response given response bytes 208 func GetResponse(resBytes []byte) (*peer.Response, error) { 209 response := &peer.Response{} 210 err := proto.Unmarshal(resBytes, response) 211 if err != nil { 212 return nil, err 213 } 214 215 return response, nil 216 } 217 218 // GetChaincodeEvents gets the ChaincodeEvents given chaicnode event bytes 219 func GetChaincodeEvents(eBytes []byte) (*peer.ChaincodeEvent, error) { 220 chaincodeEvent := &peer.ChaincodeEvent{} 221 err := proto.Unmarshal(eBytes, chaincodeEvent) 222 if err != nil { 223 return nil, err 224 } 225 226 return chaincodeEvent, nil 227 } 228 229 // GetProposalResponsePayload gets the proposal response payload 230 func GetProposalResponsePayload(prpBytes []byte) (*peer.ProposalResponsePayload, error) { 231 prp := &peer.ProposalResponsePayload{} 232 err := proto.Unmarshal(prpBytes, prp) 233 if err != nil { 234 return nil, err 235 } 236 237 return prp, nil 238 } 239 240 // GetProposal returns a Proposal message from its bytes 241 func GetProposal(propBytes []byte) (*peer.Proposal, error) { 242 prop := &peer.Proposal{} 243 err := proto.Unmarshal(propBytes, prop) 244 if err != nil { 245 return nil, err 246 } 247 248 return prop, nil 249 } 250 251 // GetPayload Get Payload from Envelope message 252 func GetPayload(e *common.Envelope) (*common.Payload, error) { 253 payload := &common.Payload{} 254 err := proto.Unmarshal(e.Payload, payload) 255 if err != nil { 256 return nil, err 257 } 258 259 return payload, nil 260 } 261 262 // GetTransaction Get Transaction from bytes 263 func GetTransaction(txBytes []byte) (*peer.Transaction, error) { 264 tx := &peer.Transaction{} 265 err := proto.Unmarshal(txBytes, tx) 266 if err != nil { 267 return nil, err 268 } 269 270 return tx, nil 271 } 272 273 // GetChaincodeActionPayload Get ChaincodeActionPayload from bytes 274 func GetChaincodeActionPayload(capBytes []byte) (*peer.ChaincodeActionPayload, error) { 275 cap := &peer.ChaincodeActionPayload{} 276 err := proto.Unmarshal(capBytes, cap) 277 if err != nil { 278 return nil, err 279 } 280 281 return cap, nil 282 } 283 284 // GetChaincodeProposalPayload Get ChaincodeProposalPayload from bytes 285 func GetChaincodeProposalPayload(bytes []byte) (*peer.ChaincodeProposalPayload, error) { 286 cpp := &peer.ChaincodeProposalPayload{} 287 err := proto.Unmarshal(bytes, cpp) 288 if err != nil { 289 return nil, err 290 } 291 292 return cpp, nil 293 } 294 295 // GetSignatureHeader Get SignatureHeader from bytes 296 func GetSignatureHeader(bytes []byte) (*common.SignatureHeader, error) { 297 sh := &common.SignatureHeader{} 298 err := proto.Unmarshal(bytes, sh) 299 if err != nil { 300 return nil, err 301 } 302 303 return sh, nil 304 } 305 306 // GetSignaturePolicyEnvelope returns a SignaturePolicyEnvelope from bytes 307 func GetSignaturePolicyEnvelope(bytes []byte) (*common.SignaturePolicyEnvelope, error) { 308 p := &common.SignaturePolicyEnvelope{} 309 err := proto.Unmarshal(bytes, p) 310 if err != nil { 311 return nil, err 312 } 313 314 return p, nil 315 } 316 317 // CreateChaincodeProposal creates a proposal from given input. 318 // It returns the proposal and the transaction id associated to the proposal 319 func CreateChaincodeProposal(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) { 320 return CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil) 321 } 322 323 // CreateChaincodeProposalWithTransient creates a proposal from given input 324 // It returns the proposal and the transaction id associated to the proposal 325 func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) { 326 // generate a random nonce 327 nonce, err := primitives.GetRandomNonce() 328 if err != nil { 329 return nil, "", err 330 } 331 332 // compute txid 333 txid, err := ComputeProposalTxID(nonce, creator) 334 if err != nil { 335 return nil, "", err 336 } 337 338 return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap) 339 } 340 341 // CreateChaincodeProposalWithTxIDNonceAndTransient creates a proposal from given input 342 func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) { 343 ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId} 344 ccHdrExtBytes, err := proto.Marshal(ccHdrExt) 345 if err != nil { 346 return nil, "", err 347 } 348 349 cisBytes, err := proto.Marshal(cis) 350 if err != nil { 351 return nil, "", err 352 } 353 354 ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap} 355 ccPropPayloadBytes, err := proto.Marshal(ccPropPayload) 356 if err != nil { 357 return nil, "", err 358 } 359 360 // TODO: epoch is now set to zero. This must be changed once we 361 // get a more appropriate mechanism to handle it in. 362 var epoch uint64 = 0 363 364 hdr := &common.Header{ChannelHeader: MarshalOrPanic(&common.ChannelHeader{ 365 Type: int32(typ), 366 TxId: txid, 367 ChannelId: chainID, 368 Extension: ccHdrExtBytes, 369 Epoch: epoch}), 370 SignatureHeader: MarshalOrPanic(&common.SignatureHeader{Nonce: nonce, Creator: creator})} 371 372 hdrBytes, err := proto.Marshal(hdr) 373 if err != nil { 374 return nil, "", err 375 } 376 377 return &peer.Proposal{Header: hdrBytes, Payload: ccPropPayloadBytes}, txid, nil 378 } 379 380 // GetBytesProposalResponsePayload gets proposal response payload 381 func GetBytesProposalResponsePayload(hash []byte, response *peer.Response, result []byte, event []byte) ([]byte, error) { 382 cAct := &peer.ChaincodeAction{Events: event, Results: result, Response: response} 383 cActBytes, err := proto.Marshal(cAct) 384 if err != nil { 385 return nil, err 386 } 387 388 prp := &peer.ProposalResponsePayload{Extension: cActBytes, ProposalHash: hash} 389 prpBytes, err := proto.Marshal(prp) 390 if err != nil { 391 return nil, err 392 } 393 394 return prpBytes, nil 395 } 396 397 // GetBytesChaincodeProposalPayload gets the chaincode proposal payload 398 func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error) { 399 cppBytes, err := proto.Marshal(cpp) 400 if err != nil { 401 return nil, err 402 } 403 404 return cppBytes, nil 405 } 406 407 // GetBytesResponse gets the bytes of Response 408 func GetBytesResponse(res *peer.Response) ([]byte, error) { 409 resBytes, err := proto.Marshal(res) 410 if err != nil { 411 return nil, err 412 } 413 414 return resBytes, nil 415 } 416 417 // GetBytesChaincodeEvent gets the bytes of ChaincodeEvent 418 func GetBytesChaincodeEvent(event *peer.ChaincodeEvent) ([]byte, error) { 419 eventBytes, err := proto.Marshal(event) 420 if err != nil { 421 return nil, err 422 } 423 424 return eventBytes, nil 425 } 426 427 // GetBytesChaincodeActionPayload get the bytes of ChaincodeActionPayload from the message 428 func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error) { 429 capBytes, err := proto.Marshal(cap) 430 if err != nil { 431 return nil, err 432 } 433 434 return capBytes, nil 435 } 436 437 // GetBytesProposalResponse gets propoal bytes response 438 func GetBytesProposalResponse(pr *peer.ProposalResponse) ([]byte, error) { 439 respBytes, err := proto.Marshal(pr) 440 if err != nil { 441 return nil, err 442 } 443 444 return respBytes, nil 445 } 446 447 // GetBytesProposal returns the bytes of a proposal message 448 func GetBytesProposal(prop *peer.Proposal) ([]byte, error) { 449 propBytes, err := proto.Marshal(prop) 450 if err != nil { 451 return nil, err 452 } 453 454 return propBytes, nil 455 } 456 457 // GetBytesHeader get the bytes of Header from the message 458 func GetBytesHeader(hdr *common.Header) ([]byte, error) { 459 bytes, err := proto.Marshal(hdr) 460 if err != nil { 461 return nil, err 462 } 463 464 return bytes, nil 465 } 466 467 // GetBytesSignatureHeader get the bytes of SignatureHeader from the message 468 func GetBytesSignatureHeader(hdr *common.SignatureHeader) ([]byte, error) { 469 bytes, err := proto.Marshal(hdr) 470 if err != nil { 471 return nil, err 472 } 473 474 return bytes, nil 475 } 476 477 // GetBytesTransaction get the bytes of Transaction from the message 478 func GetBytesTransaction(tx *peer.Transaction) ([]byte, error) { 479 bytes, err := proto.Marshal(tx) 480 if err != nil { 481 return nil, err 482 } 483 484 return bytes, nil 485 } 486 487 // GetBytesPayload get the bytes of Payload from the message 488 func GetBytesPayload(payl *common.Payload) ([]byte, error) { 489 bytes, err := proto.Marshal(payl) 490 if err != nil { 491 return nil, err 492 } 493 494 return bytes, nil 495 } 496 497 // GetBytesEnvelope get the bytes of Envelope from the message 498 func GetBytesEnvelope(env *common.Envelope) ([]byte, error) { 499 bytes, err := proto.Marshal(env) 500 if err != nil { 501 return nil, err 502 } 503 504 return bytes, nil 505 } 506 507 // GetActionFromEnvelope extracts a ChaincodeAction message from a serialized Envelope 508 func GetActionFromEnvelope(envBytes []byte) (*peer.ChaincodeAction, error) { 509 env, err := GetEnvelopeFromBlock(envBytes) 510 if err != nil { 511 return nil, err 512 } 513 514 payl, err := GetPayload(env) 515 if err != nil { 516 return nil, err 517 } 518 519 tx, err := GetTransaction(payl.Data) 520 if err != nil { 521 return nil, err 522 } 523 524 _, respPayload, err := GetPayloads(tx.Actions[0]) 525 return respPayload, err 526 } 527 528 // CreateProposalFromCIS returns a proposal given a serialized identity and a ChaincodeInvocationSpec 529 func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) { 530 return CreateChaincodeProposal(typ, chainID, cis, creator) 531 } 532 533 // CreateInstallProposalFromCDS returns a install proposal given a serialized identity and a ChaincodeDeploymentSpec 534 func CreateInstallProposalFromCDS(cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, string, error) { 535 return createProposalFromCDS("", cds, creator, nil, nil, nil, "install") 536 } 537 538 // CreateDeployProposalFromCDS returns a deploy proposal given a serialized identity and a ChaincodeDeploymentSpec 539 func CreateDeployProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) { 540 return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "deploy") 541 } 542 543 // CreateUpgradeProposalFromCDS returns a upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec 544 func CreateUpgradeProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) { 545 return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "upgrade") 546 } 547 548 // createProposalFromCDS returns a deploy or upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec 549 func createProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte, propType string) (*peer.Proposal, string, error) { 550 //in the new mode, cds will be nil, "deploy" and "upgrade" are instantiates. 551 var ccinp *peer.ChaincodeInput 552 var b []byte 553 var err error 554 if cds != nil { 555 b, err = proto.Marshal(cds) 556 if err != nil { 557 return nil, "", err 558 } 559 } 560 switch propType { 561 case "deploy": 562 fallthrough 563 case "upgrade": 564 ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), b, policy, escc, vscc}} 565 case "install": 566 ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}} 567 } 568 569 //wrap the deployment in an invocation spec to lccc... 570 lcccSpec := &peer.ChaincodeInvocationSpec{ 571 ChaincodeSpec: &peer.ChaincodeSpec{ 572 Type: peer.ChaincodeSpec_GOLANG, 573 ChaincodeId: &peer.ChaincodeID{Name: "lccc"}, 574 Input: ccinp}} 575 576 //...and get the proposal for it 577 return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lcccSpec, creator) 578 } 579 580 // ComputeProposalTxID computes TxID as the Hash computed 581 // over the concatenation of nonce and creator. 582 func ComputeProposalTxID(nonce, creator []byte) (string, error) { 583 // TODO: Get the Hash function to be used from 584 // channel configuration 585 digest, err := factory.GetDefault().Hash( 586 append(nonce, creator...), 587 &bccsp.SHA256Opts{}) 588 if err != nil { 589 return "", err 590 } 591 return hex.EncodeToString(digest), nil 592 } 593 594 // CheckProposalTxID checks that txid is equal to the Hash computed 595 // over the concatenation of nonce and creator. 596 func CheckProposalTxID(txid string, nonce, creator []byte) error { 597 computedTxID, err := ComputeProposalTxID(nonce, creator) 598 if err != nil { 599 return fmt.Errorf("Failed computing target TXID for comparison [%s]", err) 600 } 601 602 if txid != computedTxID { 603 return fmt.Errorf("Transaction is not valid. Got [%s], expected [%s]", txid, computedTxID) 604 } 605 606 return nil 607 } 608 609 // ComputeProposalBinding computes the binding of a proposal 610 func ComputeProposalBinding(proposal *peer.Proposal) ([]byte, error) { 611 if proposal == nil { 612 return nil, fmt.Errorf("Porposal is nil") 613 } 614 if len(proposal.Header) == 0 { 615 return nil, fmt.Errorf("Proposal's Header is nil") 616 } 617 618 h, err := GetHeader(proposal.Header) 619 if err != nil { 620 return nil, err 621 } 622 623 chdr, err := UnmarshalChannelHeader(h.ChannelHeader) 624 if err != nil { 625 return nil, err 626 } 627 shdr, err := GetSignatureHeader(h.SignatureHeader) 628 if err != nil { 629 return nil, err 630 } 631 632 return computeProposalBindingInternal(shdr.Nonce, shdr.Creator, chdr.Epoch) 633 } 634 635 func computeProposalBindingInternal(nonce, creator []byte, epoch uint64) ([]byte, error) { 636 epochBytes := make([]byte, 8) 637 binary.LittleEndian.PutUint64(epochBytes, epoch) 638 639 // TODO: add to genesis block the hash function used for the binding computation. 640 digest, err := factory.GetDefault().Hash( 641 append(append(nonce, creator...), epochBytes...), 642 &bccsp.SHA256Opts{}) 643 if err != nil { 644 return nil, err 645 } 646 return digest, nil 647 }