Skip to content

Commit 4d77a8c

Browse files
committed
[FAB-1038] Rework commiter to be more general
As part of the work needed for FAB-1038 to complete, this commit abstracts out transaction validation entity and extacts related code out of noopssinglechain/client.go. Change-Id: I6949c99abab6f58472dd8e95929201e2a472f13d Signed-off-by: Artem Barger <[email protected]>
1 parent 58cde93 commit 4d77a8c

File tree

4 files changed

+270
-111
lines changed

4 files changed

+270
-111
lines changed

core/committer/noopssinglechain/client.go

+14-106
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,22 @@ limitations under the License.
1717
package noopssinglechain
1818

1919
import (
20-
"fmt"
2120
"math"
2221
"time"
2322

2423
"github.com/golang/protobuf/proto"
25-
"github.com/hyperledger/fabric/core/chaincode"
2624
"github.com/hyperledger/fabric/core/committer"
27-
"github.com/hyperledger/fabric/core/util"
25+
"github.com/hyperledger/fabric/core/committer/txvalidator"
26+
"github.com/hyperledger/fabric/core/peer"
2827
"github.com/hyperledger/fabric/events/producer"
28+
gossip_proto "github.com/hyperledger/fabric/gossip/proto"
29+
"github.com/hyperledger/fabric/gossip/service"
2930
"github.com/hyperledger/fabric/protos/common"
3031
"github.com/hyperledger/fabric/protos/orderer"
31-
putils "github.com/hyperledger/fabric/protos/utils"
3232
"github.com/op/go-logging"
3333
"github.com/spf13/viper"
3434
"golang.org/x/net/context"
3535
"google.golang.org/grpc"
36-
37-
"github.com/hyperledger/fabric/core/ledger"
38-
"github.com/hyperledger/fabric/core/peer"
39-
gossip_proto "github.com/hyperledger/fabric/gossip/proto"
40-
"github.com/hyperledger/fabric/gossip/service"
41-
pb "github.com/hyperledger/fabric/protos/peer"
4236
)
4337

4438
var logger *logging.Logger // package-level logger
@@ -178,56 +172,6 @@ func (d *DeliverService) seekLatestFromCommitter(height uint64) error {
178172
})
179173
}
180174

181-
func isTxValidForVscc(payload *common.Payload, envBytes []byte) error {
182-
// TODO: Extract the VSCC/policy from LCCC as soon as this is ready
183-
vscc := "vscc"
184-
185-
chainName := payload.Header.ChainHeader.ChainID
186-
if chainName == "" {
187-
err := fmt.Errorf("transaction header does not contain an chain ID")
188-
logger.Errorf("%s", err)
189-
return err
190-
}
191-
192-
txid := "N/A" // FIXME: is that appropriate?
193-
194-
// build arguments for VSCC invocation
195-
// args[0] - function name (not used now)
196-
// args[1] - serialized Envelope
197-
args := [][]byte{[]byte(""), envBytes}
198-
199-
// create VSCC invocation proposal
200-
vsccCis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeID: &pb.ChaincodeID{Name: vscc}, CtorMsg: &pb.ChaincodeInput{Args: args}}}
201-
prop, err := putils.CreateProposalFromCIS(txid, chainName, vsccCis, []byte(""))
202-
if err != nil {
203-
logger.Errorf("Cannot create a proposal to invoke VSCC, err %s\n", err)
204-
return err
205-
}
206-
207-
// get context for the chaincode execution
208-
var txsim ledger.TxSimulator
209-
lgr := peer.GetLedger(chainName)
210-
txsim, err = lgr.NewTxSimulator()
211-
if err != nil {
212-
logger.Errorf("Cannot obtain tx simulator, err %s\n", err)
213-
return err
214-
}
215-
defer txsim.Done()
216-
ctxt := context.WithValue(context.Background(), chaincode.TXSimulatorKey, txsim)
217-
218-
version := util.GetSysCCVersion()
219-
cccid := chaincode.NewCCContext(chainName, vscc, version, txid, true, prop)
220-
221-
// invoke VSCC
222-
_, _, err = chaincode.ExecuteChaincode(ctxt, cccid, args)
223-
if err != nil {
224-
logger.Errorf("VSCC check failed for transaction, error %s", err)
225-
return err
226-
}
227-
228-
return nil
229-
}
230-
231175
func (d *DeliverService) readUntilClose() {
232176
for {
233177
msg, err := d.client.Recv()
@@ -244,63 +188,26 @@ func (d *DeliverService) readUntilClose() {
244188
logger.Warning("Got error ", t)
245189
case *orderer.DeliverResponse_Block:
246190
seqNum := t.Block.Header.Number
247-
block := &common.Block{}
248-
block.Header = t.Block.Header
249-
250-
// Copy and initialize peer metadata
251-
putils.CopyBlockMetadata(t.Block, block)
252-
block.Data = &common.BlockData{}
253-
for _, d := range t.Block.Data.Data {
254-
if d != nil {
255-
if env, err := putils.GetEnvelopeFromBlock(d); err != nil {
256-
fmt.Printf("Error getting tx from block(%s)\n", err)
257-
} else if env != nil {
258-
// validate the transaction: here we check that the transaction
259-
// is properly formed, properly signed and that the security
260-
// chain binding proposal to endorsements to tx holds. We do
261-
// NOT check the validity of endorsements, though. That's a
262-
// job for VSCC below
263-
payload, _, err := peer.ValidateTransaction(env)
264-
if err != nil {
265-
// TODO: this code needs to receive a bit more attention and discussion:
266-
// it's not clear what it means if a transaction which causes a failure
267-
// in validation is just dropped on the floor
268-
logger.Errorf("Invalid transaction, error %s", err)
269-
} else {
270-
//the payload is used to get headers
271-
err = isTxValidForVscc(payload, d)
272-
if err != nil {
273-
// TODO: this code needs to receive a bit more attention and discussion:
274-
// it's not clear what it means if a transaction which causes a failure
275-
// in validation is just dropped on the floor
276-
logger.Errorf("isTxValidForVscc returned error %s", err)
277-
continue
278-
}
279-
280-
if t, err := proto.Marshal(env); err == nil {
281-
block.Data.Data = append(block.Data.Data, t)
282-
} else {
283-
fmt.Printf("Cannot marshal transactoins %s\n", err)
284-
}
285-
}
286-
} else {
287-
logger.Warning("Nil tx from block")
288-
}
289-
}
290-
}
191+
192+
// Create new transactions validator
193+
validator := txvalidator.NewTxValidator(peer.GetLedger(d.chainID))
194+
// Validate and mark invalid transactions
195+
validator.Validate(t.Block)
291196

292197
numberOfPeers := len(service.GetGossipService().GetPeers())
293198
// Create payload with a block received
294-
payload := createPayload(seqNum, block)
199+
payload := createPayload(seqNum, t.Block)
295200
// Use payload to create gossip message
296201
gossipMsg := createGossipMsg(payload)
202+
297203
logger.Debugf("Adding payload locally, buffer seqNum = [%d], peers number [%d]", seqNum, numberOfPeers)
298204
// Add payload to local state payloads buffer
299205
service.GetGossipService().AddPayload(d.chainID, payload)
206+
300207
// Gossip messages with other nodes
301208
logger.Debugf("Gossiping block [%d], peers number [%d]", seqNum, numberOfPeers)
302209
service.GetGossipService().Gossip(gossipMsg)
303-
if err = producer.SendProducerBlockEvent(block); err != nil {
210+
if err = producer.SendProducerBlockEvent(t.Block); err != nil {
304211
logger.Errorf("Error sending block event %s", err)
305212
}
306213

@@ -319,6 +226,7 @@ func createGossipMsg(payload *gossip_proto.Payload) *gossip_proto.GossipMessage
319226
Payload: payload,
320227
},
321228
},
229+
Tag: gossip_proto.GossipMessage_EMPTY,
322230
}
323231
return gossipMsg
324232
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package txvalidator
18+
19+
import (
20+
"os"
21+
"testing"
22+
23+
"github.com/hyperledger/fabric/core/ledger/kvledger"
24+
"github.com/hyperledger/fabric/core/ledger/testutil"
25+
"github.com/hyperledger/fabric/core/ledger/util"
26+
"github.com/hyperledger/fabric/protos/common"
27+
pb "github.com/hyperledger/fabric/protos/peer"
28+
"github.com/stretchr/testify/assert"
29+
)
30+
31+
type mockVsccValidator struct {
32+
}
33+
34+
func (v *mockVsccValidator) VSCCValidateTx(payload *common.Payload, envBytes []byte) error {
35+
return nil
36+
}
37+
38+
func TestKVLedgerBlockStorage(t *testing.T) {
39+
conf := kvledger.NewConf("/tmp/tests/ledger/", 0)
40+
defer os.RemoveAll("/tmp/tests/ledger/")
41+
42+
ledger, _ := kvledger.NewKVLedger(conf)
43+
defer ledger.Close()
44+
45+
validator := &txValidator{ledger, &mockVsccValidator{}}
46+
47+
bcInfo, _ := ledger.GetBlockchainInfo()
48+
testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
49+
Height: 0, CurrentBlockHash: nil, PreviousBlockHash: nil})
50+
51+
simulator, _ := ledger.NewTxSimulator()
52+
simulator.SetState("ns1", "key1", []byte("value1"))
53+
simulator.SetState("ns1", "key2", []byte("value2"))
54+
simulator.SetState("ns1", "key3", []byte("value3"))
55+
simulator.Done()
56+
57+
simRes, _ := simulator.GetTxSimulationResults()
58+
block := testutil.ConstructBlock(t, [][]byte{simRes}, true)
59+
60+
validator.Validate(block)
61+
62+
txsfltr := util.NewFilterBitArrayFromBytes(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
63+
64+
assert.True(t, !txsfltr.IsSet(uint(0)))
65+
assert.True(t, !txsfltr.IsSet(uint(1)))
66+
assert.True(t, !txsfltr.IsSet(uint(2)))
67+
}

0 commit comments

Comments
 (0)