Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to send payment from the address generated by addresstypes.script.php #841

Closed
wartw opened this issue Mar 9, 2020 · 30 comments
Closed

Comments

@wartw
Copy link

wartw commented Mar 9, 2020

https://github.com/Bit-Wasp/bitcoin-php/blob/1.0/examples/addresstypes.script.php
How to send payment from the address generated by addresstypes.script.php, I can't find related examples

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

They're P2PKH scripts, with P2PKH in P2SH, and another with P2PKH in P2WSH. Here's an example of P2PKH. https://github.com/Bit-Wasp/bitcoin-php/blob/1.0/examples/offlinetx.p2pkh.testnet.php - and for the rest, you need to look at P2SH or P2WSH examples.

Like I explained before, try use this workflow for a P2PKH address #836 (comment) Post back with the code that you tried, and the error.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

<?php

require "vendor/autoload.php";

use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
use BitWasp\Bitcoin\Script\Interpreter\InterpreterInterface as I;
use BitWasp\Bitcoin\Script\ScriptFactory;
use BitWasp\Bitcoin\Transaction\Factory\Signer;
use BitWasp\Bitcoin\Transaction\Factory\TxBuilder;
use BitWasp\Bitcoin\Transaction\OutPoint;
use BitWasp\Bitcoin\Transaction\TransactionOutput;
use BitWasp\Buffertools\Buffer;
use BitWasp\Bitcoin\Transaction\Factory\SignData;
use BitWasp\Bitcoin\Script\WitnessScript;
use BitWasp\Bitcoin\Script\P2shScript;
use BitWasp\Bitcoin\Address\SegwitAddress;
use BitWasp\Bitcoin\Script\WitnessProgram;
use BitWasp\Bitcoin\Address\AddressCreator;

// Setup network and private key to segnet
$privKeyFactory = new PrivateKeyFactory;
$key = $privKeyFactory->fromWif("xxxxxxxxxx");//WIF

// Script is P2SH | P2WSH | P2PKH
$witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash()));
$p2shScript = new P2shScript($witnessScript);

// move to p2wpkh
$dest = new SegwitAddress(WitnessProgram::v0($key->getPublicKey()->getPubKeyHash()));

// Utxo
$outpoint = new OutPoint(Buffer::hex('44fd3a365aa0dbc0ccbcd61421757df3221e1403ef14e8141bb6986571c9be7c', 32), 0);
$txOut = new TransactionOutput(10000, $p2shScript->getOutputScript());

// Move UTXO to pub-key-hash
$builder = (new TxBuilder())
    ->spendOutPoint($outpoint)
    ->payToAddress(9000, $dest);

// Sign the transaction

$signData = (new SignData())
    ->p2sh($p2shScript)
    ->p2wsh($witnessScript);

$signer = new Signer($builder->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;

Edit: updated by @afk11 to use php code formatting

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Script validation result: yay

Witness serialized transaction: 010000000001017cbec9716598b61b14e814ef03141e22f37d752114d6bcccc0dba05a363afd44000000002322002023547dc2dddb15e83de7219093a5d02858943711e3eed4d56793936c06de782affffffff0128230000000000001600147bad4e01a499302dca9eab0e0dab19bdada0c53503483045022100b8cfce6d378abcdf53aa57a1d9c3b8c1023029d0de16f338c28b12c0dfa68b040220692bd3181591f6ab7671ba7e3c517b8f33488851a94c8c74bd91998cc5e10f7f0121037e11e4c2f058da13df5cd63632a22ed3ddf813692f330cd9e91965317f9ef04e1976a9149b91b0294a6d584049f323bd7e8b0f850ff420ac88ac00000000

Base serialized transaction: 01000000017cbec9716598b61b14e814ef03141e22f37d752114d6bcccc0dba05a363afd44000000002322002023547dc2dddb15e83de7219093a5d02858943711e3eed4d56793936c06de782affffffff0128230000000000001600147bad4e01a499302dca9eab0e0dab19bdada0c53500000000

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Appears when broadcasting a transaction
Code: -26, Error: non-mandatory-script-verify-flag (Witness requires empty scriptSig) (code 64)

@wartw
Copy link
Author

wartw commented Mar 9, 2020

I use "https://www.blockchain.com/zh-cn/btc/pushtx" for broadcast transactions

@wartw
Copy link
Author

wartw commented Mar 9, 2020

The isolated transaction address I have established is bc1qyd28mskamv27s008yxgf8fws9pvfgdc3u0hdf4t8jwfkcpk70q4qe73tw2

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

I have no idea what you're trying to do at this point, and I don't think you do either. My suggestion is to start small, and don't try to do everything all at once. You're missing the picture, and making it hard on yourself.

Edit:
44fd3a365aa0dbc0ccbcd61421757df3221e1403ef14e8141bb6986571c9be7c, 0 pays to your address bc1qyd28mskamv27s008yxgf8fws9pvfgdc3u0hdf4t8jwfkcpk70q4qe73tw2

bc1qyd28mskamv27s008yxgf8fws9pvfgdc3u0hdf4t8jwfkcpk70q4qe73tw2 - this is P2WSH|P2PKH (I don't know for sure it's P2PKH unless I see the code, but I presume it is because you asked about addresstypes.script.php.

The error said: (Witness requires empty scriptSig)

Your code is trying to spend from P2SH|P2WSH|P2PKH though, and that's wrong. The error was telling you that the funds you are trying to spend are segwit, and so REQUIRE that the scriptSig field is empty. It's NOT empty, because you told the library to sign it as a P2SH script. But you generated the address, so you should know there's no P2SH script here.

Decoding your transaction (again, learn bitcoind, or use this tool https://btc.com/tools/tx/decode) would at least show that there's something called scriptSig, and it's not empty.

You need to delete everything about P2shScript, and any usages.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

I use "addresstypes.script.php" established P2WSH
I will now transfer from this generated P2WSH
I do not know how to get PubKeyHash of P2WSH

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

@wartw see updated comment.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

So I just need TxBuilder and sign it?

@wartw
Copy link
Author

wartw commented Mar 9, 2020

My English is not very good, maybe there are some grammatical problems, please forgive me

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

Uhh, no. Your TxBuilder part is fine. You're just telling the signer the wrong instructions.

Delete any line which as p2sh in it, and it'll probably work.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Is it deleted here? One of them?
// Sign the transaction

$signData = (new SignData())
->p2sh($p2shScript)
->p2wsh($witnessScript);

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

Delete any line which as p2sh in it, and it'll probably work.

:) Yes, there too.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

let me try

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

 Try putting ```php before your code, and ``` after. Github will format it.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

<?php

require "vendor/autoload.php";

use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
use BitWasp\Bitcoin\Script\Interpreter\InterpreterInterface as I;
use BitWasp\Bitcoin\Script\ScriptFactory;
use BitWasp\Bitcoin\Transaction\Factory\Signer;
use BitWasp\Bitcoin\Transaction\Factory\TxBuilder;
use BitWasp\Bitcoin\Transaction\OutPoint;
use BitWasp\Bitcoin\Transaction\TransactionOutput;
use BitWasp\Buffertools\Buffer;
use BitWasp\Bitcoin\Transaction\Factory\SignData;
use BitWasp\Bitcoin\Script\WitnessScript;
use BitWasp\Bitcoin\Script\P2shScript;
use BitWasp\Bitcoin\Address\SegwitAddress;
use BitWasp\Bitcoin\Script\WitnessProgram;
use BitWasp\Bitcoin\Address\AddressCreator;

// Setup network and private key to segnet
$privKeyFactory = new PrivateKeyFactory;
$key = $privKeyFactory->fromWif("xxxx");//WIF

// Script is P2SH | P2WSH | P2PKH
$witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash()));

// move to p2wpkh
$dest = new SegwitAddress(WitnessProgram::v0($key->getPublicKey()->getPubKeyHash()));

// Utxo
$outpoint = new OutPoint(Buffer::hex('44fd3a365aa0dbc0ccbcd61421757df3221e1403ef14e8141bb6986571c9be7c', 32), 0);
$txOut = new TransactionOutput(10000, $witnessScript));

// Move UTXO to pub-key-hash
$builder = (new TxBuilder())
->spendOutPoint($outpoint)
->payToAddress(9000, $dest);

// Sign the transaction

$signer = new Signer($builder->get(), Bitcoin::getEcAdapter());
$input = $signer->input(0, $txOut);
$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;

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Script validation result: yay

Witness serialized transaction: 01000000017cbec9716598b61b14e814ef03141e22f37d752114d6bcccc0dba05a363afd44000000006b483045022100f4af4211015e2b39c9c2d832bc676bc720d7daaa52f0427e360df07e73e0a39e022049698664edb879dfb7df27495f5de5800ef53bfd42ad4ceae2f3fe8f42bc4b330121037e11e4c2f058da13df5cd63632a22ed3ddf813692f330cd9e91965317f9ef04effffffff0128230000000000001600149b91b0294a6d584049f323bd7e8b0f850ff420ac00000000

Base serialized transaction: 01000000017cbec9716598b61b14e814ef03141e22f37d752114d6bcccc0dba05a363afd44000000006b483045022100f4af4211015e2b39c9c2d832bc676bc720d7daaa52f0427e360df07e73e0a39e022049698664edb879dfb7df27495f5de5800ef53bfd42ad4ceae2f3fe8f42bc4b330121037e11e4c2f058da13df5cd63632a22ed3ddf813692f330cd9e91965317f9ef04effffffff0128230000000000001600149b91b0294a6d584049f323bd7e8b0f850ff420ac00000000

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Same broadcast error but Witness has been cleared

@wartw
Copy link
Author

wartw commented Mar 9, 2020

 Try putting ```php before your code, and ``` after. Github will format it.

I just found it and I found it

@wartw
Copy link
Author

wartw commented Mar 9, 2020

I was wrong, I changed it again

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

Ah, one more thing to fix - instead of passing $witnessScript into TransactionOutput, you actually need to pass $witnessScript->getOutputScript().
$txOut = new TransactionOutput(10000, $witnessScript->getOutputScript()));

I think that explains why your tx was being signed as P2PKH too.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Ah, one more thing to fix - instead of passing $witnessScript into TransactionOutput, you actually need to pass $witnessScript->getOutputScript().
$txOut = new TransactionOutput(10000, $witnessScript->getOutputScript()));

I think that explains why your tx was being signed as P2PKH too.

Fatal error: Uncaught BitWasp\Bitcoin\Exceptions\ScriptQualificationError: Witness script not provided in sign data or witness in /var/www/admin/corn/vendor/bitwasp/bitcoin/src/Script/FullyQualifiedScript.php:155
Stack trace:
#0 /var/www/admin/corn/vendor/bitwasp/bitcoin/src/Script/FullyQualifiedScript.php(206): BitWasp\Bitcoin\Script\FullyQualifiedScript::findWitnessScript(Object(BitWasp\Bitcoin\Script\ScriptWitness), Object(BitWasp\Bitcoin\Transaction\Factory\SignData))
#1 /var/www/admin/corn/vendor/bitwasp/bitcoin/src/Transaction/Factory/InputSigner.php(234): BitWasp\Bitcoin\Script\FullyQualifiedScript::fromTxData(Object(BitWasp\Bitcoin\Script\Script), Object(BitWasp\Bitcoin\Script\Script), Object(BitWasp\Bitcoin\Script\ScriptWitness), Object(BitWasp\Bitcoin\Transaction\Factory\SignData))
#2 /var/www/admin/corn/vendor/bitwasp/bitcoin/src/Transaction/Factory/Signer.php(164): BitWasp\Bitcoin\Transaction\Factory\InputSigner->extract()
#3 /var/www/admin/corn/1.php(47): BitWasp\Bitcoin\Transaction\Factory\Signer->input(0, O in /var/www/admin/corn/vendor/bitwasp/bitcoin/src/Script/FullyQualifiedScript.php on line 155

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

Hey, wait, you deleted all the SignData stuff? Why?

You were just meant to delete the line with ->p2sh() on it.

$signData = (new SignData())
->p2wsh($witnessScript);

@wartw
Copy link
Author

wartw commented Mar 9, 2020

<?php

require "vendor/autoload.php";

use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
use BitWasp\Bitcoin\Script\Interpreter\InterpreterInterface as I;
use BitWasp\Bitcoin\Script\ScriptFactory;
use BitWasp\Bitcoin\Transaction\Factory\Signer;
use BitWasp\Bitcoin\Transaction\Factory\TxBuilder;
use BitWasp\Bitcoin\Transaction\OutPoint;
use BitWasp\Bitcoin\Transaction\TransactionOutput;
use BitWasp\Buffertools\Buffer;
use BitWasp\Bitcoin\Transaction\Factory\SignData;
use BitWasp\Bitcoin\Script\WitnessScript;
use BitWasp\Bitcoin\Address\SegwitAddress;
use BitWasp\Bitcoin\Script\WitnessProgram;
use BitWasp\Bitcoin\Address\AddressCreator;

// Setup network and private key to segnet
$privKeyFactory = new PrivateKeyFactory;
$key = $privKeyFactory->fromWif("xxxxxx");//WIF

// Script is P2SH | P2WSH | P2PKH
$witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash()));


// move to p2wpkh
$dest = new SegwitAddress(WitnessProgram::v0($key->getPublicKey()->getPubKeyHash()));

// Utxo
$outpoint = new OutPoint(Buffer::hex('44fd3a365aa0dbc0ccbcd61421757df3221e1403ef14e8141bb6986571c9be7c', 32), 0);
$txOut = new TransactionOutput(10000, $witnessScript->getOutputScript());

// Move UTXO to pub-key-hash
$builder = (new TxBuilder())
    ->spendOutPoint($outpoint)
    ->payToAddress(9000, $dest);

// Sign the transaction

$signData = (new SignData())
    ->p2wsh($witnessScript);

$signer = new Signer($builder->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;

@wartw
Copy link
Author

wartw commented Mar 9, 2020

Works normally (Thank you for your help

@afk11
Copy link
Member

afk11 commented Mar 9, 2020

Yep, that looks right! Glad it worked.

@wartw
Copy link
Author

wartw commented Mar 9, 2020

@afk11 I have another question: Can the addresses generated by "addresstypes.php" not be the same?

@hussainSheikh123
Copy link

$oldTransactions = file_get_contents('https://blockchain.info/rawaddr/15716aoSwq1VuqZgxbTSEXg7XAknmRVmE7');
$oldTransactions = json_decode($oldTransactions, true);
$latestHash = $oldTransactions['txs'][0]['hash'];
$privKeyFactory = new BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
$key = $privKeyFactory->fromWif("xxxxx");
$witnessScript = new WitnessScript(ScriptFactory::scriptPubKey()->payToPubKeyHash($key->getPubKeyHash()));
$dest = new BitWasp\Bitcoin\Address\SegwitAddress(BitWasp\Bitcoin\Script\WitnessProgram::v0($key->getPublicKey()->getPubKeyHash()));
$outpoint = new BitWasp\Bitcoin\Transaction\OutPoint(BitWasp\Buffertools\Buffer::hex($latestHash, 32), 0);
$txOut = new TransactionOutput(10000, $witnessScript->getOutputScript());
$builder = (new BitWasp\Bitcoin\Transaction\Factory\TxBuilder())
->spendOutPoint($outpoint)
->payToAddress(9000, $dest);
$signData = (new SignData())
->p2wsh($witnessScript);
$signer = new Signer($builder->get(), Bitcoin::getEcAdapter());
$input = $signer->input(0, $txOut, $signData);
$input->sign($key);

$signed = $signer->get();


$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;

$apiUrl = 'https://blockchain.info/pushtx';
$postData = [
    'tx' => $signed->getBaseSerialization()->getHex(),
];
$ch = curl_init($apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
$response = curl_exec($ch);
if ($response === false) {
    die('Error: ' . curl_error($ch));
}
curl_close($ch);
$responseArray = json_decode($response, true);
if (isset($responseArray['status']) && $responseArray['status'] === 'success') {
    echo 'Transaction broadcasted successfully!';
} else {
    echo 'Error broadcasting transaction: ' . $response;
}

i used same code but my problem is not fixed I still same issue face
Script validation result: yay Witness serialized transaction: 01000000015d607272b9081dd7cf3e9251490d6bdee50521218c05ee02e438e9cf63e2636b0000000000ffffffff0128230000000000001600142d03144a1205adbb34a092a4a3f526ba9aaa95db00000000 Base serialized transaction: 01000000015d607272b9081dd7cf3e9251490d6bdee50521218c05ee02e438e9cf63e2636b0000000000ffffffff0128230000000000001600142d03144a1205adbb34a092a4a3f526ba9aaa95db00000000 Error broadcasting transaction: Code: -26, Error: non-mandatory-script-verify-flag (Witness program was passed an empty witness)

I stuck last 7 days

@hussainSheikh123
Copy link

Hey thomas please help me
Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants