Skip to content

Commit

Permalink
[FAB-4370] Basic EndorserTx support in protolator
Browse files Browse the repository at this point in the history
There have been numerous requests on rocketchat with people attempting
to inspect the endorser transaction contents.  Thanks to the complicated
structure of the endorser tx protos, it is very difficult for a casual
user to turn the binary blob into a human readable form.

This CR adds basic support for decoding typical endorser transactions.

Note: It makes no effort to handle transactions which have the proposal
visibility set to anything other than full, and no effort to support
endorser transactions which are not chaincode related (to my knowledge,
these are unimplemented).

Change-Id: I246b5a4ec60ae5748a4eedc064da54f1d3e92672
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Aug 2, 2017
1 parent b0632c0 commit 15a9028
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 20 deletions.
30 changes: 10 additions & 20 deletions protos/common/common.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Copyright IBM Corp. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package common
Expand All @@ -37,6 +27,11 @@ func (p *Payload) VariablyOpaqueFields() []string {
return []string{"data"}
}

var PayloadDataMap = map[int32]proto.Message{
int32(HeaderType_CONFIG): &ConfigEnvelope{},
int32(HeaderType_CONFIG_UPDATE): &ConfigUpdateEnvelope{},
}

func (p *Payload) VariablyOpaqueFieldProto(name string) (proto.Message, error) {
if name != p.VariablyOpaqueFields()[0] {
return nil, fmt.Errorf("not a marshaled field: %s", name)
Expand All @@ -49,15 +44,10 @@ func (p *Payload) VariablyOpaqueFieldProto(name string) (proto.Message, error) {
return nil, fmt.Errorf("corrupt channel header: %s", err)
}

switch ch.Type {
case int32(HeaderType_CONFIG):
return &ConfigEnvelope{}, nil
case int32(HeaderType_CONFIG_UPDATE):
return &ConfigUpdateEnvelope{}, nil
// TODO implement the other well known types, particularly endorser txs
default:
return nil, fmt.Errorf("decoding type %v is unimplemented", ch.Type)
if msg, ok := PayloadDataMap[ch.Type]; ok {
return msg, nil
}
return nil, fmt.Errorf("decoding type %v is unimplemented", ch.Type)
}

func (h *Header) StaticallyOpaqueFields() []string {
Expand Down
24 changes: 24 additions & 0 deletions protos/peer/proposal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package peer

import (
"fmt"

"github.com/golang/protobuf/proto"
)

func (cpp *ChaincodeProposalPayload) StaticallyOpaqueFields() []string {
return []string{"input"}
}

func (cpp *ChaincodeProposalPayload) StaticallyOpaqueFieldProto(name string) (proto.Message, error) {
if name != cpp.StaticallyOpaqueFields()[0] {
return nil, fmt.Errorf("not a marshaled field: %s", name)
}
return &ChaincodeInvocationSpec{}, nil
}
1 change: 1 addition & 0 deletions protos/peer/proposal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ message ChaincodeProposalPayload {

// Input contains the arguments for this invocation. If this invocation
// deploys a new chaincode, ESCC/VSCC are part of this field.
// This is usually a marshaled ChaincodeInvocationSpec
bytes input = 1;

// TransientMap contains data (e.g. cryptographic material) that might be used
Expand Down
24 changes: 24 additions & 0 deletions protos/peer/proposal_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package peer

import (
"fmt"

"github.com/golang/protobuf/proto"
)

func (ppr *ProposalResponsePayload) StaticallyOpaqueFields() []string {
return []string{"extension"}
}

func (ppr *ProposalResponsePayload) StaticallyOpaqueFieldProto(name string) (proto.Message, error) {
if name != ppr.StaticallyOpaqueFields()[0] {
return nil, fmt.Errorf("not a marshaled field: %s", name)
}
return &ChaincodeAction{}, nil
}
56 changes: 56 additions & 0 deletions protos/peer/transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package peer

import (
"fmt"

"github.com/hyperledger/fabric/protos/common"

"github.com/golang/protobuf/proto"
)

func init() {
common.PayloadDataMap[int32(common.HeaderType_ENDORSER_TRANSACTION)] = &Transaction{}
}

func (ta *TransactionAction) StaticallyOpaqueFields() []string {
return []string{"header", "payload"}
}

func (ta *TransactionAction) StaticallyOpaqueFieldProto(name string) (proto.Message, error) {
switch name {
case ta.StaticallyOpaqueFields()[0]:
return &common.SignatureHeader{}, nil
case ta.StaticallyOpaqueFields()[1]:
return &ChaincodeActionPayload{}, nil
default:
return nil, fmt.Errorf("not a marshaled field: %s", name)
}
}

func (cap *ChaincodeActionPayload) StaticallyOpaqueFields() []string {
return []string{"chaincode_proposal_payload"}
}

func (cap *ChaincodeActionPayload) StaticallyOpaqueFieldProto(name string) (proto.Message, error) {
if name != cap.StaticallyOpaqueFields()[0] {
return nil, fmt.Errorf("not a marshaled field: %s", name)
}
return &ChaincodeProposalPayload{}, nil
}

func (cae *ChaincodeEndorsedAction) StaticallyOpaqueFields() []string {
return []string{"proposal_response_payload"}
}

func (cae *ChaincodeEndorsedAction) StaticallyOpaqueFieldProto(name string) (proto.Message, error) {
if name != cae.StaticallyOpaqueFields()[0] {
return nil, fmt.Errorf("not a marshaled field: %s", name)
}
return &ProposalResponsePayload{}, nil
}

0 comments on commit 15a9028

Please sign in to comment.