committer_test.go 6.61 KB
Newer Older
1
/*
2
Copyright IBM Corp. All Rights Reserved.
3

4
SPDX-License-Identifier: Apache-2.0
5
6
7
8
9
*/

package committer

import (
10
	"errors"
11
	"sync/atomic"
12
13
	"testing"

14
	"github.com/hyperledger/fabric/common/configtx/test"
15
	"github.com/hyperledger/fabric/common/ledger"
16
	"github.com/hyperledger/fabric/common/ledger/testutil"
17
	"github.com/hyperledger/fabric/common/tools/configtxgen/configtxgentest"
18
	"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
19
	"github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
20
	ledger2 "github.com/hyperledger/fabric/core/ledger"
21
	cut "github.com/hyperledger/fabric/core/ledger/util"
22
	"github.com/hyperledger/fabric/protos/common"
23
	"github.com/hyperledger/fabric/protos/peer"
24
	"github.com/stretchr/testify/assert"
25
	"github.com/stretchr/testify/mock"
26
27
)

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
type mockLedger struct {
	height       uint64
	currentHash  []byte
	previousHash []byte
	mock.Mock
}

func (m *mockLedger) GetBlockchainInfo() (*common.BlockchainInfo, error) {
	info := &common.BlockchainInfo{
		Height:            m.height,
		CurrentBlockHash:  m.currentHash,
		PreviousBlockHash: m.previousHash,
	}
	return info, nil
}

func (m *mockLedger) GetBlockByNumber(blockNumber uint64) (*common.Block, error) {
	args := m.Called(blockNumber)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetBlocksIterator(startBlockNumber uint64) (ledger.ResultsIterator, error) {
	args := m.Called(startBlockNumber)
	return args.Get(0).(ledger.ResultsIterator), args.Error(1)
}

func (m *mockLedger) Close() {

}

func (m *mockLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) {
	args := m.Called(txID)
	return args.Get(0).(*peer.ProcessedTransaction), args.Error(1)
}

func (m *mockLedger) GetBlockByHash(blockHash []byte) (*common.Block, error) {
	args := m.Called(blockHash)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetBlockByTxID(txID string) (*common.Block, error) {
	args := m.Called(txID)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
	args := m.Called(txID)
	return args.Get(0).(peer.TxValidationCode), args.Error(1)
}

func (m *mockLedger) NewTxSimulator(txid string) (ledger2.TxSimulator, error) {
	args := m.Called(txid)
	return args.Get(0).(ledger2.TxSimulator), args.Error(1)
}

func (m *mockLedger) NewQueryExecutor() (ledger2.QueryExecutor, error) {
	args := m.Called()
	return args.Get(0).(ledger2.QueryExecutor), args.Error(1)
}

func (m *mockLedger) NewHistoryQueryExecutor() (ledger2.HistoryQueryExecutor, error) {
	args := m.Called()
	return args.Get(0).(ledger2.HistoryQueryExecutor), args.Error(1)
}

func (m *mockLedger) GetPvtDataAndBlockByNum(blockNum uint64, filter ledger2.PvtNsCollFilter) (*ledger2.BlockAndPvtData, error) {
	args := m.Called(blockNum, filter)
	return args.Get(0).(*ledger2.BlockAndPvtData), args.Error(1)
}

func (m *mockLedger) GetPvtDataByNum(blockNum uint64, filter ledger2.PvtNsCollFilter) ([]*ledger2.TxPvtData, error) {
	args := m.Called(blockNum, filter)
	return args.Get(0).([]*ledger2.TxPvtData), args.Error(1)
}

func (m *mockLedger) CommitWithPvtData(blockAndPvtdata *ledger2.BlockAndPvtData) error {
	m.height += 1
	m.previousHash = m.currentHash
	m.currentHash = blockAndPvtdata.Block.Header.DataHash
	args := m.Called(blockAndPvtdata)
	return args.Error(0)
}

func (m *mockLedger) PurgePrivateData(maxBlockNumToRetain uint64) error {
	args := m.Called(maxBlockNumToRetain)
	return args.Error(0)
}

func (m *mockLedger) PrivateDataMinBlockNum() (uint64, error) {
	args := m.Called()
	return args.Get(0).(uint64), args.Error(1)
}

func (m *mockLedger) Prune(policy ledger.PrunePolicy) error {
	args := m.Called(policy)
	return args.Error(0)
}

func createLedger(channelID string) (*common.Block, *mockLedger) {
	gb, _ := test.MakeGenesisBlock(channelID)
	ledger := &mockLedger{
		height:       1,
		previousHash: []byte{},
		currentHash:  gb.Header.DataHash,
	}
	return gb, ledger
}

136
func TestKVLedgerBlockStorage(t *testing.T) {
137
138
139
140
141
142
143
144
145
146
147
148
	t.Parallel()
	gb, ledger := createLedger("TestLedger")
	block1 := testutil.ConstructBlock(t, 1, gb.Header.DataHash, [][]byte{{1, 2, 3, 4}, {5, 6, 7, 8}}, true)

	ledger.On("CommitWithPvtData", mock.Anything).Run(func(args mock.Arguments) {
		b := args.Get(0).(*ledger2.BlockAndPvtData)
		assert.Equal(t, uint64(1), b.Block.Header.GetNumber())
		assert.Equal(t, gb.Header.DataHash, b.Block.Header.PreviousHash)
		assert.Equal(t, block1.Header.DataHash, b.Block.Header.DataHash)
	}).Return(nil)

	ledger.On("GetBlockByNumber", uint64(0)).Return(gb, nil)
149

150
	committer := NewLedgerCommitter(ledger)
151
	height, err := committer.LedgerHeight()
152
	assert.Equal(t, uint64(1), height)
153
154
	assert.NoError(t, err)

155
156
157
	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block1,
	})
158
159
160
	assert.NoError(t, err)

	height, err = committer.LedgerHeight()
161
	assert.Equal(t, uint64(2), height)
162
163
	assert.NoError(t, err)

164
	blocks := committer.GetBlocks([]uint64{0})
165
166
167
	assert.Equal(t, 1, len(blocks))
	assert.NoError(t, err)
}
168
169

func TestNewLedgerCommitterReactive(t *testing.T) {
170
	t.Parallel()
171
	chainID := "TestLedger"
172
173
	_, ledger := createLedger(chainID)
	ledger.On("CommitWithPvtData", mock.Anything).Return(nil)
174
	var configArrived int32
175
	committer := NewLedgerCommitterReactive(ledger, func(_ *common.Block) error {
176
177
178
179
180
181
182
183
		atomic.AddInt32(&configArrived, 1)
		return nil
	})

	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

184
	profile := configtxgentest.Load(localconfig.SampleSingleMSPSoloProfile)
185
	block := encoder.New(profile).GenesisBlockForChannel(chainID)
186
187
	txsFilter := cut.NewTxValidationFlagsSetValue(len(block.Data.Data), peer.TxValidationCode_VALID)
	block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
188

189
	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
190
191
		Block: block,
	})
192
	assert.NoError(t, err)
193
194
	assert.Equal(t, int32(1), atomic.LoadInt32(&configArrived))
}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

func TestNewLedgerCommitterReactiveFailedConfigUpdate(t *testing.T) {
	t.Parallel()
	chainID := "TestLedger"
	_, ledger := createLedger(chainID)
	ledger.On("CommitWithPvtData", mock.Anything).Return(nil)
	var configArrived int32
	committer := NewLedgerCommitterReactive(ledger, func(_ *common.Block) error {
		return errors.New("failed update config")
	})

	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

210
	profile := configtxgentest.Load(localconfig.SampleSingleMSPSoloProfile)
211
212
213
214
215
216
217
218
219
	block := encoder.New(profile).GenesisBlockForChannel(chainID)

	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block,
	})

	assert.Error(t, err)
	assert.Equal(t, int32(0), atomic.LoadInt32(&configArrived))
}