2

I am trying to spend an UTXO (non-witness P2SH) using libbitcoin. I've look at libbitcoin-system wiki documentation (https://github.com/libbitcoin/libbitcoin-system/wiki) but haven't found a solution for my problem. Unfortunately, the page only provides guide to nested-segwit P2SH spending.

The redeem script is the following =>

<expiry time> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Below is the C++ code I wrote to spend =>

    int main() {
        wallet::ec_private privateKey1("secret for obvious reason");
        wallet::ec_public publicKey1 = privateKey1.to_public();
        data_chunk pubKey1 = to_chunk(publicKey1.point());

        short_hash KeyHash1 = bitcoin_short_hash(publicKey1.point());
        data_chunk locktime;
        extend_data(locktime, to_little_endian<uint32_t>(1713352486));

        script redeem_script = script({operation(locktime), operation(opcode(177)), operation(opcode(117)), operation(opcode(118)), operation(opcode(169)), operation(to_chunk(KeyHash1)), operation(opcode(136)), operation(opcode(172))});

        wallet::payment_address from_address1("p2sh-cltv-address");
        wallet::payment_address to_address1("p2pkh-legacy-address");

        hash_digest prev_txid1;
        decode_hash(prev_txid1, "prev-txid-in-hexadecimal-format");

        uint32_t input_index1 = 0;
        output_point vin1(prev_txid1, input_index1);

        //make Input
        input input1 = input();
        input1.set_previous_output(vin1);
        input1.set_sequence(0xfffffffe);

        uint64_t output_value1;
        decode_base10(output_value1, "0.00999770", 8);
        script output_script1 = script().to_pay_key_hash_pattern(to_address1.hash());
        output output1(output_value1, output_script1);
    
        // Get current time as a time_point
        auto now = std::chrono::system_clock::now();
        auto epoch = std::chrono::system_clock::to_time_t(now);
        auto unix_time = static_cast<uint32_t>(epoch);

        chain::transaction tx = chain::transaction();
        tx.set_version(2);
        tx.set_locktime(unix_time - 100000);
        tx.inputs().push_back(input1);
        tx.outputs().push_back(output1); 

        endorsement sig1; 
        if (script::create_endorsement(sig1, privateKey1.secret(), redeem_script, tx, 0u, sighash_algorithm::all, script_version::zero, 1000000))
        {
            std::cout << "Signature: " << std::endl;
            std::cout << encode_base16(sig1) << "\n" << std::endl; 
        }

        operation::list scriptSig1; 
        scriptSig1.push_back(operation(sig1));
        scriptSig1.push_back(operation(pubKey1));
        scriptSig1.push_back(operation(redeem_script.to_data(0)));
        script unlockingScript1(scriptSig1);
        std::cout << unlockingScript1.to_string(0) << "\n" << std:: endl;

        //Make Signed TX
        tx.inputs()[0].set_script(unlockingScript1);
        std::cout << "Raw Transaction: " << std::endl;
        std::cout << encode_base16(tx.to_data(true, true)) << std::endl;
        return 0;
    }

The broadcast of the created raw-transaction returned an error (Signature must be zero for failed CHECK(MULTI)SIG operation), which indicates that something went wrong with the signature part. I checked every (at least I think so) details, from scripts to values but I can't tell exactly what is wrong. Can somebody help?

1 Answer 1

1

The issue is no more now. The problem was with the script version (which was set to zero in the code presented above). Instead of "script_version::zero", the correct configuration in this case was "script_version::unversioned".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.