Skip to content

Commit

Permalink
Merge "[FAB-16170] hdr validation for endorser transactions"
Browse files Browse the repository at this point in the history
  • Loading branch information
manish-sethi authored and Gerrit Code Review committed Nov 20, 2019
2 parents 60ef90d + 20dbb4a commit 7cc8760
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 13 deletions.
2 changes: 1 addition & 1 deletion core/tx/endorser/endorsertx_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ type protomsg struct {

func TestEndorserTx(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Books Suite")
RunSpecs(t, "EndorserTx Suite")
}
56 changes: 54 additions & 2 deletions core/tx/endorser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package endorsertx

import (
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/pkg/tx"
"github.com/hyperledger/fabric/protoutil"
Expand All @@ -25,13 +26,55 @@ type EndorserTx struct {
Endorsements []*peer.Endorsement
}

func validateHeaders(
cHdr *common.ChannelHeader,
sHdr *common.SignatureHeader,
hdrExt *peer.ChaincodeHeaderExtension,
) error {
/******************************************/
/*****VALIDATION OF THE CHANNEL HEADER*****/
/******************************************/

if cHdr.Epoch != 0 {
return errors.Errorf("invalid Epoch in ChannelHeader. Expected 0, got [%d]", cHdr.Epoch)
}

if cHdr.Version != 0 {
return errors.Errorf("invalid version in ChannelHeader. Expected 0, got [%d]", cHdr.Version)
}

/********************************************/
/*****VALIDATION OF THE SIGNATURE HEADER*****/
/********************************************/

if len(sHdr.Nonce) == 0 {
return errors.New("empty nonce")
}

if len(sHdr.Creator) == 0 {
return errors.New("empty creator")
}

/********************************************/
/*****VALIDATION OF THE HEADER EXTENSION*****/
/********************************************/

if hdrExt.ChaincodeId == nil {
return errors.New("nil ChaincodeId")
}

if hdrExt.ChaincodeId.Name == "" {
return errors.New("empty chaincode name in chaincode id")
}

return nil
}

// NewEndorserTx receives a tx.Envelope containing a partially
// unmarshalled endorser transaction and returns an EndorserTx
// instance (or an error)
func NewEndorserTx(txenv *tx.Envelope) (*EndorserTx, error) {

// TODO FAB-16170: validate headers

if len(txenv.ChannelHeader.Extension) == 0 {
return nil, errors.New("empty header extension")
}
Expand All @@ -43,6 +86,15 @@ func NewEndorserTx(txenv *tx.Envelope) (*EndorserTx, error) {
return nil, err
}

err = validateHeaders(
txenv.ChannelHeader,
txenv.SignatureHeader,
hdrExt,
)
if err != nil {
return nil, err
}

if len(txenv.Data) == 0 {
return nil, errors.New("nil payload data")
}
Expand Down
124 changes: 114 additions & 10 deletions core/tx/endorser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package endorsertx_test

import (
"encoding/hex"

"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/peer"
endorsertx "github.com/hyperledger/fabric/core/tx/endorser"
Expand All @@ -24,10 +26,22 @@ var _ = Describe("Parser", func() {
payloadData *protomsg
prpExt *protomsg
prp *protomsg
chHeader *common.ChannelHeader
sigHeader *common.SignatureHeader
)

BeforeEach(func() {
prp, hdrExt, prpExt, payloadData = nil, nil, nil, nil

chHeader = &common.ChannelHeader{
ChannelId: "my-channel",
Epoch: 0,
}

sigHeader = &common.SignatureHeader{
Nonce: []byte("1234"),
Creator: []byte("creator"),
}
})

JustBeforeEach(func() {
Expand All @@ -44,16 +58,7 @@ var _ = Describe("Parser", func() {
)
}

chHeader := &common.ChannelHeader{
ChannelId: "my-channel",
Epoch: 35,
Extension: hdrExtBytes,
}

sigHeader := &common.SignatureHeader{
Nonce: []byte("1234"),
Creator: []byte("creator"),
}
chHeader.Extension = hdrExtBytes

var extBytes []byte
if prpExt != nil {
Expand Down Expand Up @@ -295,5 +300,104 @@ var _ = Describe("Parser", func() {
Expect(err).To(MatchError("error unmarshaling ChaincodeAction: unexpected EOF"))
Expect(pe).To(BeNil())
})

When("there is a bad epoch", func() {
BeforeEach(func() {
chHeader = &common.ChannelHeader{
ChannelId: "my-channel",
Epoch: 35,
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("invalid Epoch in ChannelHeader. Expected 0, got [35]"))
Expect(pe).To(BeNil())
})
})

When("there is a bad version", func() {
BeforeEach(func() {
chHeader = &common.ChannelHeader{
ChannelId: "my-channel",
Version: 35,
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("invalid version in ChannelHeader. Expected 0, got [35]"))
Expect(pe).To(BeNil())
})
})

When("there is an empty nonce", func() {
BeforeEach(func() {
sigHeader = &common.SignatureHeader{
Creator: []byte("creator"),
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("empty nonce"))
Expect(pe).To(BeNil())
})
})

When("there is an empty creator", func() {
BeforeEach(func() {
sigHeader = &common.SignatureHeader{
Nonce: []byte("1234"),
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("empty creator"))
Expect(pe).To(BeNil())
})
})

When("there is no chaincode ID", func() {
BeforeEach(func() {
// annoyingly, it's not easy to get a nonzero length
// marshalling of a proto message with zero values
// everywhere. We simulate this condition by adding
// extra bytes for a non-existent second field that
// our unmarshaler will skip. Still, the presence of
// an extraneous field will get the unmarshaler to
// return a non-nil struct
bytes, err := hex.DecodeString("1a046369616f")
Expect(err).To(BeNil())
hdrExt = &protomsg{
msg: bytes,
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("nil ChaincodeId"))
Expect(pe).To(BeNil())
})
})

When("there is an empty chaincode name", func() {
BeforeEach(func() {
hdrExt = &protomsg{
msg: protoutil.MarshalOrPanic(
&peer.ChaincodeHeaderExtension{
ChaincodeId: &peer.ChaincodeID{},
},
),
}
})

It("returns an error", func() {
pe, err := endorsertx.NewEndorserTx(txenv)
Expect(err).To(MatchError("empty chaincode name in chaincode id"))
Expect(pe).To(BeNil())
})
})
})
})

0 comments on commit 7cc8760

Please sign in to comment.