| 178 | } |
| 179 | |
| 180 | static void exercise_detach_attach(curve_id curve, const coinbase::crypto::ecurve_t& verify_curve) { |
| 181 | auto c1 = std::make_shared<mpc_net_context_t>(0); |
| 182 | auto c2 = std::make_shared<mpc_net_context_t>(1); |
| 183 | std::vector<std::shared_ptr<mpc_net_context_t>> peers = {c1, c2}; |
| 184 | c1->init_with_peers(peers); |
| 185 | c2->init_with_peers(peers); |
| 186 | |
| 187 | local_api_transport_t t1(c1); |
| 188 | local_api_transport_t t2(c2); |
| 189 | |
| 190 | buf_t key_blob_1; |
| 191 | buf_t key_blob_2; |
| 192 | error_t rv1 = UNINITIALIZED_ERROR; |
| 193 | error_t rv2 = UNINITIALIZED_ERROR; |
| 194 | |
| 195 | const coinbase::api::job_2p_t job1{party_t::p1, "p1", "p2", t1}; |
| 196 | const coinbase::api::job_2p_t job2{party_t::p2, "p1", "p2", t2}; |
| 197 | run_2pc( |
| 198 | c1, c2, [&] { return coinbase::api::ecdsa_2p::dkg(job1, curve, key_blob_1); }, |
| 199 | [&] { return coinbase::api::ecdsa_2p::dkg(job2, curve, key_blob_2); }, rv1, rv2); |
| 200 | ASSERT_EQ(rv1, SUCCESS); |
| 201 | ASSERT_EQ(rv2, SUCCESS); |
| 202 | |
| 203 | // Refresh (exercise detach/attach on refreshed blobs too). |
| 204 | buf_t refreshed_1; |
| 205 | buf_t refreshed_2; |
| 206 | run_2pc( |
| 207 | c1, c2, [&] { return coinbase::api::ecdsa_2p::refresh(job1, key_blob_1, refreshed_1); }, |
| 208 | [&] { return coinbase::api::ecdsa_2p::refresh(job2, key_blob_2, refreshed_2); }, rv1, rv2); |
| 209 | ASSERT_EQ(rv1, SUCCESS); |
| 210 | ASSERT_EQ(rv2, SUCCESS); |
| 211 | |
| 212 | buf_t pub1; |
| 213 | ASSERT_EQ(coinbase::api::ecdsa_2p::get_public_key_compressed(refreshed_1, pub1), SUCCESS); |
| 214 | coinbase::crypto::ecc_point_t Q; |
| 215 | ASSERT_EQ(Q.from_bin(verify_curve, pub1), SUCCESS); |
| 216 | const coinbase::crypto::ecc_pub_key_t verify_key(Q); |
| 217 | |
| 218 | // Detach into scalar-redacted blob + variable-length scalar. |
| 219 | buf_t public_1; |
| 220 | buf_t public_2; |
| 221 | buf_t x1; |
| 222 | buf_t x2; |
| 223 | ASSERT_EQ(coinbase::api::ecdsa_2p::detach_private_scalar(refreshed_1, public_1, x1), SUCCESS); |
| 224 | ASSERT_EQ(coinbase::api::ecdsa_2p::detach_private_scalar(refreshed_2, public_2, x2), SUCCESS); |
| 225 | EXPECT_GT(public_1.size(), 0); |
| 226 | EXPECT_GT(public_2.size(), 0); |
| 227 | EXPECT_GT(x1.size(), 0); |
| 228 | EXPECT_GT(x2.size(), 0); |
| 229 | |
| 230 | // Capture share points before detaching (public blobs no longer carry them). |
| 231 | buf_t Qi_full_1; |
| 232 | ASSERT_EQ(coinbase::api::ecdsa_2p::get_public_share_compressed(refreshed_1, Qi_full_1), SUCCESS); |
| 233 | |
| 234 | buf_t Qi_full_2; |
| 235 | ASSERT_EQ(coinbase::api::ecdsa_2p::get_public_share_compressed(refreshed_2, Qi_full_2), SUCCESS); |
| 236 | |
| 237 | // Public blob should not be usable for signing. |
no test coverage detected