fireblocks / mpc-lib

GNU General Public License v3.0
147 stars 86 forks source link

Failed when trying to create ecdsa_preprocess data after refresh key shares #29

Open titrabui opened 2 weeks ago

titrabui commented 2 weeks ago

I tried to modify a little bit in the test of ECDSA offline

1. Create shares
2. Create ecdsa_preprocess data
3. Refresh key shares
3. ecdsa_sign
4. Create ecdsa_preprocess data <--- FAILED

I got FAILED when trying to create ecdsa_preprocess data after refresh key shares, error is below image

image

I though that we can ecdsa_preprocess after refreshing key shares. So, could you please check whether this is a bug or I made a mistake here? Thank so much

nadav-fireblocks commented 2 weeks ago

Hi @titrabui, could you make your change public so that they are easier to reproduce and discuss?

titrabui commented 2 weeks ago

Hi @nadav-fireblocks I just added the function ecdsa_preprocess at the end of test case cmp_offline_ecdsa > secp256k1 in file test/cosigner/ecdsa_offline_test.cpp Then run make run-tests, you will got FAILED

TEST_CASE("cmp_offline_ecdsa") {
    byte_vector_t chaincode(32, '\0');
    std::vector<uint32_t> path = {44, 0, 0, 0, 0};
    char keyid[37] = {0};
    elliptic_curve256_point_t pubkey;
    players_setup_info players;

    SECTION("secp256k1") {  
        uuid_t uid;
        uuid_generate_random(uid);
        uuid_unparse(uid, keyid);
        players.clear();
        players[1];
        players[2];
        create_secret(players, ECDSA_SECP256K1, keyid, pubkey);

        std::map<uint64_t, std::unique_ptr<offline_siging_info>> services;
        for (auto i = players.begin(); i != players.end(); ++i)
        {
            auto info = std::make_unique<offline_siging_info>(i->first, i->second);
            services.emplace(i->first, move(info));
        }

        auto before = Clock::now();
        ecdsa_preprocess(services, keyid, 0, BLOCK_SIZE, BLOCK_SIZE);
        auto after = Clock::now();
        std::cout << "ECDSA preprocessing took: " << std::chrono::duration_cast<std::chrono::milliseconds>(after - before).count() << " ms" << std::endl;

        ecdsa_sign(services, ECDSA_SECP256K1, keyid, 0, 1, pubkey, chaincode, {path});

        char txid[37] = {0};
        uuid_generate_random(uid);
        uuid_unparse(uid, txid);
        std::set<uint64_t> players_ids;
        std::set<std::string> players_str;
        for (auto i = services.begin(); i != services.end(); ++i)
        {
            players_ids.insert(i->first);
            players_str.insert(std::to_string(i->first));
        }
        signing_data data;
        memcpy(data.chaincode, chaincode.data(), sizeof(HDChaincode));
        signing_block_data block;
        block.data.insert(block.data.begin(), 32, '0');
        block.path = path;
        data.blocks.push_back(block);
        std::vector<recoverable_signature> sigs;
        REQUIRE_THROWS_MATCHES(services.begin()->second->signing_service.ecdsa_sign(keyid, txid, data, "", players_str, players_ids, 0, sigs), cosigner_exception, 
            Catch::Matchers::Predicate<cosigner_exception>([](const cosigner_exception& e) {return e.error_code() == cosigner_exception::INVALID_PRESIGNING_INDEX;}));

        // run 4 times as R has 50% chance of being negative
        for (size_t i = 0; i < 4; ++i)
            ecdsa_sign(services, ECDSA_SECP256K1, keyid, i + 1, 1, pubkey, chaincode, {path}, true);

        const size_t COUNT = 4;
        std::vector<uint32_t> derivation_path = {44, 0, 0, 0, 0};
        std::vector<std::vector<uint32_t>> derivation_paths;
        for (size_t i = 0; i < COUNT; i++)
        {
            derivation_paths.push_back(derivation_path);
            ++derivation_path[2];
        }
        ecdsa_sign(services, ECDSA_SECP256K1, keyid, 5, COUNT, pubkey, chaincode, derivation_paths);

        std::map<uint64_t, std::unique_ptr<key_refresh_info>> refresh_info;
        for (auto i = players.begin(); i != players.end(); ++i)
        {
            auto info = std::make_unique<key_refresh_info>(i->first, i->second, services.at(i->first)->persistency);
            refresh_info.emplace(i->first, move(info));
        }
        key_refresh(refresh_info, keyid, pubkey);
        ecdsa_sign(services, ECDSA_SECP256K1, keyid, 9, 1, pubkey, chaincode, derivation_paths);
 +      ecdsa_preprocess(services, keyid, 10, BLOCK_SIZE, BLOCK_SIZE);