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

Creating transaction for Bitcoin Cash #609

Closed
Vasiliy-Bondarenko opened this issue Jan 16, 2018 · 9 comments
Closed

Creating transaction for Bitcoin Cash #609

Vasiliy-Bondarenko opened this issue Jan 16, 2018 · 9 comments
Labels

Comments

@Vasiliy-Bondarenko
Copy link
Contributor

Hello.

I'm constructing transaction for Bitcoin Cash using this example
But when i try to broadcast it, I get an error:

error code: -26
error message:
16: mandatory-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation)

What's wrong? How to debug it?

Transaction in hex:

0100000001367ff84870b1511912cbe18c66dd72e15585f402a47bfb89abd3a743ca9a665c000000006b483045022100f64eff52538c376c0316c525f75ef1d68486c77542c68d53fe52d5bc06c9c67c0220513033f3315175a898cab7a2e0a39a89a2d61016e4c0c81d08b7430567a7cebd01210335bc2d792f974a4e8952b93e0ee1e6b84e93c662f97bec9566265664763f64b10100000001071b0000000000001976a914eb5808ea4850a18bd03a933e92a2ac5c7873020188ac00000000
@Vasiliy-Bondarenko
Copy link
Contributor Author

i use this network:

class NetworkFactory extends \BitWasp\Bitcoin\Network\NetworkFactory
{
    /**
     * @return NetworkInterface
     * @throws \Exception
     */
    public static function bitcoinCash(): NetworkInterface
    {
        return self::create('00', '05', '80')
                   ->setHDPubByte('0488b21e')
                   ->setHDPrivByte('0488ade4')
                   ->setNetMagicBytes('d9b4bef9')
                // ->setSegwitBech32Prefix("bc") # this needs to be removed to safely use bitcoin cash
            ;
    }
}

@afk11
Copy link
Member

afk11 commented Jan 16, 2018

My first guess is that you used the wrong txOut because when signed the public key doesn't match the pubKeyHash in the script:
DUP HASH160 [hash] EQUALVERIFY CHECKSIG

Double check that the txout script you are using is the correct one for that txid,vout. The signer will detect if you are signing a pubKeyHash script with the wrong key. maybe it's the right key for the scriptPubKey, but you are using the wrong scriptPubKey for that output?

Btw here's an example, you have to tell the Signer it's redeeming bitcoin cash (not mentioned in docs)
https://github.com/Bit-Wasp/bitcoin-php/blob/master/tests/Transaction/Factory/SignerTest.php#L399

@afk11 afk11 added the question label Jan 16, 2018
@Vasiliy-Bondarenko
Copy link
Contributor Author

Ok. Getting there...
I'm trying to rewrite the code using the test as an example.

public function redeemBitcoinCash()
- this method has different signature in current release then in master branch. Which one is correct? :)

@Vasiliy-Bondarenko
Copy link
Contributor Author

Thanks for the help, but still not working... :) Even with the code from the test you mentioned.
Below in the code it's real address and it's wif.
I'm working on last 0.0.34.2 release.
I get the same error as before then i broadcasting generated transaction.

Transaction https://blockdozer.com/insight/address/1APR9o8f7fnSKB3WsQ792xcHdhNEPt79Lo
I need to spend from n=1 address 1APR9o8f7fnSKB3WsQ792xcHdhNEPt79Lo

       $network = NetworkFactory::bitcoinCash();

        $wif = "L1X77tAPT3YtTrvXKoQE6zuFD4JKg8x2zpVAoh1Zx8awmtfv8w1w";

        $keyPair = PrivateKeyFactory::fromWif($wif, null, $network);

        $value = 7205;
        $txid = "35d5d41aa012f76ca9faa4696af94a8bf417be7735ae269142927b3b349281e9";
        $vout = 1;
        $spk = ScriptFactory::scriptPubKey()->payToPubKey($keyPair->getPublicKey());

        $dest = AddressFactory::fromString("1NTPFr8MhALzHDKJ9xs8oxPyANLb1hBzJT", $network)->getScriptPubKey();
        $txb = (new TxBuilder())
            ->version(2)
            ->input($txid, $vout)
            ->output($value, $dest)
        ;
        $txs = new Signer($txb->get());
        $txs->redeemBitcoinCash(true);
        $hashType = SigHash::BITCOINCASH | SigHash::ALL;
        $input = $txs->input(0, new TransactionOutput($value, $spk));
        $input->sign($keyPair, $hashType);
        $tx = $txs->get();

        var_dump($tx->getHex());
        exit;

outputs:

0200000001e98192343b7b92429126ae3577be17f48b4af96a69a4faa96cf712a01ad4d5350100000049483045022100b4e68844ff37e00da389bd22496a1c3ae3a6daa3f1182c333a062ad68f56a248022005c42361a3a81809ee158dafddf1fdd5307c268ab8e2841d2e9742dc658bec6941ffffffff01251c0000000000001976a914eb5808ea4850a18bd03a933e92a2ac5c7873020188ac00000000

I'm lost... :)

@Vasiliy-Bondarenko
Copy link
Contributor Author

Vasiliy-Bondarenko commented Jan 17, 2018

looks i solved the issue with hash by modifying script like this:

$spk = ScriptFactory::scriptPubKey()->payToPubKeyHash($keyPair->getPublicKey()->getPubKeyHash());

no i've come to the next error... the code looks like:

        $network = NetworkFactory::bitcoinCash();

        $wif = "L3xeChXH329KhyppGkpHtDJFV7j4dr7uA5GZ9cg1FREf2aopzqzB";

        $keyPair = PrivateKeyFactory::fromWif($wif, null, $network);

        $value = 7205;
        $txid = "35d5d41aa012f76ca9faa4696af94a8bf417be7735ae269142927b3b349281e9";
        $vout = 1;
        $spk = ScriptFactory::scriptPubKey()->payToPubKeyHash($keyPair->getPublicKey()->getPubKeyHash());

        $dest = AddressFactory::fromString("1NTPFr8MhALzHDKJ9xs8oxPyANLb1hBzJT", $network)->getScriptPubKey();

        $txb = (new TxBuilder())
            ->version(2)
            ->input($txid, $vout)
            ->output($value, $dest);

        $txs = new Signer($txb->get());
        $txs->redeemBitcoinCash(true);

        $hashType = SigHash::BITCOINCASH | SigHash::ALL;

        $input = $txs->input(0, new TransactionOutput($value, $spk));
        $input->sign($keyPair, $hashType);

        $tx = $txs->get();

        var_dump($tx->getHex());
        exit;

outputs:

0200000001e98192343b7b92429126ae3577be17f48b4af96a69a4faa96cf712a01ad4d535010000006a47304402201eb46e2605495fc59bd5811c8e2e20adc8e73d5235e87ad5bad3efd9aeacc1ee0220166607e7ad9aa74306e91ddad4b51fd85df6091440eace104a2d35d8077961bf41210245378ef9f3d4761ec934f044e85dcce0ab19cb1b244c794d32032de5dd523dc5ffffffff01251c0000000000001976a914eb5808ea4850a18bd03a933e92a2ac5c7873020188ac00000000

and errors out while broadcasting with:

16: mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)

@Vasiliy-Bondarenko
Copy link
Contributor Author

Problem resolved. My fault. I had an error with keys for derived addresses.
Thanks for the help.

@afk11
Copy link
Member

afk11 commented Jan 26, 2018

Sorry, was offline this week! Glad to see you got the problem sorted! Generally you should just derive and save the scriptpubkey & address (+ redeem/witness scripts) in a database. It's implied that before you received payment, you took a private key, derived the public key and scriptPubKey and address. Saving those, and then finding the txid/vout/value is normally the way to go.

If you have just address you received funds on, you can decode it and use getScriptPubKey()

@Vasiliy-Bondarenko
Copy link
Contributor Author

i'm saving only address and sequence number in DB. so i can track blocks for my addresses and recover all i need to spend transaction using sequence number from master private key. is it ok? or i can have a problem down the road?

@afk11
Copy link
Member

afk11 commented Jan 28, 2018

Cool That's fine - AddressFactory::fromString($addr)->getScriptPubKey(); will give it back to you in the most direct way when you want to sign!

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

No branches or pull requests

2 participants