go_study/fabric-main/core/peer/deliverevents_test.go

737 lines
25 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package peer
import (
"context"
"fmt"
"io"
"strings"
"sync"
"testing"
"time"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/orderer"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/deliver"
"github.com/hyperledger/fabric/common/ledger/blockledger"
"github.com/hyperledger/fabric/common/metrics/disabled"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
fake "github.com/hyperledger/fabric/core/peer/mock"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/metadata"
peer2 "google.golang.org/grpc/peer"
)
// defaultPolicyCheckerProvider policy checker provider used by default,
// generates policy checker which always accepts regardless of arguments
// passed in
var defaultPolicyCheckerProvider = func(_ string) deliver.PolicyCheckerFunc {
return func(_ *common.Envelope, _ string) error {
return nil
}
}
//go:generate counterfeiter -o mock/peer_ledger.go -fake-name PeerLedger . peerLedger
type peerLedger interface {
ledger.PeerLedger
}
//go:generate counterfeiter -o mock/identity_deserializer_manager.go -fake-name IdentityDeserializerManager . identityDeserializerManager
type identityDeserializerManager interface {
IdentityDeserializerManager
}
//go:generate counterfeiter -o mock/collection_policy_checker.go -fake-name CollectionPolicyChecker . collectionPolicyChecker
type collectionPolicyChecker interface {
CollectionPolicyChecker
}
// mockIterator mock structure implementing
// the blockledger.Iterator interface
type mockIterator struct {
mock.Mock
}
func (m *mockIterator) Next() (*common.Block, common.Status) {
args := m.Called()
return args.Get(0).(*common.Block), args.Get(1).(common.Status)
}
func (m *mockIterator) ReadyChan() <-chan struct{} {
panic("implement me")
}
func (m *mockIterator) Close() {
}
// mockReader mock structure implementing
// the blockledger.Reader interface
type mockReader struct {
mock.Mock
}
func (m *mockReader) Iterator(startType *orderer.SeekPosition) (blockledger.Iterator, uint64) {
args := m.Called(startType)
return args.Get(0).(blockledger.Iterator), args.Get(1).(uint64)
}
func (m *mockReader) Height() uint64 {
args := m.Called()
return args.Get(0).(uint64)
}
func (m *mockReader) RetrieveBlockByNumber(blockNum uint64) (*common.Block, error) {
args := m.Called()
return args.Get(0).(*common.Block), args.Error(1)
}
// mockChainSupport
type mockChainSupport struct {
mock.Mock
}
func (m *mockChainSupport) Sequence() uint64 {
return m.Called().Get(0).(uint64)
}
func (m *mockChainSupport) Ledger() ledger.PeerLedger {
return m.Called().Get(0).(ledger.PeerLedger)
}
func (m *mockChainSupport) PolicyManager() policies.Manager {
panic("implement me")
}
func (m *mockChainSupport) Reader() blockledger.Reader {
return m.Called().Get(0).(blockledger.Reader)
}
func (*mockChainSupport) Errored() <-chan struct{} {
return make(chan struct{})
}
// mockChainManager mock implementation of the ChainManager interface
type mockChainManager struct {
mock.Mock
}
func (m *mockChainManager) GetChain(channelID string) deliver.Chain {
args := m.Called(channelID)
return args.Get(0).(deliver.Chain)
}
// mockDeliverServer mock implementation of the Deliver_DeliverServer
type mockDeliverServer struct {
mock.Mock
}
func (m *mockDeliverServer) Context() context.Context {
return m.Called().Get(0).(context.Context)
}
func (m *mockDeliverServer) Recv() (*common.Envelope, error) {
args := m.Called()
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*common.Envelope), args.Error(1)
}
func (m *mockDeliverServer) Send(response *peer.DeliverResponse) error {
args := m.Called(response)
return args.Error(0)
}
func (*mockDeliverServer) RecvMsg(m interface{}) error {
panic("implement me")
}
func (*mockDeliverServer) SendHeader(metadata.MD) error {
panic("implement me")
}
func (*mockDeliverServer) SendMsg(m interface{}) error {
panic("implement me")
}
func (*mockDeliverServer) SetHeader(metadata.MD) error {
panic("implement me")
}
func (*mockDeliverServer) SetTrailer(metadata.MD) {
panic("implement me")
}
type testConfig struct {
channelID string
eventName string
chaincodeName string
txID string
payload *common.Payload
*require.Assertions
}
type testCase struct {
name string
prepare func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer)
}
func TestFilteredBlockResponseSenderIsFiltered(t *testing.T) {
var fbrs interface{} = &filteredBlockResponseSender{}
filtered, ok := fbrs.(deliver.Filtered)
require.True(t, ok, "should be filtered")
require.True(t, filtered.IsFiltered(), "should return true from IsFiltered")
}
func TestEventsServer_DeliverFiltered(t *testing.T) {
tests := []testCase{
{
name: "Testing deliver of the filtered block events",
prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
wg.Add(2)
p := &peer2.Peer{}
chaincodeActionPayload, err := createChaincodeAction(config.chaincodeName, config.eventName, config.txID)
config.NoError(err)
chainManager := createDefaultSupportMamangerMock(config, chaincodeActionPayload, nil)
// setup mock deliver server
deliverServer := &mockDeliverServer{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{
Payload: protoutil.MarshalOrPanic(config.payload),
}, nil).Run(func(_ mock.Arguments) {
// once we are getting new message we need to mock
// Recv call to get io.EOF to stop the looping for
// next message and we can assert for the DeliverResponse
// value we are getting from the deliver server
deliverServer.Mock = mock.Mock{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
defer wg.Done()
response := args.Get(0).(*peer.DeliverResponse)
switch response.Type.(type) {
case *peer.DeliverResponse_Status:
config.Equal(common.Status_SUCCESS, response.GetStatus())
case *peer.DeliverResponse_FilteredBlock:
block := response.GetFilteredBlock()
config.Equal(uint64(0), block.Number)
config.Equal(config.channelID, block.ChannelId)
config.Equal(1, len(block.FilteredTransactions))
tx := block.FilteredTransactions[0]
config.Equal(config.txID, tx.Txid)
config.Equal(peer.TxValidationCode_VALID, tx.TxValidationCode)
config.Equal(common.HeaderType_ENDORSER_TRANSACTION, tx.Type)
transactionActions := tx.GetTransactionActions()
config.NotNil(transactionActions)
chaincodeActions := transactionActions.ChaincodeActions
config.Equal(1, len(chaincodeActions))
config.Equal(config.eventName, chaincodeActions[0].ChaincodeEvent.EventName)
config.Equal(config.txID, chaincodeActions[0].ChaincodeEvent.TxId)
config.Equal(config.chaincodeName, chaincodeActions[0].ChaincodeEvent.ChaincodeId)
default:
config.FailNow("Unexpected response type")
}
}).Return(nil)
})
return chainManager, deliverServer
}
}(testConfig{
channelID: "testChannelID",
eventName: "testEvent",
chaincodeName: "mycc",
txID: "testID",
payload: &common.Payload{
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
ChannelId: "testChannelID",
Timestamp: util.CreateUtcTimestamp(),
}),
SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
},
Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
Start: &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
Stop: &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
}),
},
Assertions: require.New(t),
}),
},
{
name: "Testing deliver of the filtered block events with nil chaincode action payload",
prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
wg.Add(2)
p := &peer2.Peer{}
chainManager := createDefaultSupportMamangerMock(config, nil, nil)
// setup mock deliver server
deliverServer := &mockDeliverServer{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{
Payload: protoutil.MarshalOrPanic(config.payload),
}, nil).Run(func(_ mock.Arguments) {
// once we are getting new message we need to mock
// Recv call to get io.EOF to stop the looping for
// next message and we can assert for the DeliverResponse
// value we are getting from the deliver server
deliverServer.Mock = mock.Mock{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
defer wg.Done()
response := args.Get(0).(*peer.DeliverResponse)
switch response.Type.(type) {
case *peer.DeliverResponse_Status:
config.Equal(common.Status_SUCCESS, response.GetStatus())
case *peer.DeliverResponse_FilteredBlock:
block := response.GetFilteredBlock()
config.Equal(uint64(0), block.Number)
config.Equal(config.channelID, block.ChannelId)
config.Equal(1, len(block.FilteredTransactions))
tx := block.FilteredTransactions[0]
config.Equal(config.txID, tx.Txid)
config.Equal(peer.TxValidationCode_VALID, tx.TxValidationCode)
config.Equal(common.HeaderType_ENDORSER_TRANSACTION, tx.Type)
transactionActions := tx.GetTransactionActions()
config.NotNil(transactionActions)
chaincodeActions := transactionActions.ChaincodeActions
// we expecting to get zero chaincode action,
// since provided nil payload
config.Equal(0, len(chaincodeActions))
default:
config.FailNow("Unexpected response type")
}
}).Return(nil)
})
return chainManager, deliverServer
}
}(testConfig{
channelID: "testChannelID",
eventName: "testEvent",
chaincodeName: "mycc",
txID: "testID",
payload: &common.Payload{
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
ChannelId: "testChannelID",
Timestamp: util.CreateUtcTimestamp(),
}),
SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
},
Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
Start: &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
Stop: &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
}),
},
Assertions: require.New(t),
}),
},
{
name: "Testing deliver of the filtered block events with nil payload header",
prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
wg.Add(1)
p := &peer2.Peer{}
chainManager := createDefaultSupportMamangerMock(config, nil, nil)
// setup mock deliver server
deliverServer := &mockDeliverServer{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{
Payload: protoutil.MarshalOrPanic(config.payload),
}, nil).Run(func(_ mock.Arguments) {
// once we are getting new message we need to mock
// Recv call to get io.EOF to stop the looping for
// next message and we can assert for the DeliverResponse
// value we are getting from the deliver server
deliverServer.Mock = mock.Mock{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
defer wg.Done()
response := args.Get(0).(*peer.DeliverResponse)
switch response.Type.(type) {
case *peer.DeliverResponse_Status:
config.Equal(common.Status_BAD_REQUEST, response.GetStatus())
case *peer.DeliverResponse_FilteredBlock:
config.FailNow("Unexpected response type")
default:
config.FailNow("Unexpected response type")
}
}).Return(nil)
})
return chainManager, deliverServer
}
}(testConfig{
channelID: "testChannelID",
eventName: "testEvent",
chaincodeName: "mycc",
txID: "testID",
payload: &common.Payload{
Header: nil,
Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
Start: &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
Stop: &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
}),
},
Assertions: require.New(t),
}),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
wg := &sync.WaitGroup{}
chainManager, deliverServer := test.prepare(wg)
metrics := deliver.NewMetrics(&disabled.Provider{})
server := &DeliverServer{
DeliverHandler: deliver.NewHandler(chainManager, time.Second, false, metrics, false),
PolicyCheckerProvider: defaultPolicyCheckerProvider,
}
err := server.DeliverFiltered(deliverServer)
wg.Wait()
// no error expected
require.NoError(t, err)
})
}
}
func TestEventsServer_DeliverWithPrivateData(t *testing.T) {
fakeDeserializerMgr := &fake.IdentityDeserializerManager{}
fakeDeserializerMgr.DeserializerReturns(nil, nil)
fakeCollPolicyChecker := &fake.CollectionPolicyChecker{}
fakeCollPolicyChecker.CheckCollectionPolicyReturns(true, nil)
tests := []testCase{
{
name: "Testing deliver block with private data events",
prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
wg.Add(2)
p := &peer2.Peer{}
chaincodeActionPayload, err := createChaincodeAction(config.chaincodeName, config.eventName, config.txID)
config.NoError(err)
pvtData := []*ledger.TxPvtData{
produceSamplePvtdataOrPanic(0, []string{"ns-0:coll-0", "ns-2:coll-20", "ns-2:coll-21"}),
}
chainManager := createDefaultSupportMamangerMock(config, chaincodeActionPayload, pvtData)
deliverServer := &mockDeliverServer{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{
Payload: protoutil.MarshalOrPanic(config.payload),
}, nil).Run(func(_ mock.Arguments) {
// mock Recv calls to get io.EOF to stop the looping for next message
deliverServer.Mock = mock.Mock{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
defer wg.Done()
response := args.Get(0).(*peer.DeliverResponse)
switch response.Type.(type) {
case *peer.DeliverResponse_Status:
config.Equal(common.Status_SUCCESS, response.GetStatus())
case *peer.DeliverResponse_BlockAndPrivateData:
blockAndPvtData := response.GetBlockAndPrivateData()
block := blockAndPvtData.Block
config.Equal(uint64(0), block.Header.Number)
config.Equal(1, len(blockAndPvtData.PrivateDataMap))
config.NotNil(blockAndPvtData.PrivateDataMap[uint64(0)])
txPvtRwset := blockAndPvtData.PrivateDataMap[uint64(0)]
// expect to have 2 NsPvtRwset (i.e., 2 namespaces)
config.Equal(2, len(txPvtRwset.NsPvtRwset))
// check namespace because the index may be out of order
for _, nsPvtRwset := range txPvtRwset.NsPvtRwset {
switch nsPvtRwset.Namespace {
case "ns-0":
config.Equal(1, len(nsPvtRwset.CollectionPvtRwset))
config.Equal("coll-0", nsPvtRwset.CollectionPvtRwset[0].CollectionName)
case "ns-2":
config.Equal(2, len(nsPvtRwset.CollectionPvtRwset))
config.Equal("coll-20", nsPvtRwset.CollectionPvtRwset[0].CollectionName)
config.Equal("coll-21", nsPvtRwset.CollectionPvtRwset[1].CollectionName)
default:
config.FailNow("Wrong namespace " + nsPvtRwset.Namespace)
}
}
default:
config.FailNow("Unexpected response type")
}
}).Return(nil)
})
return chainManager, deliverServer
}
}(testConfig{
channelID: "testChannelID",
eventName: "testEvent",
chaincodeName: "mycc",
txID: "testID",
payload: &common.Payload{
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
ChannelId: "testChannelID",
Timestamp: util.CreateUtcTimestamp(),
}),
SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
},
Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
Start: &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
Stop: &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
}),
},
Assertions: require.New(t),
}),
},
{
name: "Testing deliver of block with private data events with nil header",
prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
wg.Add(1)
p := &peer2.Peer{}
chainManager := createDefaultSupportMamangerMock(config, nil, nil)
deliverServer := &mockDeliverServer{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{
Payload: protoutil.MarshalOrPanic(config.payload),
}, nil).Run(func(_ mock.Arguments) {
// mock Recv calls to get io.EOF to stop the looping for next message
deliverServer.Mock = mock.Mock{}
deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
defer wg.Done()
response := args.Get(0).(*peer.DeliverResponse)
switch response.Type.(type) {
case *peer.DeliverResponse_Status:
config.Equal(common.Status_BAD_REQUEST, response.GetStatus())
case *peer.DeliverResponse_BlockAndPrivateData:
config.FailNow("Unexpected response type")
default:
config.FailNow("Unexpected response type")
}
}).Return(nil)
})
return chainManager, deliverServer
}
}(testConfig{
channelID: "testChannelID",
eventName: "testEvent",
chaincodeName: "mycc",
txID: "testID",
payload: &common.Payload{
Header: nil,
Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
Start: &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
Stop: &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
}),
},
Assertions: require.New(t),
}),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
wg := &sync.WaitGroup{}
chainManager, deliverServer := test.prepare(wg)
metrics := deliver.NewMetrics(&disabled.Provider{})
handler := deliver.NewHandler(chainManager, time.Second, false, metrics, false)
server := &DeliverServer{
DeliverHandler: handler,
PolicyCheckerProvider: defaultPolicyCheckerProvider,
CollectionPolicyChecker: fakeCollPolicyChecker,
IdentityDeserializerMgr: fakeDeserializerMgr,
}
err := server.DeliverWithPrivateData(deliverServer)
wg.Wait()
// no error expected
require.NoError(t, err)
})
}
}
func createDefaultSupportMamangerMock(config testConfig, chaincodeActionPayload *peer.ChaincodeActionPayload, pvtData []*ledger.TxPvtData) *mockChainManager {
chainManager := &mockChainManager{}
iter := &mockIterator{}
reader := &mockReader{}
chain := &mockChainSupport{}
ldgr := &fake.PeerLedger{}
payload, err := createEndorsement(config.channelID, config.txID, chaincodeActionPayload)
config.NoError(err)
payloadBytes, err := proto.Marshal(payload)
config.NoError(err)
block, err := createTestBlock([]*common.Envelope{{
Payload: payloadBytes,
Signature: []byte{},
}})
config.NoError(err)
iter.On("Next").Return(block, common.Status_SUCCESS)
reader.On("Iterator", mock.Anything).Return(iter, uint64(1))
reader.On("Height").Return(uint64(1))
chain.On("Sequence").Return(uint64(0))
chain.On("Reader").Return(reader)
chain.On("Ledger").Return(ldgr)
chainManager.On("GetChain", config.channelID).Return(chain, true)
ldgr.GetPvtDataByNumReturns(pvtData, nil)
return chainManager
}
func createEndorsement(channelID string, txID string, chaincodeActionPayload *peer.ChaincodeActionPayload) (*common.Payload, error) {
var chActionBytes []byte
var err error
if chaincodeActionPayload != nil {
chActionBytes, err = proto.Marshal(chaincodeActionPayload)
if err != nil {
return nil, err
}
}
// the transaction
txBytes, err := proto.Marshal(&peer.Transaction{
Actions: []*peer.TransactionAction{
{
Payload: chActionBytes,
},
},
})
if err != nil {
return nil, err
}
// channel header
chdrBytes, err := proto.Marshal(&common.ChannelHeader{
ChannelId: channelID,
TxId: txID,
Type: int32(common.HeaderType_ENDORSER_TRANSACTION),
})
if err != nil {
return nil, err
}
// the payload
payload := &common.Payload{
Header: &common.Header{
ChannelHeader: chdrBytes,
},
Data: txBytes,
}
return payload, nil
}
func createChaincodeAction(chaincodeName string, eventName string, txID string) (*peer.ChaincodeActionPayload, error) {
// chaincode events
eventsBytes, err := proto.Marshal(&peer.ChaincodeEvent{
ChaincodeId: chaincodeName,
EventName: eventName,
TxId: txID,
})
if err != nil {
return nil, err
}
// chaincode action
actionBytes, err := proto.Marshal(&peer.ChaincodeAction{
ChaincodeId: &peer.ChaincodeID{
Name: chaincodeName,
},
Events: eventsBytes,
})
if err != nil {
return nil, err
}
// proposal response
proposalResBytes, err := proto.Marshal(&peer.ProposalResponsePayload{
Extension: actionBytes,
})
if err != nil {
return nil, err
}
// chaincode action
chaincodeActionPayload := &peer.ChaincodeActionPayload{
Action: &peer.ChaincodeEndorsedAction{
ProposalResponsePayload: proposalResBytes,
Endorsements: []*peer.Endorsement{},
},
}
return chaincodeActionPayload, err
}
func createTestBlock(data []*common.Envelope) (*common.Block, error) {
// block
block := &common.Block{
Header: &common.BlockHeader{
Number: 0,
DataHash: []byte{},
},
Data: &common.BlockData{},
Metadata: &common.BlockMetadata{},
}
for _, d := range data {
envBytes, err := proto.Marshal(d)
if err != nil {
return nil, err
}
block.Data.Data = append(block.Data.Data, envBytes)
}
// making up metadata
block.Metadata.Metadata = make([][]byte, 4)
block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = make([]byte, len(data))
return block, nil
}
func produceSamplePvtdataOrPanic(txNum uint64, nsColls []string) *ledger.TxPvtData {
builder := rwsetutil.NewRWSetBuilder()
for _, nsColl := range nsColls {
nsCollSplit := strings.Split(nsColl, ":")
ns := nsCollSplit[0]
coll := nsCollSplit[1]
builder.AddToPvtAndHashedWriteSet(ns, coll, fmt.Sprintf("key-%s-%s", ns, coll), []byte(fmt.Sprintf("value-%s-%s", ns, coll)))
}
simRes, err := builder.GetTxSimulationResults()
if err != nil {
panic(err)
}
return &ledger.TxPvtData{SeqInBlock: txNum, WriteSet: simRes.PvtSimulationResults}
}