|
8 | 8 | #include <random.h> |
9 | 9 | #include <streams.h> |
10 | 10 | #include <util/irange.h> |
| 11 | +#include <util/strencodings.h> |
11 | 12 |
|
12 | 13 | #include <boost/test/unit_test.hpp> |
13 | 14 |
|
@@ -472,4 +473,124 @@ BOOST_AUTO_TEST_CASE(bls_threshold_signature_tests) |
472 | 473 | FuncThresholdSignature(false); |
473 | 474 | } |
474 | 475 |
|
| 476 | +// A dummy BLS object that satisfies the minimal interface expected by CBLSLazyWrapper. |
| 477 | +class DummyBLS |
| 478 | +{ |
| 479 | +public: |
| 480 | + // Define a fixed serialization size (for testing purposes). |
| 481 | + static const size_t SerSize = 4; |
| 482 | + std::array<uint8_t, SerSize> data{}; |
| 483 | + |
| 484 | + DummyBLS() { data.fill(0); } |
| 485 | + |
| 486 | + // A dummy validity check: valid if any byte is non-zero. |
| 487 | + bool IsValid() const |
| 488 | + { |
| 489 | + return std::any_of(data.begin(), data.end(), [](uint8_t c) { return c != 0; }); |
| 490 | + } |
| 491 | + |
| 492 | + // Convert to bytes; ignore the legacy flag for simplicity. |
| 493 | + std::array<uint8_t, SerSize> ToBytes(bool /*legacy*/) const { return data; } |
| 494 | + |
| 495 | + // Set from bytes; again, ignore the legacy flag. |
| 496 | + void SetBytes(const std::array<uint8_t, SerSize>& bytes, bool /*legacy*/) { data = bytes; } |
| 497 | + |
| 498 | + // A dummy malleability check: simply compares the stored data to the given bytes. |
| 499 | + bool CheckMalleable(const std::array<uint8_t, SerSize>& bytes, bool /*legacy*/) const { return data == bytes; } |
| 500 | + |
| 501 | + // Reset the object to an "empty" state. |
| 502 | + void Reset() { data.fill(0); } |
| 503 | + |
| 504 | + // Produce a string representation. |
| 505 | + std::string ToString(bool /*legacy*/) const { return HexStr(data); } |
| 506 | + |
| 507 | + // Equality operator. |
| 508 | + bool operator==(const DummyBLS& other) const { return data == other.data; } |
| 509 | +}; |
| 510 | + |
| 511 | +// Define a type alias for our lazy wrapper instantiated with DummyBLS. |
| 512 | +using LazyDummyBLS = CBLSLazyWrapper<DummyBLS>; |
| 513 | + |
| 514 | +// Test 1: Two default (unset) wrappers should compare equal. |
| 515 | +BOOST_AUTO_TEST_CASE(test_default_equality) |
| 516 | +{ |
| 517 | + LazyDummyBLS lazy1; |
| 518 | + LazyDummyBLS lazy2; |
| 519 | + // Neither instance has been set, so they represent the default/null object. |
| 520 | + BOOST_CHECK(lazy1 == lazy2); |
| 521 | +} |
| 522 | + |
| 523 | +// Test 2: A default wrapper and one initialized with a nonzero DummyBLS should compare unequal. |
| 524 | +BOOST_AUTO_TEST_CASE(test_non_default_vs_default) |
| 525 | +{ |
| 526 | + LazyDummyBLS lazy_default; |
| 527 | + LazyDummyBLS lazy_set; |
| 528 | + DummyBLS obj; |
| 529 | + obj.data = {1, 0, 0, 0}; // nonzero data makes the object valid |
| 530 | + lazy_set.Set(obj, false); |
| 531 | + BOOST_CHECK(!(lazy_default == lazy_set)); |
| 532 | + BOOST_CHECK(lazy_default != lazy_set); |
| 533 | +} |
| 534 | + |
| 535 | +// Test 2: A default wrapper and one initialized with a nonzero DummyBLS should compare unequal. |
| 536 | +BOOST_AUTO_TEST_CASE(test_non_default_vs_different) |
| 537 | +{ |
| 538 | + LazyDummyBLS lazy_a; |
| 539 | + LazyDummyBLS lazy_b; |
| 540 | + DummyBLS obj; |
| 541 | + obj.data = {1, 2, 3, 4}; // nonzero data makes the object valid |
| 542 | + lazy_a.Set(obj, false); |
| 543 | + obj.data = {2, 2, 3, 4}; // nonzero data makes the object valid |
| 544 | + lazy_b.Set(obj, false); |
| 545 | + BOOST_CHECK(lazy_a != lazy_b); |
| 546 | +} |
| 547 | + |
| 548 | +// Test 3: Two wrappers set with the same underlying DummyBLS value compare equal. |
| 549 | +BOOST_AUTO_TEST_CASE(test_equality_same_value) |
| 550 | +{ |
| 551 | + LazyDummyBLS lazy1; |
| 552 | + LazyDummyBLS lazy2; |
| 553 | + BOOST_CHECK(lazy1 == lazy2); |
| 554 | + DummyBLS obj; |
| 555 | + obj.data = {5, 6, 7, 8}; |
| 556 | + lazy1.Set(obj, false); |
| 557 | + BOOST_CHECK(lazy1 != lazy2); |
| 558 | + lazy2.Set(obj, false); |
| 559 | + BOOST_CHECK(lazy1 == lazy2); |
| 560 | +} |
| 561 | + |
| 562 | +// Test 4: Serialization and unserialization preserve the wrapped value. |
| 563 | +BOOST_AUTO_TEST_CASE(test_serialization_unserialization) |
| 564 | +{ |
| 565 | + LazyDummyBLS lazy1; |
| 566 | + DummyBLS obj; |
| 567 | + obj.data = {9, 10, 11, 12}; |
| 568 | + // Set with a specific legacy flag (true in this case) |
| 569 | + lazy1.Set(obj, true); |
| 570 | + |
| 571 | + // Serialize the lazy object into a data stream. |
| 572 | + CDataStream ds(SER_DISK, CLIENT_VERSION); |
| 573 | + lazy1.Serialize(ds, true); |
| 574 | + |
| 575 | + // Create a new instance and unserialize the data into it. |
| 576 | + LazyDummyBLS lazy2; |
| 577 | + lazy2.Unserialize(ds, true); |
| 578 | + BOOST_CHECK(lazy1 == lazy2); |
| 579 | + BOOST_CHECK(lazy2.Get() == obj); |
| 580 | +} |
| 581 | + |
| 582 | +// Test 5: Two wrappers wrapping the same object should have the same hash. |
| 583 | +BOOST_AUTO_TEST_CASE(test_get_hash_consistency) |
| 584 | +{ |
| 585 | + LazyDummyBLS lazy1; |
| 586 | + LazyDummyBLS lazy2; |
| 587 | + DummyBLS obj; |
| 588 | + obj.data = {13, 14, 15, 16}; |
| 589 | + lazy1.Set(obj, false); |
| 590 | + lazy2.Set(obj, false); |
| 591 | + uint256 hash1 = lazy1.GetHash(); |
| 592 | + uint256 hash2 = lazy2.GetHash(); |
| 593 | + BOOST_CHECK(hash1 == hash2); |
| 594 | +} |
| 595 | + |
475 | 596 | BOOST_AUTO_TEST_SUITE_END() |
0 commit comments