<p>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 &quot;script_version::zero&quot;, the correct configuration in this case was &quot;script_version::unversioned&quot;.</p>

CC BY-SA 4.0
2024-05-04T18:13:33.460Z
2024-05-04T18:13:33.460Z
paranoid
<p>I am trying to spend an UTXO (non-witness P2SH) using libbitcoin. I've look at libbitcoin-system wiki documentation (<a href="https://github.com/libbitcoin/libbitcoin-system/wiki" rel="nofollow noreferrer">https://github.com/libbitcoin/libbitcoin-system/wiki</a>) but haven't found a solution for my problem. Unfortunately, the page only provides guide to nested-segwit P2SH spending.</p>
<p>The redeem script is the following =&gt;</p>
<pre><code>&lt;expiry time&gt; OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 &lt;pubKeyHash&gt; OP_EQUALVERIFY OP_CHECKSIG
</code></pre>
<p>Below is the C++ code I wrote to spend =&gt;</p>
<pre class="lang-cpp prettyprint-override"><code>    int main() {
        wallet::ec_private privateKey1(&quot;secret for obvious reason&quot;);
        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&lt;uint32_t&gt;(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(&quot;p2sh-cltv-address&quot;);
        wallet::payment_address to_address1(&quot;p2pkh-legacy-address&quot;);

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

        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, &quot;0.00999770&quot;, 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&lt;uint32_t&gt;(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 &lt;&lt; &quot;Signature: &quot; &lt;&lt; std::endl;
            std::cout &lt;&lt; encode_base16(sig1) &lt;&lt; &quot;\n&quot; &lt;&lt; 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 &lt;&lt; unlockingScript1.to_string(0) &lt;&lt; &quot;\n&quot; &lt;&lt; std:: endl;

        //Make Signed TX
        tx.inputs()[0].set_script(unlockingScript1);
        std::cout &lt;&lt; &quot;Raw Transaction: &quot; &lt;&lt; std::endl;
        std::cout &lt;&lt; encode_base16(tx.to_data(true, true)) &lt;&lt; std::endl;
        return 0;
    }
</code></pre>
<p>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?</p>

<p2sh><checklocktimeverify><libbitcoin>
Non-witness P2SH spending using C++ libbitcoin
paranoid
# Non-witness P2SH spending using C++ libbitcoin

(Asked by: username_0 on 2024-05-01)

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 =>
 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160  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(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(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?

**Tags:** p2sh, checklocktimeverify, libbitcoin


---

## 1 answers

### Answer by username_0 on 2024-05-04. Score: 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".


---

