github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/lib/server/idemix/revocationauthority_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package idemix_test 8 9 import ( 10 "bytes" 11 "io/ioutil" 12 "os" 13 "path" 14 "testing" 15 16 "github.com/hxx258456/ccgo/sm2" 17 "github.com/hxx258456/fabric-ca-gm/internal/pkg/util" 18 . "github.com/hxx258456/fabric-ca-gm/lib/server/idemix" 19 "github.com/hxx258456/fabric-ca-gm/lib/server/idemix/mocks" 20 dmocks "github.com/hxx258456/fabric-ca-gm/lib/server/idemix/mocks" 21 "github.com/hxx258456/fabric-gm/idemix" 22 fp256bn "github.com/hyperledger/fabric-amcl/amcl/FP256BN" 23 "github.com/pkg/errors" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestLongTermKeyError(t *testing.T) { 28 issuer := new(mocks.MyIssuer) 29 issuer.On("Name").Return("") 30 issuer.On("HomeDir").Return(".") 31 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(".", DefaultRevocationPublicKeyFile), 32 RevocationPrivateKeyfile: path.Join("./msp/keystore", DefaultRevocationPrivateKeyFile)} 33 issuer.On("Config").Return(opts) 34 lib := new(mocks.Lib) 35 lib.On("GenerateLongTermRevocationKey").Return(nil, errors.New("Failed to create revocation key")) 36 issuer.On("IdemixLib").Return(lib) 37 db := new(dmocks.FabricCADB) 38 issuer.On("DB").Return(db) 39 _, err := NewRevocationAuthority(issuer, 1) 40 assert.Error(t, err) 41 if err != nil { 42 assert.Contains(t, err.Error(), "Failed to generate revocation key for issuer") 43 } 44 } 45 func TestRevocationKeyLoadError(t *testing.T) { 46 homeDir, err := ioutil.TempDir(".", "revokekeyloaderrortest") 47 if err != nil { 48 t.Fatalf("Failed to create temp directory: %s", err.Error()) 49 } 50 defer os.RemoveAll(homeDir) 51 err = os.MkdirAll(path.Join(homeDir, "msp/keystore"), 0777) 52 if err != nil { 53 t.Fatalf("Failed to create directory: %s", err.Error()) 54 } 55 revocationpubkeyfile := path.Join(homeDir, DefaultRevocationPublicKeyFile) 56 revocationprivkeyfile := path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile) 57 err = util.WriteFile(revocationprivkeyfile, []byte(""), 0666) 58 if err != nil { 59 t.Fatalf("Failed to write to file: %s", err.Error()) 60 } 61 err = util.WriteFile(revocationpubkeyfile, []byte(""), 0666) 62 if err != nil { 63 t.Fatalf("Failed to write to file: %s", err.Error()) 64 } 65 issuer := new(mocks.MyIssuer) 66 issuer.On("Name").Return("") 67 issuer.On("HomeDir").Return(homeDir) 68 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: revocationpubkeyfile, 69 RevocationPrivateKeyfile: revocationprivkeyfile} 70 issuer.On("Config").Return(opts) 71 lib := new(mocks.Lib) 72 issuer.On("IdemixLib").Return(lib) 73 db := new(dmocks.FabricCADB) 74 issuer.On("DB").Return(db) 75 _, err = NewRevocationAuthority(issuer, 1) 76 assert.Error(t, err) 77 if err != nil { 78 assert.Contains(t, err.Error(), "Failed to load revocation key for issuer") 79 } 80 } 81 82 func TestGetRAInfoFromDBError(t *testing.T) { 83 homeDir, err := ioutil.TempDir(".", "rainfodberrortest") 84 if err != nil { 85 t.Fatalf("Failed to create temp directory: %s", err.Error()) 86 } 87 defer os.RemoveAll(homeDir) 88 err = os.MkdirAll(path.Join(homeDir, "msp/keystore"), 0777) 89 if err != nil { 90 t.Fatalf("Failed to create directory: %s", err.Error()) 91 } 92 issuer := new(mocks.MyIssuer) 93 issuer.On("Name").Return("ca1") 94 lib := new(mocks.Lib) 95 revocationKey, err := idemix.GenerateLongTermRevocationKey() 96 if err != nil { 97 t.Fatalf("Failed to generate test revocation key: %s", err.Error()) 98 } 99 lib.On("GenerateLongTermRevocationKey").Return(revocationKey, nil) 100 issuer.On("IdemixLib").Return(lib) 101 rainfos := []RevocationAuthorityInfo{} 102 db := new(dmocks.FabricCADB) 103 db.On("Select", "GetRAInfo", &rainfos, "SELECT * FROM revocation_authority_info"). 104 Return(errors.New("Failed to execute select query")) 105 issuer.On("DB").Return(db) 106 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 107 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 108 issuer.On("Config").Return(opts) 109 _, err = NewRevocationAuthority(issuer, 1) 110 assert.Error(t, err) 111 } 112 113 func TestGetRAInfoFromNewDBSelectError(t *testing.T) { 114 homeDir, err := ioutil.TempDir(".", "rainfodberrortest") 115 if err != nil { 116 t.Fatalf("Failed to create temp directory: %s", err.Error()) 117 } 118 defer os.RemoveAll(homeDir) 119 err = os.MkdirAll(path.Join(homeDir, "msp/keystore"), 0777) 120 if err != nil { 121 t.Fatalf("Failed to create directory: %s", err.Error()) 122 } 123 issuer := new(mocks.MyIssuer) 124 issuer.On("Name").Return("") 125 issuer.On("HomeDir").Return(homeDir) 126 lib := new(mocks.Lib) 127 revocationKey, err := idemix.GenerateLongTermRevocationKey() 128 if err != nil { 129 t.Fatalf("Failed to generate test revocation key: %s", err.Error()) 130 } 131 lib.On("GenerateLongTermRevocationKey").Return(revocationKey, nil) 132 issuer.On("IdemixLib").Return(lib) 133 db := new(dmocks.FabricCADB) 134 raInfos := []RevocationAuthorityInfo{} 135 f := getSelectFunc(t, true, true) 136 db.On("Select", "GetRAInfo", &raInfos, SelectRAInfo).Return(f) 137 issuer.On("DB").Return(db) 138 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 139 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 140 issuer.On("Config").Return(opts) 141 _, err = NewRevocationAuthority(issuer, 1) 142 assert.Error(t, err) 143 } 144 145 func TestGetRAInfoFromExistingDB(t *testing.T) { 146 homeDir, err := ioutil.TempDir(".", "newraexistingdbtest") 147 if err != nil { 148 t.Fatalf("Failed to create temp directory: %s", err.Error()) 149 } 150 defer os.RemoveAll(homeDir) 151 err = os.MkdirAll(path.Join(homeDir, "msp/keystore"), 0777) 152 if err != nil { 153 t.Fatalf("Failed to create directory: %s", err.Error()) 154 } 155 issuer := new(mocks.MyIssuer) 156 issuer.On("Name").Return("") 157 issuer.On("HomeDir").Return(homeDir) 158 lib := new(mocks.Lib) 159 revocationKey, err := idemix.GenerateLongTermRevocationKey() 160 if err != nil { 161 t.Fatalf("Failed to generate test revocation key: %s", err.Error()) 162 } 163 issuer.On("IdemixLib").Return(lib) 164 rk := NewRevocationKey(path.Join(homeDir, DefaultRevocationPublicKeyFile), 165 path.Join(homeDir, "msp/keystore/", DefaultRevocationPrivateKeyFile), lib) 166 rk.SetKey(revocationKey) 167 err = rk.Store() 168 if err != nil { 169 t.Fatalf("Failed to store test revocation key: %s", err.Error()) 170 } 171 db := new(dmocks.FabricCADB) 172 raInfos := []RevocationAuthorityInfo{} 173 f := getSelectFunc(t, false, false) 174 db.On("Select", "GetRAInfo", &raInfos, SelectRAInfo).Return(f) 175 issuer.On("DB").Return(db) 176 opts := &Config{RHPoolSize: 100, 177 RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 178 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 179 issuer.On("Config").Return(opts) 180 _, err = NewRevocationAuthority(issuer, 1) 181 assert.NoError(t, err) 182 } 183 184 func TestRevocationKeyStoreFailure(t *testing.T) { 185 homeDir, err := ioutil.TempDir(".", "rkstoretesthome") 186 if err != nil { 187 t.Fatalf("Failed to create temp directory: %s", err.Error()) 188 } 189 defer os.RemoveAll(homeDir) 190 issuer, db, _ := setupForInsertTests(t, homeDir) 191 os.RemoveAll(path.Join(homeDir, "msp/keystore")) 192 rainfo := RevocationAuthorityInfo{ 193 Epoch: 1, 194 NextRevocationHandle: 1, 195 LastHandleInPool: 100, 196 Level: 1, 197 } 198 result := new(dmocks.Result) 199 result.On("RowsAffected").Return(int64(1), nil) 200 db.On("NamedExec", InsertRAInfo, &rainfo).Return(result, nil) 201 issuer.On("DB").Return(db) 202 keystoreDir := path.Join(homeDir, "msp/keystore") 203 err = os.MkdirAll(keystoreDir, 4444) 204 if err != nil { 205 t.Fatalf("Failed to create read only directory: %s", err.Error()) 206 } 207 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 208 RevocationPrivateKeyfile: path.Join(keystoreDir, DefaultRevocationPrivateKeyFile)} 209 issuer.On("Config").Return(opts) 210 _, err = NewRevocationAuthority(issuer, 1) 211 assert.Error(t, err) 212 if err != nil { 213 assert.Contains(t, err.Error(), "Failed to store revocation key of issuer") 214 } 215 } 216 217 func TestGetRAInfoFromNewDBInsertFailure(t *testing.T) { 218 homeDir, err := ioutil.TempDir(".", "rainfoinserttest") 219 if err != nil { 220 t.Fatalf("Failed to create temp directory: %s", err.Error()) 221 } 222 defer os.RemoveAll(homeDir) 223 issuer, db, _ := setupForInsertTests(t, homeDir) 224 rainfo := RevocationAuthorityInfo{ 225 Epoch: 1, 226 NextRevocationHandle: 1, 227 LastHandleInPool: 100, 228 Level: 1, 229 } 230 result := new(dmocks.Result) 231 result.On("RowsAffected").Return(int64(0), nil) 232 db.On("NamedExec", "AddRAInfo", InsertRAInfo, &rainfo).Return(result, nil) 233 issuer.On("DB").Return(db) 234 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 235 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 236 issuer.On("Config").Return(opts) 237 _, err = NewRevocationAuthority(issuer, 1) 238 assert.Error(t, err) 239 if err != nil { 240 assert.Contains(t, err.Error(), "Failed to insert the revocation authority info record; no rows affected") 241 } 242 } 243 244 func TestGetRAInfoFromNewDBInsertFailure1(t *testing.T) { 245 homeDir, err := ioutil.TempDir(".", "rainfoinserttest") 246 if err != nil { 247 t.Fatalf("Failed to create temp directory: %s", err.Error()) 248 } 249 err = os.MkdirAll(path.Join(homeDir, "msp/keystore"), 0777) 250 if err != nil { 251 t.Fatalf("Failed to create directory: %s", err.Error()) 252 } 253 defer os.RemoveAll(homeDir) 254 issuer, db, _ := setupForInsertTests(t, homeDir) 255 rainfo := RevocationAuthorityInfo{ 256 Epoch: 1, 257 NextRevocationHandle: 1, 258 LastHandleInPool: 100, 259 Level: 1, 260 } 261 result := new(dmocks.Result) 262 result.On("RowsAffected").Return(int64(2), nil) 263 db.On("NamedExec", "AddRAInfo", InsertRAInfo, &rainfo).Return(result, nil) 264 issuer.On("DB").Return(db) 265 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 266 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 267 issuer.On("Config").Return(opts) 268 _, err = NewRevocationAuthority(issuer, 1) 269 assert.Error(t, err) 270 if err != nil { 271 assert.Contains(t, err.Error(), "Expected to affect 1 entry in revocation authority info table but affected") 272 } 273 } 274 275 func TestGetRAInfoFromNewDBInsertError(t *testing.T) { 276 homeDir, err := ioutil.TempDir(".", "rainfoinserttest") 277 if err != nil { 278 t.Fatalf("Failed to create temp directory: %s", err.Error()) 279 } 280 defer os.RemoveAll(homeDir) 281 issuer, db, _ := setupForInsertTests(t, homeDir) 282 rainfo := RevocationAuthorityInfo{ 283 Epoch: 1, 284 NextRevocationHandle: 1, 285 LastHandleInPool: 100, 286 Level: 1, 287 } 288 db.On("NamedExec", "AddRAInfo", InsertRAInfo, &rainfo).Return(nil, 289 errors.New("Inserting revocation authority info into DB failed")) 290 issuer.On("DB").Return(db) 291 opts := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 292 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 293 issuer.On("Config").Return(opts) 294 _, err = NewRevocationAuthority(issuer, 1) 295 assert.Error(t, err) 296 if err != nil { 297 assert.Contains(t, err.Error(), "Failed to insert revocation authority info into database") 298 } 299 } 300 301 func TestGetNewRevocationHandleSelectError(t *testing.T) { 302 homeDir, err := ioutil.TempDir(".", "selecterrortest") 303 if err != nil { 304 t.Fatalf("Failed to create temp directory: %s", err.Error()) 305 } 306 defer os.RemoveAll(homeDir) 307 db := new(dmocks.FabricCADB) 308 selectFnc := getSelectFunc(t, true, false) 309 ra := getRevocationAuthority(t, "GetNextRevocationHandle", homeDir, db, nil, 0, false, false, selectFnc) 310 311 tx := new(dmocks.FabricCATx) 312 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 313 tx.On("Rollback", "GetNextRevocationHandle").Return(nil) 314 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 315 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 316 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, nil) 317 rcInfos := []RevocationAuthorityInfo{} 318 fnc := getTxSelectFunc(t, &rcInfos, 1, true, true) 319 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(fnc) 320 tx.On("Select", "GetNextRevocationHandle", &rcInfos, SelectRAInfo).Return(fnc) 321 322 db.On("BeginTx").Return(tx) 323 _, err = ra.GetNewRevocationHandle() 324 assert.Error(t, err) 325 if err != nil { 326 assert.Contains(t, err.Error(), "Failed to get revocation authority info from database") 327 } 328 } 329 330 func TestGetNewRevocationHandleNoData(t *testing.T) { 331 homeDir, err := ioutil.TempDir(".", "rhnodatatest") 332 if err != nil { 333 t.Fatalf("Failed to create temp directory: %s", err.Error()) 334 } 335 defer os.RemoveAll(homeDir) 336 db := new(dmocks.FabricCADB) 337 selectFnc := getSelectFunc(t, true, false) 338 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 339 340 tx := new(dmocks.FabricCATx) 341 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 342 tx.On("Rollback", "GetNextRevocationHandle").Return(nil) 343 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 344 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 345 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, nil) 346 rcInfos := []RevocationAuthorityInfo{} 347 fnc := getTxSelectFunc(t, &rcInfos, 1, false, false) 348 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(fnc) 349 350 db.On("BeginTx").Return(tx) 351 _, err = ra.GetNewRevocationHandle() 352 assert.Error(t, err) 353 if err != nil { 354 assert.Contains(t, err.Error(), "No revocation authority info found in database") 355 } 356 } 357 358 func TestGetNewRevocationHandleExecError(t *testing.T) { 359 homeDir, err := ioutil.TempDir(".", "nextrhexecerrortest") 360 if err != nil { 361 t.Fatalf("Failed to create temp directory: %s", err.Error()) 362 } 363 defer os.RemoveAll(homeDir) 364 db := new(dmocks.FabricCADB) 365 selectFnc := getSelectFunc(t, true, false) 366 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 367 368 tx := new(dmocks.FabricCATx) 369 rcInfos := []RevocationAuthorityInfo{} 370 fnc := getTxSelectFunc(t, &rcInfos, 1, false, true) 371 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(fnc) 372 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 373 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 374 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, errors.New("Exec error")) 375 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 376 tx.On("Rollback", "GetNextRevocationHandle").Return(nil) 377 378 db.On("BeginTx").Return(tx) 379 _, err = ra.GetNewRevocationHandle() 380 assert.Error(t, err) 381 if err != nil { 382 assert.Contains(t, err.Error(), "Failed to update revocation authority info") 383 } 384 } 385 386 func TestGetNewRevocationHandleRollbackError(t *testing.T) { 387 homeDir, err := ioutil.TempDir(".", "nextrhrollbackerrortest") 388 if err != nil { 389 t.Fatalf("Failed to create temp directory: %s", err.Error()) 390 } 391 defer os.RemoveAll(homeDir) 392 db := new(dmocks.FabricCADB) 393 selectFnc := getSelectFunc(t, true, false) 394 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 395 396 tx := new(dmocks.FabricCATx) 397 rcInfos := []RevocationAuthorityInfo{} 398 fnc := getTxSelectFunc(t, &rcInfos, 1, false, true) 399 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(fnc) 400 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 401 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 402 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, errors.New("Exec error")) 403 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 404 tx.On("Rollback", "GetNextRevocationHandle").Return(errors.New("Rollback error")) 405 406 db.On("BeginTx").Return(tx) 407 _, err = ra.GetNewRevocationHandle() 408 assert.Error(t, err) 409 if err != nil { 410 assert.Contains(t, err.Error(), "Error encountered while rolling back transaction") 411 } 412 } 413 414 func TestGetNewRevocationHandleCommitError(t *testing.T) { 415 homeDir, err := ioutil.TempDir(".", "nextrhcommiterrortest") 416 if err != nil { 417 t.Fatalf("Failed to create temp directory: %s", err.Error()) 418 } 419 defer os.RemoveAll(homeDir) 420 db := new(dmocks.FabricCADB) 421 selectFnc := getSelectFunc(t, true, false) 422 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 423 424 tx := new(dmocks.FabricCATx) 425 tx.On("Commit", "GetNextRevocationHandle").Return(errors.New("Error commiting")) 426 tx.On("Rollback").Return(nil) 427 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 428 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 429 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, nil) 430 rcInfos := []RevocationAuthorityInfo{} 431 f1 := getTxSelectFunc(t, &rcInfos, 1, false, true) 432 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(f1) 433 434 db.On("BeginTx").Return(tx) 435 _, err = ra.GetNewRevocationHandle() 436 assert.Error(t, err) 437 assert.Contains(t, err.Error(), "Error encountered while committing transaction") 438 } 439 440 func TestGetNewRevocationHandle(t *testing.T) { 441 homeDir, err := ioutil.TempDir(".", "nextrhtest") 442 if err != nil { 443 t.Fatalf("Failed to create temp directory: %s", err.Error()) 444 } 445 defer os.RemoveAll(homeDir) 446 db := new(dmocks.FabricCADB) 447 selectFnc := getSelectFunc(t, true, false) 448 rc := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 449 450 tx := new(dmocks.FabricCATx) 451 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 452 tx.On("Rollback", "GetNextRevocationHandle").Return(nil) 453 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 454 tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle) 455 tx.On("Exec", "GetNextRevocationHandle", UpdateNextHandle, 2, 1).Return(nil, nil) 456 rcInfos := []RevocationAuthorityInfo{} 457 f1 := getTxSelectFunc(t, &rcInfos, 1, false, true) 458 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(f1) 459 460 db.On("BeginTx").Return(tx) 461 rh, err := rc.GetNewRevocationHandle() 462 assert.NoError(t, err) 463 assert.Equal(t, 0, bytes.Compare(idemix.BigToBytes(fp256bn.NewBIGint(1)), idemix.BigToBytes(rh)), "Expected next revocation handle to be 1") 464 } 465 466 func TestGetNewRevocationHandleLastHandle(t *testing.T) { 467 homeDir, err := ioutil.TempDir(".", "nextlastrhtest") 468 if err != nil { 469 t.Fatalf("Failed to create temp directory: %s", err.Error()) 470 } 471 defer os.RemoveAll(homeDir) 472 db := new(dmocks.FabricCADB) 473 selectFnc := getSelectFunc(t, true, false) 474 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 475 476 tx := new(dmocks.FabricCATx) 477 tx.On("Commit", "GetNextRevocationHandle").Return(nil) 478 tx.On("Rollback", "GetNextRevocationHandle").Return(nil) 479 tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo) 480 tx.On("Rebind", UpdateNextAndLastHandle).Return(UpdateNextAndLastHandle) 481 tx.On("Exec", "GetNextRevocationHandle", UpdateNextAndLastHandle, 101, 200, 2, 1).Return(nil, nil) 482 rcInfos := []RevocationAuthorityInfo{} 483 f1 := getTxSelectFunc(t, &rcInfos, 100, false, true) 484 tx.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(f1) 485 486 db.On("BeginTx").Return(tx) 487 rh, err := ra.GetNewRevocationHandle() 488 assert.NoError(t, err) 489 assert.Equal(t, 0, bytes.Compare(idemix.BigToBytes(fp256bn.NewBIGint(100)), idemix.BigToBytes(rh)), 490 "Expected next revocation handle to be 100") 491 assert.Equal(t, util.B64Encode(idemix.BigToBytes(fp256bn.NewBIGint(100))), util.B64Encode(idemix.BigToBytes(rh)), 492 "Expected next revocation handle to be 100") 493 } 494 495 func TestGetEpoch(t *testing.T) { 496 homeDir, err := ioutil.TempDir(".", "getepochtest") 497 if err != nil { 498 t.Fatalf("Failed to create temp directory: %s", err.Error()) 499 } 500 defer os.RemoveAll(homeDir) 501 db := new(dmocks.FabricCADB) 502 selectFnc := getSelectFunc(t, true, false) 503 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, nil, 0, false, false, selectFnc) 504 505 rcInfos := []RevocationAuthorityInfo{} 506 db.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(selectFnc) 507 epoch, err := ra.Epoch() 508 assert.NoError(t, err) 509 assert.Equal(t, 1, epoch) 510 key := ra.PublicKey() 511 assert.NotNil(t, key, "Public key should not be nil") 512 } 513 514 func TestGetEpochRAInfoError(t *testing.T) { 515 homeDir, err := ioutil.TempDir(".", "createcritest") 516 if err != nil { 517 t.Fatalf("Failed to create temp directory: %s", err.Error()) 518 } 519 defer os.RemoveAll(homeDir) 520 db := new(dmocks.FabricCADB) 521 522 revocationKey, err := idemix.GenerateLongTermRevocationKey() 523 if err != nil { 524 t.Fatalf("Failed to generate ECDSA key for revocation authority") 525 } 526 selectFnc := getSelectFuncForCreateCRI(t, true, true) 527 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, revocationKey, 0, false, false, selectFnc) 528 _, err = ra.Epoch() 529 assert.Error(t, err, "Epoch should fail if there is an error getting revocation info from DB") 530 } 531 532 func TestCreateCRIGetRAInfoError(t *testing.T) { 533 homeDir, err := ioutil.TempDir(".", "createcritest") 534 if err != nil { 535 t.Fatalf("Failed to create temp directory: %s", err.Error()) 536 } 537 defer os.RemoveAll(homeDir) 538 db := new(dmocks.FabricCADB) 539 540 revocationKey, err := idemix.GenerateLongTermRevocationKey() 541 if err != nil { 542 t.Fatalf("Failed to generate ECDSA key for revocation authority") 543 } 544 selectFnc := getSelectFuncForCreateCRI(t, true, true) 545 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, revocationKey, 0, false, false, selectFnc) 546 _, err = ra.CreateCRI() 547 assert.Error(t, err, "CreateCRI should fail if there is an error getting revocation info from DB") 548 } 549 550 func TestCreateCRIGetRevokeCredsError(t *testing.T) { 551 homeDir, err := ioutil.TempDir(".", "createcritest") 552 if err != nil { 553 t.Fatalf("Failed to create temp directory: %s", err.Error()) 554 } 555 defer os.RemoveAll(homeDir) 556 db := new(dmocks.FabricCADB) 557 558 revocationKey, err := idemix.GenerateLongTermRevocationKey() 559 if err != nil { 560 t.Fatalf("Failed to generate ECDSA key for revocation authority") 561 } 562 563 selectFnc := getSelectFuncForCreateCRI(t, true, false) 564 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, revocationKey, 0, true, false, selectFnc) 565 _, err = ra.CreateCRI() 566 assert.Error(t, err, "CreateCRI should fail if there is an error getting revoked credentials") 567 } 568 569 func TestIdemixCreateCRIError(t *testing.T) { 570 homeDir, err := ioutil.TempDir(".", "createcritest") 571 if err != nil { 572 t.Fatalf("Failed to create temp directory: %s", err.Error()) 573 } 574 defer os.RemoveAll(homeDir) 575 576 revocationKey, err := idemix.GenerateLongTermRevocationKey() 577 if err != nil { 578 t.Fatalf("Failed to generate ECDSA key for revocation authority") 579 } 580 581 db := new(dmocks.FabricCADB) 582 selectFnc := getSelectFuncForCreateCRI(t, true, false) 583 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, revocationKey, 0, false, true, selectFnc) 584 _, err = ra.CreateCRI() 585 assert.Error(t, err, "CreateCRI should fail if idemix.CreateCRI returns an error") 586 } 587 588 func TestEpochValuesInCRI(t *testing.T) { 589 homeDir, err := ioutil.TempDir(".", "createcritest") 590 if err != nil { 591 t.Fatalf("Failed to create temp directory: %s", err.Error()) 592 } 593 defer os.RemoveAll(homeDir) 594 revocationKey, err := idemix.GenerateLongTermRevocationKey() 595 if err != nil { 596 t.Fatalf("Failed to generate ECDSA key for revocation authority") 597 } 598 selectFnc := getSelectFuncForCreateCRI(t, true, false) 599 db := new(dmocks.FabricCADB) 600 ra := getRevocationAuthority(t, "GetRAInfo", homeDir, db, revocationKey, 0, false, false, selectFnc) 601 cri, err := ra.CreateCRI() 602 assert.NoError(t, err) 603 604 cri1, err := ra.CreateCRI() 605 assert.NoError(t, err) 606 if err == nil { 607 assert.Equal(t, cri.Epoch, cri1.Epoch) 608 } 609 } 610 611 func setupForInsertTests(t *testing.T, homeDir string) (*mocks.MyIssuer, *dmocks.FabricCADB, *sm2.PrivateKey) { 612 issuer := new(mocks.MyIssuer) 613 issuer.On("Name").Return("") 614 issuer.On("HomeDir").Return(homeDir) 615 keystore := path.Join(homeDir, "msp/keystore") 616 err := os.MkdirAll(keystore, 0777) 617 if err != nil { 618 t.Fatalf("Failed to create directory %s: %s", keystore, err.Error()) 619 } 620 lib := new(mocks.Lib) 621 privateKey, err := idemix.GenerateLongTermRevocationKey() 622 if err != nil { 623 t.Fatalf("Failed to generate ECDSA key for revocation authority") 624 } 625 lib.On("GenerateLongTermRevocationKey").Return(privateKey, nil) 626 issuer.On("IdemixLib").Return(lib) 627 db := new(dmocks.FabricCADB) 628 rcInfos := []RevocationAuthorityInfo{} 629 f := getSelectFunc(t, true, false) 630 db.On("Select", "GetRAInfo", &rcInfos, SelectRAInfo).Return(f) 631 return issuer, db, privateKey 632 } 633 634 func getRevocationAuthority(t *testing.T, funcName, homeDir string, db *dmocks.FabricCADB, revocationKey *sm2.PrivateKey, revokedCred int, 635 getRevokedCredsError bool, idemixCreateCRIError bool, selectFnc func(string, interface{}, string, ...interface{}) error) RevocationAuthority { 636 issuer := new(mocks.MyIssuer) 637 issuer.On("Name").Return("ca1") 638 issuer.On("HomeDir").Return(homeDir) 639 keystore := path.Join(homeDir, "msp/keystore") 640 err := os.MkdirAll(keystore, 0777) 641 if err != nil { 642 t.Fatalf("Failed to create directory %s: %s", keystore, err.Error()) 643 } 644 645 if revocationKey == nil { 646 var err error 647 revocationKey, err = idemix.GenerateLongTermRevocationKey() 648 if err != nil { 649 t.Fatalf("Failed to generate ECDSA key for revocation authority") 650 } 651 } 652 lib := new(mocks.Lib) 653 lib.On("GenerateLongTermRevocationKey").Return(revocationKey, nil) 654 issuer.On("IdemixLib").Return(lib) 655 656 rcInfosForSelect := []RevocationAuthorityInfo{} 657 db.On("Select", "GetRAInfo", &rcInfosForSelect, SelectRAInfo).Return(selectFnc) 658 rcinfo := RevocationAuthorityInfo{ 659 Epoch: 1, 660 NextRevocationHandle: 1, 661 LastHandleInPool: 100, 662 Level: 1, 663 } 664 result := new(dmocks.Result) 665 result.On("RowsAffected").Return(int64(1), nil) 666 db.On("NamedExec", "AddRAInfo", InsertRAInfo, &rcinfo).Return(result, nil) 667 issuer.On("DB").Return(db) 668 cfg := &Config{RHPoolSize: 100, RevocationPublicKeyfile: path.Join(homeDir, DefaultRevocationPublicKeyFile), 669 RevocationPrivateKeyfile: path.Join(homeDir, "msp/keystore", DefaultRevocationPrivateKeyFile)} 670 issuer.On("Config").Return(cfg) 671 672 rnd, err := idemix.GetRand() 673 if err != nil { 674 t.Fatalf("Failed generate random number: %s", err.Error()) 675 } 676 issuer.On("IdemixRand").Return(rnd) 677 678 credDBAccessor := new(mocks.CredDBAccessor) 679 if getRevokedCredsError { 680 credDBAccessor.On("GetRevokedCredentials").Return(nil, errors.New("Failed to get revoked credentials")) 681 } else { 682 revokedCreds := []CredRecord{} 683 if revokedCred > 0 { 684 rh := util.B64Encode(idemix.BigToBytes(fp256bn.NewBIGint(revokedCred))) 685 cr := CredRecord{ 686 RevocationHandle: rh, 687 Cred: "", 688 ID: "", 689 Status: "revoked", 690 } 691 revokedCreds = append(revokedCreds, cr) 692 } 693 credDBAccessor.On("GetRevokedCredentials").Return(revokedCreds, nil) 694 } 695 696 issuer.On("CredDBAccessor").Return(credDBAccessor) 697 698 validHandles := []*fp256bn.BIG{} 699 for i := 1; i <= 100; i = i + 1 { 700 validHandles = append(validHandles, fp256bn.NewBIGint(i)) 701 } 702 alg := idemix.ALG_NO_REVOCATION 703 if idemixCreateCRIError { 704 lib.On("CreateCRI", revocationKey, validHandles, 1, alg, rnd).Return(nil, errors.New("Idemix lib create CRI error")) 705 } else { 706 cri, err := idemix.CreateCRI(revocationKey, validHandles, 1, alg, rnd) 707 if err != nil { 708 t.Fatalf("Failed to create CRI: %s", err.Error()) 709 } 710 lib.On("CreateCRI", revocationKey, validHandles, 1, alg, rnd).Return(cri, nil) 711 } 712 713 ra, err := NewRevocationAuthority(issuer, 1) 714 if err != nil { 715 t.Fatalf("Failed to get revocation authority instance: %s", err.Error()) 716 } 717 return ra 718 } 719 720 func getSelectFunc(t *testing.T, newDB bool, isError bool) func(string, interface{}, string, ...interface{}) error { 721 numTimesCalled := 0 722 return func(funcName string, dest interface{}, query string, args ...interface{}) error { 723 rcInfos, _ := dest.(*[]RevocationAuthorityInfo) 724 rcInfo := RevocationAuthorityInfo{ 725 Epoch: 1, 726 NextRevocationHandle: 1, 727 LastHandleInPool: 100, 728 Level: 1, 729 } 730 if !newDB || numTimesCalled > 0 { 731 *rcInfos = append(*rcInfos, rcInfo) 732 } 733 if isError { 734 return errors.New("Failed to get RevocationComponentInfo from DB") 735 } 736 numTimesCalled = numTimesCalled + 1 737 return nil 738 } 739 } 740 741 func getSelectFuncForCreateCRI(t *testing.T, newDB bool, isError bool) func(string, interface{}, string, ...interface{}) error { 742 numTimesCalled := 0 743 return func(funcName string, dest interface{}, query string, args ...interface{}) error { 744 rcInfos, _ := dest.(*[]RevocationAuthorityInfo) 745 rcInfo := RevocationAuthorityInfo{ 746 Epoch: 1, 747 NextRevocationHandle: 1, 748 LastHandleInPool: 100, 749 Level: 1, 750 } 751 if !newDB || numTimesCalled > 0 { 752 *rcInfos = append(*rcInfos, rcInfo) 753 } 754 755 var err error 756 if isError && numTimesCalled%2 == 1 { 757 err = errors.New("Failed to get RevocationComponentInfo from DB") 758 } 759 numTimesCalled = numTimesCalled + 1 760 return err 761 } 762 } 763 764 func getTxSelectFunc(t *testing.T, rcs *[]RevocationAuthorityInfo, nextRH int, isError bool, isAppend bool) func(string, interface{}, string, ...interface{}) error { 765 return func(funcName string, dest interface{}, query string, args ...interface{}) error { 766 rcInfos := dest.(*[]RevocationAuthorityInfo) 767 rcInfo := RevocationAuthorityInfo{ 768 Epoch: 1, 769 NextRevocationHandle: nextRH, 770 LastHandleInPool: 100, 771 Level: 1, 772 } 773 if isAppend { 774 *rcInfos = append(*rcInfos, rcInfo) 775 *rcs = append(*rcs, rcInfo) 776 } 777 778 if isError { 779 return errors.New("Failed to get RevocationComponentInfo from DB") 780 } 781 return nil 782 } 783 }