Skip to content

Commit 79aa4df

Browse files
committed
[FAB-1384]: Change ValidatedLedger APIs
In order to provide support for JIRA [FAB-1038], validated ledger should be able to receive block to commit with list of invalid transactions to execute MVCC validation as part of the flow described in FAB-1038. Change-Id: Ica9c48c036ecd97a17484e4954a85d1b7abccf2a Signed-off-by: Artem Barger <[email protected]> Signed-off-by: Yacov Manevich <[email protected]> Signed-off-by: Artem Barger <[email protected]>
1 parent 0eadb03 commit 79aa4df

File tree

16 files changed

+159
-150
lines changed

16 files changed

+159
-150
lines changed

core/chaincode/exectransaction_test.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,8 @@ func endTxSimulation(chainID string, txsim ledger.TxSimulator, payload []byte, c
191191
//create the block with 1 transaction
192192
block := common.NewBlock(1, []byte{})
193193
block.Data.Data = [][]byte{envBytes}
194-
if _, _, err = lgr.RemoveInvalidTransactionsAndPrepare(block); err != nil {
195-
return err
196-
}
197194
//commit the block
198-
if err := lgr.Commit(); err != nil {
195+
if err := lgr.Commit(block); err != nil {
199196
return err
200197
}
201198
}

core/committer/committer_impl.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,7 @@ func NewLedgerCommitter(ledger ledger.ValidatedLedger) *LedgerCommitter {
4848

4949
// CommitBlock commits block to into the ledger
5050
func (lc *LedgerCommitter) CommitBlock(block *common.Block) error {
51-
if _, _, err := lc.ledger.RemoveInvalidTransactionsAndPrepare(block); err != nil {
52-
return err
53-
}
54-
if err := lc.ledger.Commit(); err != nil {
51+
if err := lc.ledger.Commit(block); err != nil {
5552
return err
5653
}
5754
return nil

core/endorser/endorser.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,7 @@ func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID string, sig
334334
block := common.NewBlock(1, []byte{})
335335
block.Data.Data = [][]byte{txBytes}
336336
block.Header.DataHash = block.Data.Hash()
337-
if _, _, err = lgr.RemoveInvalidTransactionsAndPrepare(block); err != nil {
338-
return err
339-
}
340-
341-
if err = lgr.Commit(); err != nil {
337+
if err = lgr.Commit(block); err != nil {
342338
return err
343339
}
344340

core/ledger/kvledger/example/committer.go

+4-12
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"github.com/hyperledger/fabric/core/ledger"
2121

2222
"github.com/hyperledger/fabric/protos/common"
23-
pb "github.com/hyperledger/fabric/protos/peer"
2423
)
2524

2625
// Committer a toy committer
@@ -34,17 +33,10 @@ func ConstructCommitter(ledger ledger.ValidatedLedger) *Committer {
3433
}
3534

3635
// CommitBlock commits the block
37-
func (c *Committer) CommitBlock(rawBlock *common.Block) (*common.Block, []*pb.InvalidTransaction, error) {
38-
var validBlock *common.Block
39-
var invalidTxs []*pb.InvalidTransaction
40-
var err error
36+
func (c *Committer) CommitBlock(rawBlock *common.Block) error {
4137
logger.Debugf("Committer validating the block...")
42-
if validBlock, invalidTxs, err = c.ledger.RemoveInvalidTransactionsAndPrepare(rawBlock); err != nil {
43-
return nil, nil, err
38+
if err := c.ledger.Commit(rawBlock); err != nil {
39+
return err
4440
}
45-
logger.Debugf("Committer committing the block...")
46-
if err = c.ledger.Commit(); err != nil {
47-
return nil, nil, err
48-
}
49-
return validBlock, invalidTxs, err
41+
return nil
5042
}

core/ledger/kvledger/example/main/example.go

+18-9
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import (
2424
"github.com/hyperledger/fabric/core/ledger/kvledger"
2525
"github.com/hyperledger/fabric/core/ledger/kvledger/example"
2626
"github.com/hyperledger/fabric/core/ledger/testutil"
27+
"github.com/hyperledger/fabric/core/ledger/util"
2728
"github.com/hyperledger/fabric/protos/common"
28-
pb "github.com/hyperledger/fabric/protos/peer"
2929
)
3030

3131
const (
@@ -97,9 +97,9 @@ func initApp() {
9797
accounts[3]: 100})
9898
handleError(err, true)
9999
rawBlock := consenter.ConstructBlock(tx)
100-
finalBlock, invalidTx, err := committer.CommitBlock(rawBlock)
100+
err = committer.CommitBlock(rawBlock)
101101
handleError(err, true)
102-
printBlocksInfo(rawBlock, finalBlock, invalidTx)
102+
printBlocksInfo(rawBlock)
103103
}
104104

105105
func transferFunds() {
@@ -112,9 +112,9 @@ func transferFunds() {
112112
rawBlock := consenter.ConstructBlock(tx1, tx2)
113113

114114
// act as committing peer to commit the Raw Block
115-
finalBlock, invalidTx, err := committer.CommitBlock(rawBlock)
115+
err = committer.CommitBlock(rawBlock)
116116
handleError(err, true)
117-
printBlocksInfo(rawBlock, finalBlock, invalidTx)
117+
printBlocksInfo(rawBlock)
118118
}
119119

120120
func tryInvalidTransfer() {
@@ -128,14 +128,23 @@ func tryDoubleSpend() {
128128
tx2, err := app.TransferFunds("account1", "account4", 50)
129129
handleError(err, true)
130130
rawBlock := consenter.ConstructBlock(tx1, tx2)
131-
finalBlock, invalidTx, err := committer.CommitBlock(rawBlock)
131+
err = committer.CommitBlock(rawBlock)
132132
handleError(err, true)
133-
printBlocksInfo(rawBlock, finalBlock, invalidTx)
133+
printBlocksInfo(rawBlock)
134134
}
135135

136-
func printBlocksInfo(rawBlock *common.Block, finalBlock *common.Block, invalidTxs []*pb.InvalidTransaction) {
136+
func printBlocksInfo(block *common.Block) {
137+
// Read invalid transactions filter
138+
txsFltr := util.NewFilterBitArrayFromBytes(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
139+
numOfInvalid := 0
140+
// Count how many transaction indeed invalid
141+
for i := 0; i < len(block.Data.Data); i++ {
142+
if txsFltr.IsSet(uint(i)) {
143+
numOfInvalid++
144+
}
145+
}
137146
fmt.Printf("Num txs in rawBlock = [%d], num invalidTxs = [%d]\n",
138-
len(rawBlock.Data.Data), len(invalidTxs))
147+
len(block.Data.Data), numOfInvalid)
139148
}
140149

141150
func printBalances() {

core/ledger/kvledger/kv_ledger.go

+22-35
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ import (
2727
"github.com/hyperledger/fabric/core/ledger/history"
2828
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/couchdbtxmgmt"
2929
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/stateleveldb"
30+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr"
3031
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr"
3132
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
3233

3334
logging "github.com/op/go-logging"
3435

35-
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr"
3636
"github.com/hyperledger/fabric/protos/common"
3737
pb "github.com/hyperledger/fabric/protos/peer"
3838
)
@@ -60,10 +60,9 @@ func NewConf(filesystemPath string, maxBlockfileSize int) *Conf {
6060
// KVLedger provides an implementation of `ledger.ValidatedLedger`.
6161
// This implementation provides a key-value based data model
6262
type KVLedger struct {
63-
blockStore blkstorage.BlockStore
64-
txtmgmt txmgr.TxMgr
65-
historymgmt history.HistMgr
66-
pendingBlockToCommit *common.Block
63+
blockStore blkstorage.BlockStore
64+
txtmgmt txmgr.TxMgr
65+
historymgmt history.HistMgr
6766
}
6867

6968
// NewKVLedger constructs new `KVLedger`
@@ -114,10 +113,13 @@ func NewKVLedger(conf *Conf) (*KVLedger, error) {
114113
couchDBDef.Username, //enter couchDB id here
115114
couchDBDef.Password) //enter couchDB pw here
116115
}
117-
l := &KVLedger{blockStore, txmgmt, historymgmt, nil}
116+
117+
l := &KVLedger{blockStore, txmgmt, historymgmt}
118+
118119
if err := recoverStateDB(l); err != nil {
119120
panic(fmt.Errorf(`Error during state DB recovery:%s`, err))
120121
}
122+
121123
return l, nil
122124
}
123125

@@ -135,7 +137,7 @@ func recoverStateDB(l *KVLedger) error {
135137
if savepointValue, err = l.txtmgmt.GetBlockNumFromSavepoint(); err != nil {
136138
return err
137139
}
138-
logger.Debugf("savepointValue=%d, info.Height=%d", savepointValue, info.Height)
140+
139141
//Checking whether the savepointValue is in sync with block storage height
140142
if savepointValue == info.Height {
141143
return nil
@@ -145,19 +147,20 @@ func recoverStateDB(l *KVLedger) error {
145147

146148
//Compute updateSet for each missing savepoint and commit to state DB
147149
for blockNumber := savepointValue + 1; blockNumber <= info.Height; blockNumber++ {
148-
if l.pendingBlockToCommit, err = l.GetBlockByNumber(blockNumber); err != nil {
150+
var block *common.Block
151+
if block, err = l.GetBlockByNumber(blockNumber); err != nil {
149152
return err
150153
}
151154
logger.Debugf("Constructing updateSet for the block %d", blockNumber)
152-
if _, _, err = l.txtmgmt.ValidateAndPrepare(l.pendingBlockToCommit, false); err != nil {
155+
if err = l.txtmgmt.ValidateAndPrepare(block, false); err != nil {
153156
return err
154157
}
155158
logger.Debugf("Committing block %d to state database", blockNumber)
156159
if err = l.txtmgmt.Commit(); err != nil {
157160
return err
158161
}
159162
}
160-
l.pendingBlockToCommit = nil
163+
161164
return nil
162165
}
163166

@@ -208,54 +211,38 @@ func (l *KVLedger) NewQueryExecutor() (ledger.QueryExecutor, error) {
208211
return l.txtmgmt.NewQueryExecutor()
209212
}
210213

211-
// RemoveInvalidTransactionsAndPrepare validates all the transactions in the given block
212-
// and returns a block that contains only valid transactions and a list of transactions that are invalid
213-
func (l *KVLedger) RemoveInvalidTransactionsAndPrepare(block *common.Block) (*common.Block, []*pb.InvalidTransaction, error) {
214-
var validBlock *common.Block
215-
var invalidTxs []*pb.InvalidTransaction
214+
// Commit commits the valid block (returned in the method RemoveInvalidTransactionsAndPrepare) and related state changes
215+
func (l *KVLedger) Commit(block *common.Block) error {
216216
var err error
217-
validBlock, invalidTxs, err = l.txtmgmt.ValidateAndPrepare(block, true)
218-
if err == nil {
219-
l.pendingBlockToCommit = validBlock
220-
}
221-
return validBlock, invalidTxs, err
222-
}
223217

224-
// Commit commits the valid block (returned in the method RemoveInvalidTransactionsAndPrepare) and related state changes
225-
func (l *KVLedger) Commit() error {
226-
if l.pendingBlockToCommit == nil {
227-
panic(fmt.Errorf(`Nothing to commit. RemoveInvalidTransactionsAndPrepare() method should have been called and should not have thrown error`))
218+
logger.Debugf("Validating block")
219+
err = l.txtmgmt.ValidateAndPrepare(block, true)
220+
if err != nil {
221+
return err
228222
}
229223

230224
logger.Debugf("Committing block to storage")
231-
if err := l.blockStore.AddBlock(l.pendingBlockToCommit); err != nil {
225+
if err = l.blockStore.AddBlock(block); err != nil {
232226
return err
233227
}
234228

235229
logger.Debugf("Committing block to state database")
236-
if err := l.txtmgmt.Commit(); err != nil {
230+
if err = l.txtmgmt.Commit(); err != nil {
237231
panic(fmt.Errorf(`Error during commit to txmgr:%s`, err))
238232
}
239233

240234
//TODO future will want to run async with state db writes. History needs to wait for chain (FSBlock) to write but not the state db
241235
logger.Debugf("===HISTORYDB=== Commit() will write to hisotry if enabled else will be by-passed if not enabled: vledgerconfig.IsHistoryDBEnabled(): %v\n", ledgerconfig.IsHistoryDBEnabled())
242236
if ledgerconfig.IsHistoryDBEnabled() == true {
243237
logger.Debugf("Committing transactions to history database")
244-
if err := l.historymgmt.Commit(l.pendingBlockToCommit); err != nil {
238+
if err := l.historymgmt.Commit(block); err != nil {
245239
panic(fmt.Errorf(`Error during commit to txthistory:%s`, err))
246240
}
247241
}
248242

249-
l.pendingBlockToCommit = nil
250243
return nil
251244
}
252245

253-
// Rollback rollbacks the changes caused by the last invocation to method `RemoveInvalidTransactionsAndPrepare`
254-
func (l *KVLedger) Rollback() {
255-
l.txtmgmt.Rollback()
256-
l.pendingBlockToCommit = nil
257-
}
258-
259246
// Close closes `KVLedger`
260247
func (l *KVLedger) Close() {
261248
l.blockStore.Shutdown()

core/ledger/kvledger/kv_ledger_test.go

+9-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
2323
"github.com/hyperledger/fabric/core/ledger/testutil"
2424
pb "github.com/hyperledger/fabric/protos/peer"
25+
"github.com/stretchr/testify/assert"
2526
)
2627

2728
func TestKVLedgerBlockStorage(t *testing.T) {
@@ -41,8 +42,7 @@ func TestKVLedgerBlockStorage(t *testing.T) {
4142
simRes, _ := simulator.GetTxSimulationResults()
4243
bg := testutil.NewBlockGenerator(t)
4344
block1 := bg.NextBlock([][]byte{simRes}, false)
44-
ledger.RemoveInvalidTransactionsAndPrepare(block1)
45-
ledger.Commit()
45+
ledger.Commit(block1)
4646

4747
bcInfo, _ = ledger.GetBlockchainInfo()
4848
block1Hash := block1.Header.Hash()
@@ -56,8 +56,7 @@ func TestKVLedgerBlockStorage(t *testing.T) {
5656
simulator.Done()
5757
simRes, _ = simulator.GetTxSimulationResults()
5858
block2 := bg.NextBlock([][]byte{simRes}, false)
59-
ledger.RemoveInvalidTransactionsAndPrepare(block2)
60-
ledger.Commit()
59+
ledger.Commit(block2)
6160

6261
bcInfo, _ = ledger.GetBlockchainInfo()
6362
block2Hash := block2.Header.Hash()
@@ -99,9 +98,7 @@ func TestKVLedgerStateDBRecovery(t *testing.T) {
9998
bg := testutil.NewBlockGenerator(t)
10099
block1 := bg.NextBlock([][]byte{simRes}, false)
101100
//performing validation of read and write set to find valid transactions
102-
ledger.RemoveInvalidTransactionsAndPrepare(block1)
103-
//writing the validated block to block storage and committing the transaction to state DB
104-
ledger.Commit()
101+
ledger.Commit(block1)
105102

106103
bcInfo, _ = ledger.GetBlockchainInfo()
107104
block1Hash := block1.Header.Hash()
@@ -119,10 +116,11 @@ func TestKVLedgerStateDBRecovery(t *testing.T) {
119116
//generating a block based on the simulation result
120117
block2 := bg.NextBlock([][]byte{simRes}, false)
121118
//performing validation of read and write set to find valid transactions
122-
ledger.RemoveInvalidTransactionsAndPrepare(block2)
119+
ledger.txtmgmt.ValidateAndPrepare(block2, true)
123120
//writing the validated block to block storage but not committing the transaction to state DB
124-
ledger.blockStore.AddBlock(ledger.pendingBlockToCommit)
121+
err := ledger.blockStore.AddBlock(block2)
125122
//assume that peer fails here before committing the transaction
123+
assert.NoError(t, err)
126124

127125
bcInfo, _ = ledger.GetBlockchainInfo()
128126
block2Hash := block2.Header.Hash()
@@ -186,8 +184,7 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
186184
bg := testutil.NewBlockGenerator(t)
187185
block1 := bg.NextBlock([][]byte{simRes}, false)
188186

189-
ledger.RemoveInvalidTransactionsAndPrepare(block1)
190-
ledger.Commit()
187+
ledger.Commit(block1)
191188

192189
bcInfo, _ = ledger.GetBlockchainInfo()
193190
block1Hash := block1.Header.Hash()
@@ -214,8 +211,7 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
214211
simulationResults = append(simulationResults, simRes2)
215212

216213
block2 := bg.NextBlock(simulationResults, false)
217-
ledger.RemoveInvalidTransactionsAndPrepare(block2)
218-
ledger.Commit()
214+
ledger.Commit(block2)
219215

220216
bcInfo, _ = ledger.GetBlockchainInfo()
221217
block2Hash := block2.Header.Hash()

core/ledger/kvledger/marble_example/main/marble_example.go

+16-7
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import (
2424
"github.com/hyperledger/fabric/core/ledger/kvledger"
2525
"github.com/hyperledger/fabric/core/ledger/kvledger/example"
2626
"github.com/hyperledger/fabric/core/ledger/testutil"
27+
"github.com/hyperledger/fabric/core/ledger/util"
2728
"github.com/hyperledger/fabric/protos/common"
28-
pb "github.com/hyperledger/fabric/protos/peer"
2929
logging "github.com/op/go-logging"
3030
)
3131

@@ -81,24 +81,33 @@ func initApp() {
8181
tx, err := marbleApp.CreateMarble(marble)
8282
handleError(err, true)
8383
rawBlock := consenter.ConstructBlock(tx)
84-
finalBlock, invalidTx, err := committer.CommitBlock(rawBlock)
84+
err = committer.CommitBlock(rawBlock)
8585
handleError(err, true)
86-
printBlocksInfo(rawBlock, finalBlock, invalidTx)
86+
printBlocksInfo(rawBlock)
8787
}
8888

8989
func transferMarble() {
9090
logger.Debugf("===COUCHDB=== Marble Example transferMarble()")
9191
tx1, err := marbleApp.TransferMarble([]string{"marble1", "jerry"})
9292
handleError(err, true)
9393
rawBlock := consenter.ConstructBlock(tx1)
94-
finalBlock, invalidTx, err := committer.CommitBlock(rawBlock)
94+
err = committer.CommitBlock(rawBlock)
9595
handleError(err, true)
96-
printBlocksInfo(rawBlock, finalBlock, invalidTx)
96+
printBlocksInfo(rawBlock)
9797
}
9898

99-
func printBlocksInfo(rawBlock *common.Block, finalBlock *common.Block, invalidTxs []*pb.InvalidTransaction) {
99+
func printBlocksInfo(block *common.Block) {
100+
// Read invalid transactions filter
101+
txsFltr := util.NewFilterBitArrayFromBytes(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
102+
numOfInvalid := 0
103+
// Count how many transaction indeed invalid
104+
for i := 0; i < len(block.Data.Data); i++ {
105+
if txsFltr.IsSet(uint(i)) {
106+
numOfInvalid++
107+
}
108+
}
100109
fmt.Printf("Num txs in rawBlock = [%d], num invalidTxs = [%d]\n",
101-
len(rawBlock.Data.Data), len(invalidTxs))
110+
len(block.Data.Data), numOfInvalid)
102111
}
103112

104113
func handleError(err error, quit bool) {

0 commit comments

Comments
 (0)