Bitcoin
checklocktimeverify – Unwitnessed P2SH spending using C++ libbitcoin
I’m trying to use UTXO (Unwitness P2SH) using libbitcoin. I looked at the libbitcoin-system wiki documentation (https://github.com/libbitcoin/libbitcoin-system/wiki) but didn’t find a solution to my problem. Unfortunately, this page only provides guidance on nested SegWit P2SH spending.
The redemption script is as follows =>
<expiry time> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Below is the C++ code I wrote =>
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 generated raw transaction returned an error (the signature should be 0 for a failed CHECK(MULTI)SIG operation). This indicates a problem with the signature part. I’ve checked every detail (at least I think so), from the script to the values, but I can’t figure out exactly what’s wrong. Can someone help me?