github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/committer/txvalidator/validator_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 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 "fmt" 21 "os" 22 "testing" 23 24 "github.com/hyperledger/fabric/common/cauthdsl" 25 ctxt "github.com/hyperledger/fabric/common/configtx/test" 26 "github.com/hyperledger/fabric/common/ledger/testutil" 27 "github.com/hyperledger/fabric/common/mocks/scc" 28 "github.com/hyperledger/fabric/common/util" 29 ccp "github.com/hyperledger/fabric/core/common/ccprovider" 30 "github.com/hyperledger/fabric/core/common/sysccprovider" 31 "github.com/hyperledger/fabric/core/ledger" 32 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 33 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 34 lutils "github.com/hyperledger/fabric/core/ledger/util" 35 "github.com/hyperledger/fabric/core/mocks/ccprovider" 36 "github.com/hyperledger/fabric/msp" 37 "github.com/hyperledger/fabric/msp/mgmt" 38 "github.com/hyperledger/fabric/msp/mgmt/testtools" 39 "github.com/hyperledger/fabric/protos/common" 40 "github.com/hyperledger/fabric/protos/peer" 41 "github.com/hyperledger/fabric/protos/utils" 42 "github.com/spf13/viper" 43 "github.com/stretchr/testify/assert" 44 ) 45 46 func signedByAnyMember(ids []string) []byte { 47 p := cauthdsl.SignedByAnyMember(ids) 48 return utils.MarshalOrPanic(p) 49 } 50 51 func setupLedgerAndValidator(t *testing.T) (ledger.PeerLedger, Validator) { 52 viper.Set("peer.fileSystemPath", "/tmp/fabric/validatortest") 53 ledgermgmt.InitializeTestEnv() 54 gb, err := ctxt.MakeGenesisBlock("TestLedger") 55 assert.NoError(t, err) 56 theLedger, err := ledgermgmt.CreateLedger(gb) 57 assert.NoError(t, err) 58 theValidator := NewTxValidator(&mockSupport{l: theLedger}) 59 60 return theLedger, theValidator 61 } 62 63 func createRWset(t *testing.T, ccnames ...string) []byte { 64 rwsetBuilder := rwsetutil.NewRWSetBuilder() 65 for _, ccname := range ccnames { 66 rwsetBuilder.AddToWriteSet(ccname, "key", []byte("value")) 67 } 68 rwset := rwsetBuilder.GetTxReadWriteSet() 69 rws, err := rwset.ToProtoBytes() 70 assert.NoError(t, err) 71 return rws 72 } 73 74 func getProposal(ccID string) (*peer.Proposal, error) { 75 cis := &peer.ChaincodeInvocationSpec{ 76 ChaincodeSpec: &peer.ChaincodeSpec{ 77 ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion}, 78 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}}, 79 Type: peer.ChaincodeSpec_GOLANG}} 80 81 proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, signerSerialized) 82 return proposal, err 83 } 84 85 const ccVersion = "1.0" 86 87 func getEnv(ccID string, res []byte, t *testing.T) *common.Envelope { 88 // get a toy proposal 89 prop, err := getProposal(ccID) 90 assert.NoError(t, err) 91 92 response := &peer.Response{Status: 200} 93 94 // endorse it to get a proposal response 95 presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, res, nil, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, nil, signer) 96 assert.NoError(t, err) 97 98 // assemble a transaction from that proposal and endorsement 99 tx, err := utils.CreateSignedTx(prop, signer, presp) 100 assert.NoError(t, err) 101 102 return tx 103 } 104 105 func putCCInfoWithVSCCAndVer(theLedger ledger.PeerLedger, ccname, vscc, ver string, policy []byte, t *testing.T) { 106 cd := &ccp.ChaincodeData{ 107 Name: ccname, 108 Version: ver, 109 Vscc: vscc, 110 Policy: policy, 111 } 112 113 cdbytes := utils.MarshalOrPanic(cd) 114 115 simulator, err := theLedger.NewTxSimulator() 116 assert.NoError(t, err) 117 simulator.SetState("lscc", ccname, cdbytes) 118 simulator.Done() 119 120 simRes, err := simulator.GetTxSimulationResults() 121 assert.NoError(t, err) 122 block0 := testutil.ConstructBlock(t, 1, []byte("hash"), [][]byte{simRes}, true) 123 err = theLedger.Commit(block0) 124 assert.NoError(t, err) 125 } 126 127 func putCCInfo(theLedger ledger.PeerLedger, ccname string, policy []byte, t *testing.T) { 128 putCCInfoWithVSCCAndVer(theLedger, ccname, "vscc", ccVersion, policy, t) 129 } 130 131 type mockSupport struct { 132 l ledger.PeerLedger 133 } 134 135 func (m *mockSupport) Ledger() ledger.PeerLedger { 136 return m.l 137 } 138 139 func (m *mockSupport) MSPManager() msp.MSPManager { 140 return mgmt.GetManagerForChain(util.GetTestChainID()) 141 } 142 143 func (m *mockSupport) Apply(configtx *common.ConfigEnvelope) error { 144 return nil 145 } 146 147 func (m *mockSupport) GetMSPIDs(cid string) []string { 148 return []string{"DEFAULT"} 149 } 150 151 func assertInvalid(block *common.Block, t *testing.T, code peer.TxValidationCode) { 152 txsFilter := lutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 153 assert.True(t, txsFilter.IsInvalid(0)) 154 assert.True(t, txsFilter.IsSetTo(0, code)) 155 } 156 157 func assertValid(block *common.Block, t *testing.T) { 158 txsFilter := lutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 159 assert.False(t, txsFilter.IsInvalid(0)) 160 } 161 162 func TestInvokeBadRWSet(t *testing.T) { 163 l, v := setupLedgerAndValidator(t) 164 defer ledgermgmt.CleanupTestEnv() 165 defer l.Close() 166 167 ccID := "mycc" 168 169 tx := getEnv(ccID, []byte("barf"), t) 170 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 171 172 err := v.Validate(b) 173 assert.NoError(t, err) 174 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 175 } 176 177 func TestInvokeNoPolicy(t *testing.T) { 178 l, v := setupLedgerAndValidator(t) 179 defer ledgermgmt.CleanupTestEnv() 180 defer l.Close() 181 182 ccID := "mycc" 183 184 putCCInfo(l, ccID, nil, t) 185 186 tx := getEnv(ccID, createRWset(t, ccID), t) 187 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 188 189 err := v.Validate(b) 190 assert.NoError(t, err) 191 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 192 } 193 194 func TestInvokeOK(t *testing.T) { 195 l, v := setupLedgerAndValidator(t) 196 defer ledgermgmt.CleanupTestEnv() 197 defer l.Close() 198 199 ccID := "mycc" 200 201 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 202 203 tx := getEnv(ccID, createRWset(t, ccID), t) 204 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 205 206 err := v.Validate(b) 207 assert.NoError(t, err) 208 assertValid(b, t) 209 } 210 211 func TestInvokeOKSCC(t *testing.T) { 212 l, v := setupLedgerAndValidator(t) 213 defer ledgermgmt.CleanupTestEnv() 214 defer l.Close() 215 216 ccID := "lscc" 217 218 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 219 220 tx := getEnv(ccID, createRWset(t, ccID), t) 221 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 222 223 err := v.Validate(b) 224 assert.NoError(t, err) 225 assertValid(b, t) 226 } 227 228 func TestInvokeNOKWritesToLSCC(t *testing.T) { 229 l, v := setupLedgerAndValidator(t) 230 defer ledgermgmt.CleanupTestEnv() 231 defer l.Close() 232 233 ccID := "mycc" 234 235 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 236 237 tx := getEnv(ccID, createRWset(t, ccID, "lscc"), t) 238 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 239 240 err := v.Validate(b) 241 assert.NoError(t, err) 242 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 243 } 244 245 func TestInvokeNOKWritesToESCC(t *testing.T) { 246 l, v := setupLedgerAndValidator(t) 247 defer ledgermgmt.CleanupTestEnv() 248 defer l.Close() 249 250 ccID := "mycc" 251 252 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 253 254 tx := getEnv(ccID, createRWset(t, ccID, "escc"), t) 255 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 256 257 err := v.Validate(b) 258 assert.NoError(t, err) 259 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 260 } 261 262 func TestInvokeNOKWritesToNotExt(t *testing.T) { 263 l, v := setupLedgerAndValidator(t) 264 defer ledgermgmt.CleanupTestEnv() 265 defer l.Close() 266 267 ccID := "mycc" 268 269 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 270 271 tx := getEnv(ccID, createRWset(t, ccID, "notext"), t) 272 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 273 274 err := v.Validate(b) 275 assert.NoError(t, err) 276 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 277 } 278 279 func TestInvokeNOKInvokesNotExt(t *testing.T) { 280 l, v := setupLedgerAndValidator(t) 281 defer ledgermgmt.CleanupTestEnv() 282 defer l.Close() 283 284 ccID := "notext" 285 286 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 287 288 tx := getEnv(ccID, createRWset(t, ccID), t) 289 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 290 291 err := v.Validate(b) 292 assert.NoError(t, err) 293 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 294 } 295 296 func TestInvokeNOKInvokesEmptyCCName(t *testing.T) { 297 l, v := setupLedgerAndValidator(t) 298 defer ledgermgmt.CleanupTestEnv() 299 defer l.Close() 300 301 ccID := "" 302 303 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 304 305 tx := getEnv(ccID, createRWset(t, ccID), t) 306 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 307 308 err := v.Validate(b) 309 assert.NoError(t, err) 310 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 311 } 312 313 func TestInvokeNOKExpiredCC(t *testing.T) { 314 l, v := setupLedgerAndValidator(t) 315 defer ledgermgmt.CleanupTestEnv() 316 defer l.Close() 317 318 ccID := "mycc" 319 320 putCCInfoWithVSCCAndVer(l, ccID, "vscc", "badversion", signedByAnyMember([]string{"DEFAULT"}), t) 321 322 tx := getEnv(ccID, createRWset(t, ccID), t) 323 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 324 325 err := v.Validate(b) 326 assert.NoError(t, err) 327 assertInvalid(b, t, peer.TxValidationCode_EXPIRED_CHAINCODE) 328 } 329 330 func TestInvokeNOKBogusActions(t *testing.T) { 331 l, v := setupLedgerAndValidator(t) 332 defer ledgermgmt.CleanupTestEnv() 333 defer l.Close() 334 335 ccID := "mycc" 336 337 putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t) 338 339 tx := getEnv(ccID, []byte("barf"), t) 340 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 341 342 err := v.Validate(b) 343 assert.NoError(t, err) 344 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 345 } 346 347 func TestInvokeNOKCCDoesntExist(t *testing.T) { 348 l, v := setupLedgerAndValidator(t) 349 defer ledgermgmt.CleanupTestEnv() 350 defer l.Close() 351 352 ccID := "mycc" 353 354 tx := getEnv(ccID, createRWset(t, ccID), t) 355 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 356 357 err := v.Validate(b) 358 assert.NoError(t, err) 359 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 360 } 361 362 func TestInvokeNOKVSCCUnspecified(t *testing.T) { 363 l, v := setupLedgerAndValidator(t) 364 defer ledgermgmt.CleanupTestEnv() 365 defer l.Close() 366 367 ccID := "mycc" 368 369 putCCInfoWithVSCCAndVer(l, ccID, "", ccVersion, signedByAnyMember([]string{"DEFAULT"}), t) 370 371 tx := getEnv(ccID, createRWset(t, ccID), t) 372 b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} 373 374 err := v.Validate(b) 375 assert.NoError(t, err) 376 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 377 } 378 379 func TestInvokeNoBlock(t *testing.T) { 380 l, v := setupLedgerAndValidator(t) 381 defer ledgermgmt.CleanupTestEnv() 382 defer l.Close() 383 384 err := v.Validate(&common.Block{Data: &common.BlockData{Data: [][]byte{}}}) 385 assert.NoError(t, err) 386 } 387 388 var signer msp.SigningIdentity 389 var signerSerialized []byte 390 391 func TestMain(m *testing.M) { 392 sysccprovider.RegisterSystemChaincodeProviderFactory(&scc.MocksccProviderFactory{}) 393 ccp.RegisterChaincodeProviderFactory(&ccprovider.MockCcProviderFactory{}) 394 395 msptesttools.LoadMSPSetupForTesting() 396 397 var err error 398 signer, err = mgmt.GetLocalMSP().GetDefaultSigningIdentity() 399 if err != nil { 400 fmt.Println("Could not get signer") 401 os.Exit(-1) 402 return 403 } 404 405 signerSerialized, err = signer.Serialize() 406 if err != nil { 407 fmt.Println("Could not serialize identity") 408 os.Exit(-1) 409 return 410 } 411 412 os.Exit(m.Run()) 413 }