Closed mindkind closed 3 years ago
I'm trying to spend this transaction but since its not a p2pkh address i am lost, can someone please help me.
Hi, thanks for opening the issue
I glanced over the code and nothing seemed off with regards how you are using the library, I ran the script and saw "Script validation result: yay" so I took this to mean testnet3 wasn't accepting your signed transaction
https://blockstream.info/testnet/tx/cf1d74ef626b36eb0c9295f5dc7a45fcefece44b34ac8a02be4a114a8946bc1a
When I look at the transaction, I can spot the issue - the value you used in $txOut doesn't match the value of the output on the block explorer. This would explain why bitcoin php verified the transaction, but the network failed it - segwit signatures commit to the amount of the output being spent, to protect against certain attacks. Since the same value for 'amount' was used for signing + verification, the signature was 'valid' to bitcoin-php, but when the network verifies, it's using the actual value for 'amount' and so the signature fails
The fix happens on these two lines:
// this line, use 1946804
$txOut = new TransactionOutput(1947304, $p2shScript->getOutputScript());
...
// on this line, use an appropriate number that's smaller than 1946804 to allow for fees
->payToAddress(1946804, $addressCreator->fromString("mmQTeNks2M8roQBiup8fD8cfw5DiqxoYGn"));
I think if you make these alterations the transaction will broadcast - good luck and let me know if there's anything else
Thank you sir ;)
Glad you got it sorted!
and how about me?, fail too...
Bitcoin::setNetwork(NetworkFactory::bitcoinTestnet());
// Setup network and private key to segnet $privKeyFactory = new PrivateKeyFactory(); $key = $privKeyFactory->fromWif("cTcRivQrRrbZXQ5YkeRV29BHGe3aBJuLsLcivZe35fHrTibFfCmB");
// Script is P2SH | P2WSH | P2PKH $witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash())); $p2shScript = new P2shScript($witnessScript);
$address = $p2shScript->getAddress()->getAddress();
// UTXO $outpoint = new OutPoint(Buffer::hex('7c2892e947cda2edfbec3e47a68949a3af995fb2aec41bb4dd190466ec2c79fb', 32), 0); $txOut = new TransactionOutput(100000, $p2shScript->getOutputScript());
$addressCreator = new AddressCreator();
// Create unsigned transaction $tx = (new TxBuilder()) ->spendOutPoint($outpoint) ->payToAddress(90000, $addressCreator->fromString("mvCR6zv4rY4p4NSEMKw38WKZEq5QSX1Zra"));
// Sign the transaction
$signData = (new SignData()) ->p2sh($p2shScript) ->p2wsh($witnessScript);
$signer = new Signer($tx->get(), Bitcoin::getEcAdapter()); $input = $signer->input(0, $txOut, $signData); $input->sign($key);
$signed = $signer->get();
sendrawtransaction RPC error: {"code":-26,"message":"mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)"}
`<?php
require_once(DIR . "/modules/bitcoin-php/vendor/autoload.php");
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Address\Address; use BitWasp\Bitcoin\Address\AddressCreator; use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress; use BitWasp\Bitcoin\Address\ScriptHashAddress; use BitWasp\Bitcoin\Address\SegwitAddress; use BitWasp\Bitcoin\Script\P2shScript; use BitWasp\Bitcoin\Script\WitnessScript; use BitWasp\Bitcoin\Script\WitnessProgram;
use BitWasp\Bitcoin\Address\AddressFactory; use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Transaction\Factory\Signer; use BitWasp\Bitcoin\Transaction\Factory\TxBuilder; use BitWasp\Bitcoin\Transaction\OutPoint; use BitWasp\Bitcoin\Transaction\Transaction; use BitWasp\Bitcoin\Transaction\TransactionOutput; use BitWasp\Bitcoin\Transaction\TransactionInput; use BitWasp\Bitcoin\Transaction\TransactionFactory;
use BitWasp\Bitcoin\Script\Interpreter\InterpreterInterface as I; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Script\Script; use BitWasp\Bitcoin\Network\NetworkFactory; use BitWasp\Bitcoin\Transaction\Factory\SignData;
Bitcoin::setNetwork(NetworkFactory::bitcoinTestnet());
// Setup network and private key to segnet $privKeyFactory = new PrivateKeyFactory(); $key = $privKeyFactory->fromWif("cMwnKaFRvP9No8qdRUcuMzsMhyyCm8UEoNWhmfxW5F6Nn4Ak2rUA");
// Script is P2SH | P2WSH | P2PKH $witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash())); $p2shScript = new P2shScript($witnessScript);
$address = $p2shScript->getAddress()->getAddress();
// UTXO $outpoint = new OutPoint(Buffer::hex('cf1d74ef626b36eb0c9295f5dc7a45fcefece44b34ac8a02be4a114a8946bc1a', 32), 0); $txOut = new TransactionOutput(1947304, $p2shScript->getOutputScript());
$addressCreator = new AddressCreator();
// Create unsigned transaction $tx = (new TxBuilder()) ->spendOutPoint($outpoint) ->payToAddress(1946804, $addressCreator->fromString("mmQTeNks2M8roQBiup8fD8cfw5DiqxoYGn"));
// Sign the transaction
$signData = (new SignData()) ->p2sh($p2shScript) ->p2wsh($witnessScript);
$signer = new Signer($tx->get(), Bitcoin::getEcAdapter()); $input = $signer->input(0, $txOut, $signData); $input->sign($key);
$signed = $signer->get();
// Verify what we've produced
$consensus = ScriptFactory::consensus(); echo "Script validation result: " . ($input->verify(I::VERIFY_P2SH | I::VERIFY_WITNESS) ? "yay\n" : "nay\n");
echo PHP_EOL; echo "Witness serialized transaction: " . $signed->getHex() . PHP_EOL. PHP_EOL; echo "Base serialized transaction: " . $signed->getBaseSerialization()->getHex() . PHP_EOL;`