I was sent a P2SH puzzle address. I have solved the puzzle, which is to say I have created a script that matches the hash, and I know what to put on the stack before the script. Sadly, what I am having trouble figuring out is how to actually create a valid transaction with this non-standard script and no signature. All the examples and documentation I've found only talk about creating standard signature-based transactions and not ones with arbitrary scripts.

For example, let's say the encoded script is 955787 and someone actually sent bitcoin to the P2SH address for that script, which is 3PijzLhTnkA9S2HDFLrdwX9SCg69W8ggD4

Now I want to spend that by providing the full redeem script:

1 7 955787

or I guess more accurately

OP_1 OP_7 3 0x955787

How do I actually create that transaction using bitcoind or bcoin? I don't see how to get it to create a transaction with that supplied script or transmit it to the network without a signature. I am looking for a list of command-line commands to run (use placeholders for any required data I did not supply above).

  • This is standard behavior/script/transaction. it is even not too difficult to create a transaction manually and/or write a tool for it. I think importaddress "955787" "3PijzLhTnkA9S2HDFLrdwX9SCg69W8ggD4" false will help – amaclin Dec 1 '17 at 4:29

First thing I noticed was the redeemScript, it's using OP_MUL which is disabled and you won't be able to use it in scripts. But I can show it using OP_ADD.

If you want to play with bcoin and test the scripts, how they validate you can use bcoin.script:

Verify and play with scripts

const scriptSig = new Script();
scriptSig.pushInt(6);
scriptSig.pushInt(1);
scriptSig.compile();

or you can assemble it using just string

const scriptSig = Script.fromString('OP_6 OP_1');

Now pubkeyScript (redeemScript in P2SH)

const scriptPubkey = Script.fromRaw('935787', 'hex');

Or more verbose

const scriptPubkey = Script.fromString('OP_ADD OP_7 OP_EQUAL');

You can use bcoin.stack to run these scripts

const stack = new Stack();
scriptSig.execute(stack);
scriptPubkey.execute(stack);

// Verify the script was successful in its execution:
assert(stack.length === 1);
assert(stack.getBool(-1) === true);

Redeem transaction

Back to the question:

const redeemScript = Script.fromRaw('935787', 'hex');
const address = Address.fromScripthash(redeemScript.hash160());
const sendto = Address.fromString('sendtoaddress');

// generate script with redeem
const script = new Script();
script.pushInt(6);
script.pushInt(1);
script.push(Opcode.fromPush(redeemScript.toRaw()));
script.compile();


// We received some transaction
// lets say coinbase
const cb = new MTX();

// Add a typical coinbase input
cb.addInput({
  prevout: new Outpoint(),
  script: new Script()
});

cb.addOutput({
  address: address,
  value: Amount.fromBTC('5').toValue()
});

const coin = bcoin.coin.fromTX(cb, 0, -1);

// From here we spend the transaction
const spend = new MTX();

spend.addCoin(coin);
spend.addOutput(sendto, Amount.fromBTC('4.9999').toValue());

spend.inputs[0].script = script;

assert(spend.verify());

// You can broadcast raw transaction
console.log(spend.toRaw().toString('hex'));

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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