bitcoin-php icon indicating copy to clipboard operation
bitcoin-php copied to clipboard

Spend from native segwit addresses

Open exfoex opened this issue 5 years ago • 1 comments

I'm trying to spend from a native segwit address. I modified an example code to this:

require_once "vendor/autoload.php";
use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
use BitWasp\Bitcoin\Script\Interpreter\InterpreterInterface as I;
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\Script\ScriptFactory;
use BitWasp\Bitcoin\Address\AddressCreator;

$privKeyFactory = new PrivateKeyFactory();
$privateKey = $privKeyFactory->fromWif("KzgdZ7XMryXCMDtx8fdg5Mw8J76w4CoB6DUhpuR1tfrJNfZrwRTp");

$addressCreator = new AddressCreator();
$sendToAddress = $addressCreator->fromString('1J8coKbxvxauTh6z4LdxsEtxR39cDA5iA1');

$outpoint = new OutPoint(Buffer::hex('e4a71be6d7c472680a9b22757e1b65ad478f42ba7f760e69d12923601a49b86c',32), 0);

$program = ScriptFactory::scriptPubKey()->p2wkh($privateKey->getPubKeyHash());

$txOut = new TransactionOutput(38000, $program);

$tx = (new TxBuilder())
    ->spendOutPoint($outpoint)
    ->payToAddress(38000, $sendToAddress)
    ->get();

$signer = new Signer($tx);
$input = $signer->input(0, $txOut);
$input->sign($privateKey);
$signed = $signer->get();

echo PHP_EOL;
echo "Witness serialized transaction: " . $signed->getHex() . PHP_EOL. PHP_EOL;
echo "Base serialized transaction: " . $signed->getBaseSerialization()->getHex() . PHP_EOL;
echo "txid: {$signed->getTxId()->getHex()}\n";
echo PHP_EOL;

The code gives this result:

Witness serialized transaction: 010000000001016cb8491a602329d1690e767fba428f47ad651b7e75229b0a6872c4d7e61ba7e40000000000ffffffff0170940000000000001976a914bbeaeee989eaba3161fa80a4a0aa78c84888dac488ac024830450221008b6531a8e579d2a0f0c67b6ac35455955fb6a3fe8db26e8933f5b69529b38bc10220289acd4e15dd4c90387e4da7a536cec0f2e59cd22722bd1e67e659323fa6f5840121020a5d6b7e449f8167628a4840cd5c26c38ab570f2c3117da025ca62e012da174100000000 Base serialized transaction: 01000000016cb8491a602329d1690e767fba428f47ad651b7e75229b0a6872c4d7e61ba7e40000000000ffffffff0170940000000000001976a914bbeaeee989eaba3161fa80a4a0aa78c84888dac488ac00000000 txid: 1e4fdd9b86c82818b0342fa29e0229b4dda603f19c6d74b0f7cc6d88fb4e4aba

And when I try to brodcast this transaction through https://live.blockcypher.com/btc/pushtx/ it says:

Error validating transaction: Error running script for input 0 referencing e4a71be6d7c472680a9b22757e1b65ad478f42ba7f760e69d12923601a49b86c at 0: Script was NOT verified successfully..

exfoex avatar Jun 14 '19 06:06 exfoex

I checked the outpoint you referenced, and it looks like the value is 39000 sat, not 38000 sat. Segwit signatures happen to cover this value, and so it must be correct for signatures to be valid. (It's a measure to protect hardware wallets from compromised host machines that lie about the input value to scalp fees)

afk11 avatar Jun 16 '19 08:06 afk11