Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <iostream>
  2. #include <vector>
  3. #include "shared.hpp"
  4. struct IP { uint8_t_32 a = {}; bool e = false; std::string desc = ""; };
  5. struct PA { uint8_t_32 a; uint8_t_32 b; uint8_t_32 e = Null<uint8_t_32>(); std::string except = ""; std::string desc = ""; };
  6. void generate (std::ostream& o) {
  7. ///////////////////////////////// isPrivate
  8. // edge cases (verify)
  9. // from https://github.com/bitcoin-core/secp256k1/blob/6ad5cdb42a1a8257289a0423d644dcbdeab0f83c/src/tests.c
  10. std::vector<IP> ip = {
  11. { ZERO, false, "== 0" }, // #L3145
  12. { ONE, true, "== 1" }, // #L3153
  13. { GROUP_ORDER_LESS_1, true, "== G - 1" }, // #L3171
  14. { GROUP_ORDER, false, "== G" }, // #L3115
  15. { GROUP_ORDER_OVER_1, false, "> G" }, // #L3162
  16. { UINT256_MAX, false, "2^256 - 1" }, // #L3131
  17. };
  18. // fuzz
  19. for (size_t i = 0; i < 1000; ++i) {
  20. ip.push_back({ randomPrivate(), true });
  21. }
  22. for (size_t i = 0; i < 1000; ++i) {
  23. const auto key = randomScalarHigh();
  24. const auto verified = secp256k1_ec_seckey_verify(ctx, key.data());
  25. ip.push_back({ key, verified });
  26. }
  27. ///////////////////////////////// privateAdd
  28. std::vector<PA> pa;
  29. // visually inspected
  30. // covers https://github.com/bitcoin-core/secp256k1/blob/6ad5cdb42a1a8257289a0423d644dcbdeab0f83c/src/tests.c
  31. pa.push_back({ ONE, ZERO, ONE, "", "1 + 0 == 1" });
  32. for (size_t i = 1; i < 5; ++i) pa.push_back({ ONE, scalarFromUInt32(i), scalarFromUInt32(1 + i) });
  33. for (size_t i = 1; i < 5; ++i) pa.push_back({ scalarFromUInt32(i), TWO, scalarFromUInt32(i + 2) });
  34. pa.push_back({ ONE, GROUP_ORDER_LESS_1, Null<uint8_t_32>(), "", "1 + -1 == 0" });
  35. pa.push_back({ ONE, GROUP_ORDER_LESS_2, GROUP_ORDER_LESS_1, "", "1 + -2 == -1" });
  36. pa.push_back({ ONE, GROUP_ORDER_LESS_3, GROUP_ORDER_LESS_2, "", "1 + -3 == -2" });
  37. pa.push_back({ GROUP_ORDER_LESS_1, GROUP_ORDER_LESS_1, GROUP_ORDER_LESS_2 });
  38. pa.push_back({ GROUP_ORDER_LESS_2, GROUP_ORDER_LESS_1, GROUP_ORDER_LESS_3 });
  39. pa.push_back({ GROUP_ORDER_LESS_3, ONE, GROUP_ORDER_LESS_2 });
  40. pa.push_back({ GROUP_ORDER_LESS_3, TWO, GROUP_ORDER_LESS_1, "", "-3 + 2 == -1" });
  41. pa.push_back({ GROUP_ORDER_LESS_3, THREE, Null<uint8_t_32>(), "", "-3 + 3 == 0" });
  42. // fuzz
  43. for (size_t i = 0; i < 10000; ++i) {
  44. const auto paPush = [&](const auto k, const auto t) {
  45. bool ok = true;
  46. const auto expected = _privAdd(k, t, ok);
  47. if (ok) pa.push_back({ k, t, expected });
  48. else pa.push_back({ k, t, Null<uint8_t_32>() });
  49. };
  50. paPush(randomPrivate(), randomPrivate());
  51. paPush(randomPrivateHigh(), randomPrivateLow());
  52. paPush(randomPrivateLow(), randomPrivateHigh());
  53. }
  54. std::vector<PA> paf;
  55. for (const auto x : BAD_PRIVATES) paf.push_back({ x.a, ONE, {}, THROW_BAD_PRIVATE, x.desc });
  56. for (const auto x : BAD_TWEAKS) paf.push_back({ ONE, x.a, {}, THROW_BAD_TWEAK, x.desc });
  57. ///////////////////////////////// privateSub
  58. std::vector<PA> ps;
  59. // visually inspected
  60. // covers https://github.com/bitcoin-core/secp256k1/blob/6ad5cdb42a1a8257289a0423d644dcbdeab0f83c/src/tests.c
  61. ps.push_back({ ONE, ZERO, ONE, "", "1 - 0 == 1" });
  62. for (size_t i = 2; i < 7; ++i) ps.push_back({ scalarFromUInt32(i), ONE, scalarFromUInt32(i - 1) });
  63. for (size_t i = 1; i < 10; ++i) ps.push_back({ scalarFromUInt32(10), scalarFromUInt32(i), scalarFromUInt32(10 - i) });
  64. ps.push_back({ ONE, ONE, Null<uint8_t_32>(), "", "1 - 1 == 0" });
  65. ps.push_back({ THREE, THREE, Null<uint8_t_32>(), "", "3 - 3 == 0" });
  66. ps.push_back({ GROUP_ORDER_LESS_1, ONE, GROUP_ORDER_LESS_2 });
  67. ps.push_back({ GROUP_ORDER_LESS_2, ONE, GROUP_ORDER_LESS_3 });
  68. ps.push_back({ GROUP_ORDER_LESS_1, GROUP_ORDER_LESS_2, ONE });
  69. ps.push_back({ GROUP_ORDER_LESS_2, GROUP_ORDER_LESS_3, ONE });
  70. // fuzz
  71. for (size_t i = 0; i < 1000; ++i) {
  72. const auto psPush = [&](const auto k, const auto t) {
  73. bool ok = true;
  74. const auto expected = _privSub(k, t, ok);
  75. if (ok) ps.push_back({ k, t, expected });
  76. else ps.push_back({ k, t, Null<uint8_t_32>() });
  77. };
  78. psPush(randomPrivate(), randomPrivate());
  79. psPush(randomPrivateHigh(), randomPrivateLow());
  80. psPush(randomPrivateLow(), randomPrivateHigh());
  81. }
  82. std::vector<PA> psf;
  83. for (const auto x : BAD_PRIVATES) psf.push_back({ x.a, ONE, {}, THROW_BAD_PRIVATE, x.desc });
  84. for (const auto x : BAD_TWEAKS) psf.push_back({ ONE, x.a, {}, THROW_BAD_TWEAK, x.desc });
  85. // dump JSON
  86. const auto jPA = [](auto x) {
  87. return jsonifyO({
  88. x.desc.empty() ? "" : jsonp("description", jsonify(x.desc)),
  89. jsonp("d", jsonify(x.a)),
  90. jsonp("tweak", jsonify(x.b)),
  91. x.except.empty() ? jsonp("expected", isNull(x.e) ? "null" : jsonify(x.e)) : "",
  92. x.except.empty() ? "" : jsonp("exception", jsonify(x.except))
  93. });
  94. };
  95. o << jsonifyO({
  96. jsonp("valid", jsonifyO({
  97. jsonp("isPrivate", jsonifyA(ip, [](auto x) {
  98. return jsonifyO({
  99. x.desc.empty() ? "" : jsonp("description", jsonify(x.desc)),
  100. jsonp("d", jsonify(x.a)),
  101. jsonp("expected", jsonify(x.e))
  102. });
  103. })),
  104. jsonp("privateAdd", jsonifyA(pa, jPA)),
  105. jsonp("privateSub", jsonifyA(ps, jPA))
  106. })),
  107. jsonp("invalid", jsonifyO({
  108. jsonp("privateAdd", jsonifyA(paf, jPA)),
  109. jsonp("privateSub", jsonifyA(psf, jPA))
  110. }))
  111. });
  112. }
  113. int main () {
  114. _ec_init();
  115. generate(std::cout);
  116. return 0;
  117. }