Author

Topic: Bitcoin Protocol OP_RETURN + Omni USDT Tether + CoPay Multisig Help (Read 689 times)

newbie
Activity: 11
Merit: 0
haha well I have heard that CoPay is not supported anymore or whatever, I'm unsure because I was kind of new to Multisig in Bitcoin Cheesy irronically I'm quite experienced with the NEM blockchain.. where Multisig is completely different, where the blockchain is actually different ^^

I'm thankful for all this knowledge and have written a better readme file to the repository, adding some links to the recovery process and examples, etc. For anyone who will need to go through this process some day Tongue

I believe the tool can be used to recover any omni property balance stuck in CoPay Multisig with the tool Smiley

- Examples and Scenario explanation
- The php application omni:copay-recovery command

It was amazing to learn so much Smiley Thank you guys for all the details and for helping sorting this out Smiley

I have also successfully recovered the actual funds (not the reproduced case mentioned in this article) using the tool and I hope I will learn more about Bitcoin soon Smiley
newbie
Activity: 10
Merit: 0
Nice,

Glad you got it working, also being able to recover funds from a Copay wallet is definitely a nice option.
Now if we could just get an Omni Integration that worked natively with Copay  Cheesy
newbie
Activity: 11
Merit: 0
THOUSAND MILLION THANKS.

After some more debugging, My transaction got through!.

To explain the hurdles ... At first I tried to use an input I couldn't reproduce the redeem script for. Then I discovered that the wallet I need to recover is at m/44'/0'/0'/0/2 (second address with this multisig wallet - the *master* multisig HD for each cosigner being at m/44'/0'/0'.

Before I go in the details.... I have managed to move the funds to a new USDT address THANKS A LOT for the inputs !!!

So... On my journey today I encountered :

- Copay Cosigners are derived at m/44'/0'/0' from the BIP39 Seed of the mnemonic+passphrase.
- Each address generated with the copay client will use a different sub derivation path.
    - First Address: m/44'/0'/0'/0/0
    - Second Address: m/44'/0'/0'/0/1
    - Third Address: m/44'/0'/0'/0/02
    - and so on
- If you ever use a copay wallet as the change address the derivation path for those accounts is at m/44'/0'/0'/1/0.

The biggest hurdle was that I was using the input of a change address and didn't realize this. Now the transaction is broadcast, and even confirmed! And omniwallet.org tells me the funds moved Smiley

Here some links to the WELL DONE WORK!!!!

https://blockchain.info/tx/09d01daebfb08d9124ba442d8db5e9e11f9cdd29e799d471f7c37768148a4e9a?show_adv=true

https://www.omniwallet.org/explorer/inspector?view=09d01daebfb08d9124ba442d8db5e9e11f9cdd29e799d471f7c37768148a4e9a

Thanks a lot! Smiley
newbie
Activity: 10
Merit: 0
Yes it could be a missing signature, though i do see 2 signatures after decoding.

The other possibility is it could also mean the wrong signature (see https://bitcoin.stackexchange.com/questions/58176/what-does-16-mandatory-script-verify-flag-failed-non-canonical-der-signature)

Have you double checked the signing functionality/logic to ensure you're using the correct address in the chain?

Dexx any other thoughts?

newbie
Activity: 11
Merit: 0

* gevs thinks that I am very close to *it*. Please forgive my noobishness.

So, gathering back my inputs together and signing with the right keys again, I have been able to produce following transaction payload:

Code:
010000000139ccd23fba99b192acfc1b8bc00259408de9133a048f57ce23c44cbfd40a7a5101000000fdfd0000483045022100d6a8679e4ec1cb184e1cf4f2a139d17da0f18afde524613a6c6d6610b3f7ef2702207ebce807860ff1602c01d6372904afa218d46c8662585e64cb20113758912bed01473044022061c42d9ac42b1d37f62ebee90f8b87a0d4bf0e3878278c85082db1850dd0ab650220680e796af999f3523158e29225edd9f7f2ceff635136807e576424c59d01c878014c69522102109c754588a5e6de512a68b0e82fa8ed6520f5fd57f6b41315e3d3c2b8f92ac2210318e0167d697e9366f17c2e83ac21c7e66ecc9427884d083887c8d3b6aa3857d8210350bc7cb1f4632c42ad092b1b825beea81ad4a663fa1c365c95d09ff44a11f30353aeffffffff030000000000000000166a146f6d6e69000000000000001f000000002faf0800a8610000000000001976a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ace0150000000000001976a9146ad34cb4fa9d06c874f0a0974bb20f57309fb44c88ac00000000

Yet this time the error about 16: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element) is back.

Two Things about this error :

1) dexX7 mentioned it happens when there are missing signatures, i will check this of course but currently i think i sign with all the needed cosigners (2-of-3 as you will see in coin.bin in case you copy paste my payload).

2) When I add a "OP_EQUAL" at the end of the OP_RETURN sequence, The error will change to 64: scriptpubkey. This is also why last time I had re-added the OP_EQUAL at the end, because I thought it seems to fix my error... but maybe this is falsly guessed.

I hope I can get this to work Smiley I learned so much... and thank you for your patience too guys!
newbie
Activity: 11
Merit: 0
Thanks for the inputs both of you!

I'm making my way through it, I understood the input and output thing and that omni is actually not input/output based, so it made things much easier to understand ^^.

Sadly now I'm hurting a "Signing with the wrong private key" error which you guys can't help with, I must get my inputs organized again haha nightly debugging got me cursed i think.

I will come back with any non-answered question but there is already a lot of input in here to make this work. Crossing fingers Smiley
newbie
Activity: 10
Merit: 0
Changing the input should be fine as long as your script/setup takes into account the change in usable amount of btc for change/miner fee's etc .
The actual omni payload in the op_return shouldn't be affected by a change in inputs as long as they belong to the same address.
newbie
Activity: 11
Merit: 0
Hey there!

I must be something like Cursed Tongue So yes, I tried to double spend when i got this Missing inputs error... Because I did a test transaction from CoPay, which in fact spent the input i was using lol

soo.. trying to use a different input, now i'm a little stuck getting my parameters back together to produce a valid transaction payload.

I'm now using the input vout=1 in https://api.smartbit.com.au/v1/blockchain/tx/517a0ad4bf4cc423ce578f043a13e98d405902c08b1bfcac92b199ba3fd2cc39. Does this change something to my process ?

Quote
No need for the OP_EQUAL

I removed it and put it back in during debug.. Thanks for re-mentioning Smiley

I will have a look also at importing keys in omnicore directly. Thank you for the details.
legendary
Activity: 1106
Merit: 1026
Hi gevs,

just a few quick notes:

Quote
16: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)

IIRC this error pops up, if there are still signatures missing to satisfy the multisig script.

Quote
Missing inputs

Are all inputs still available or did you try to double spend one? Is your client completely synced, when you try to broadcast the transaction?

Quote
OP_RETURN 6f6d6e69000000000000001f000000002faf0800 OP_EQUAL

No need for the OP_EQUAL

Quote
Maybe I need a non-standard allowing node?

Omni transactions are standard. The only website still not considering OP_RETURN as standard script is blockchain.info. So be aware about this.

Here is a link to create simple send transactions with Omni Core:

https://github.com/OmniLayer/omnicore/wiki/Use-the-raw-transaction-API-to-create-a-Simple-Send-transaction

If you manage to follow these steps, you just have to figure out how to sign the transaction. To do so, you could probably import all keys into Omni/Bitcoin Core and then use `signrawtransaction`.
newbie
Activity: 11
Merit: 0
Hey there @shmali again.. So I have worked out a copy of your transaction with my php implementation,

- Omni CoPay USDT Recovery tool

And it seems i am now able to produce the right signed input!.

Next stop, when I try to broadcast the payload below, I get an error: Missing inputs.

Code:
0100000001cb0e9efba54a6acee3d8b09df2b9527ca05fb1c61b6f893ad5c8ee2cc4d6f54e00000000fdfe0000483045022100e74b44e77720559daea6568bd92382b0abe0af28b160b911e10cd175fe6942ef02204e87ee7721a61d34c4058e9518ad8a6615913d2ffc0c8778852c9f5a7a5ab9f801483045022100d071a38afcb42d296c65be0f693cc523d7b17ecac6085d13db139bbeeda81e0b02201ee360c89387c18ee24438b7bbc617473c2c51b69cea36ac867140f62204de7b014c69522102109c754588a5e6de512a68b0e82fa8ed6520f5fd57f6b41315e3d3c2b8f92ac2210318e0167d697e9366f17c2e83ac21c7e66ecc9427884d083887c8d3b6aa3857d8210350bc7cb1f4632c42ad092b1b825beea81ad4a663fa1c365c95d09ff44a11f30353aeffffffff030000000000000000166a146f6d6e69000000000000001f000000002faf080050c30000000000001976a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ace0150000000000001976a9146ad34cb4fa9d06c874f0a0974bb20f57309fb44c88ac00000000

You will see it now display 2 of 3 multisig (that's what it should be.) I have been able to reproduce the exact same hash as the redeemScript of my input displays.

Any idea where this error comes from? Smiley Maybe I need a non-standard allowing node? I tried with elligius but still getting "Response = 0", and standard pushtx API is which gives me the "Missing inputs" error.

Thanks for the details, you helped a lot already!!!
newbie
Activity: 11
Merit: 0
Next, The sender is determined by the first input in the tx. So you can fund the tx from several address if needed, however only the first input in the tx will signal to the Omni protocol who is sending the Omni Assets.

The receiver is chosen/indicated by the last output address that is not the sender. So if you want to send any extra btc change back to yourself or to a different address specify those first.
Signaling The receiver address only needs a fraction of btc,  right now we're using 0.00005460 btc as that 'reference output amount'.

I found something relating to this in the code just yesterday - thank you for breaking it down in details!

I will give a try to simply sign the payload you provided. Thank you!

A few more tools/resources that may be of use.

Bitcoin Scripting in general: https://en.bitcoin.it/wiki/Script

One of the Omni Dev's put together this interface for payload creations and commands to use with the Omnicore client: http://builder.bitwatch.co/

And then here is gist that shows how to use the omnicore client to manually create a tx with payload: https://gist.github.com/dexX7/352670c990ebf9ea31d6346a1519eb52

Amazing Thank you for that builder, I didn't find it Smiley
newbie
Activity: 10
Merit: 0
A few more tools/resources that may be of use.

Bitcoin Scripting in general: https://en.bitcoin.it/wiki/Script

One of the Omni Dev's put together this interface for payload creations and commands to use with the Omnicore client: http://builder.bitwatch.co/

And then here is gist that shows how to use the omnicore client to manually create a tx with payload: https://gist.github.com/dexX7/352670c990ebf9ea31d6346a1519eb52
newbie
Activity: 10
Merit: 0
I can provide some insight though i've pinged one of the omnicore dev's to assist with some of the more base line bitcoin protocol details.
For full details on the Omni protocol spec please see: https://github.com/OmniLayer/spec

While all transactions on the OmniProtocol are sent over the Bitcoin network there are a few general rules on the structure of an Omni protocol transaction (and thus a tether send transaction) :

First since it is on the bitcoin network, it will have to be a valid bitcoin tx at the end of the day. So miners fee's signing inputs/outputs etc.. all have to comply with a normal tx.

Next, The sender is determined by the first input in the tx. So you can fund the tx from several address if needed, however only the first input in the tx will signal to the Omni protocol who is sending the Omni Assets.

The receiver is chosen/indicated by the last output address that is not the sender. So if you want to send any extra btc change back to yourself or to a different address specify those first.
Signaling The receiver address only needs a fraction of btc,  right now we're using 0.00005460 btc as that 'reference output amount'.

Finally the guts and glory of an Omni Protocol transaction, the data packet encoded into OP_RETURN.
This is a hex encoded payload that has a few different components.
From your example above you already have the ASM OP_RETURN 6f6d6e69000000000000001f000000002faf0800 OP_EQUAL

If we break it down we get:
Bitcoin protocol:
 OP_RETURN  opcode/operation

Omni protocol (hex encoded values):
 6f6d6e69 -  string 'omni' used to indicate/mark the tx is for the omni protocol to Omni software
 0000 - Next 4 bytes indicate the Transaction version, at present simple send is version 0
 0000 - next 4 bytes indicate transaction type, simple send is type 0
 0000001f - Next 8 bytes, are used to represent the token property id of tokens being acted upon, In this case Tether is Property id 31, 1f in hex
 000000002faf0800 - Next 16 bytes are used to indicate the number of tokens being sent as a whole number.
  Note: The omni protocol has 2 concepts for tokens, Divisible like bitcoin, fractional amounts. And not indivisible, smallest unit represented is 1, no fractional amounts. When encoding
  amounts for the payload divisible amounts are converted to whole number representations (multiple by 1e8). Since Tether is a divisible property, sending an amount of 8, you would
  hex encoded 800000000 * 8 *  1e8)

Bitcoin protocol :
 OP_EQUAL -  You actually do not want this, remove it. THE OP_RETURN is a data payload, not actually an addresses.

A few more notes/things to understand.
The Omni Protocol is not Input/Output based. I.e. the output of a 8 tether send is not needed/relevant when sending 8 Tethers later on.
The Omni Protocol is basically a state machine, where every transaction you send is just an instruction that state machine uses to update a balance or process a request.
So when you send 8 Tether, you are basically sending the instructions to the Omni protocol that say, transfer 8 Tether from address X to address Y.
If all the validation/security/tx checking are verified then the software processes the request and balances are updated/funds are moved.

I've updated your tx (without signatures) to show what the 8 Tether simple send would look like using only the 1 input (minimize tx size)
Code:
0100000001cb0e9efba54a6acee3d8b09df2b9527ca05fb1c61b6f893ad5c8ee2cc4d6f54e00000000b500483045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53aeffffffff030000000000000000176a156f6d6e69000000000000001f000000002faf080087a0860100000000001976a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ac54150000000000001976a914f40da014c137ad88006608834887556944e2dfeb88ac00000000


and if we decode it to show both the BTC and OMNI decode info we get

Code:
{
  "BTC": {
    "hash": "fbe3b32419117a95e0983bf930a1d2b285e3c8a8a6af082c59d24e7e47fc354a",
    "locktime": 0,
    "size": 332,
    "txid": "fbe3b32419117a95e0983bf930a1d2b285e3c8a8a6af082c59d24e7e47fc354a",
    "version": 1,
    "vin": [
      {
        "scriptSig": {
          "asm": "0 3045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876[ALL] 51210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae",
          "hex": "00483045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae"
        },
        "sequence": 4294967295,
        "txid": "4ef5d6c42ceec8d53a896f1bc6b15fa07c52b9f29db0d8e3ce6a4aa5fb9e0ecb",
        "vout": 0
      }
    ],
    "vout": [
      {
        "n": 0,
        "scriptPubKey": {
          "asm": "OP_RETURN 6f6d6e69000000000000001f000000002faf080087",
          "hex": "6a156f6d6e69000000000000001f000000002faf080087",
          "type": "nulldata"
        },
        "value": 0.0
      },
      {
        "n": 1,
        "scriptPubKey": {
          "addresses": [
            "143f5QPkc5mJurEr2kGPPoecJqkhvaQ2u2"
          ],
          "asm": "OP_DUP OP_HASH160 2168fe52d8c1cbc656a544859c4193dd4b92e237 OP_EQUALVERIFY OP_CHECKSIG",
          "hex": "76a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ac",
          "reqSigs": 1,
          "type": "pubkeyhash"
        },
        "value": 0.001
      },
      {
        "n": 2,
        "scriptPubKey": {
          "addresses": [
            "1PFSCWbPdfQfwtRidBxj5x2HxigG7JGFNb"
          ],
          "asm": "OP_DUP OP_HASH160 f40da014c137ad88006608834887556944e2dfeb OP_EQUALVERIFY OP_CHECKSIG",
          "hex": "76a914f40da014c137ad88006608834887556944e2dfeb88ac",
          "reqSigs": 1,
          "type": "pubkeyhash"
        },
        "value": 5.46e-05
      }
    ],
    "vsize": 332
  },
  "OMNI": {
    "amount": "8.00000000",
    "confirmations": 0,
    "divisible": true,
    "fee": "0.00094540",
    "ismine": false,
    "propertyid": 31,
    "referenceaddress": "1PFSCWbPdfQfwtRidBxj5x2HxigG7JGFNb",
    "sendingaddress": "3B2d4gAe51A6yEPG9qAxRfKxdVA1Zfpq9R",
    "txid": "fbe3b32419117a95e0983bf930a1d2b285e3c8a8a6af082c59d24e7e47fc354a",
    "type": "Simple Send",
    "type_int": 0,
    "version": 0
  }  
}

If you were to sign this tx with the required number of signatures it would be valid to send.


newbie
Activity: 11
Merit: 0
Finally one more update! Now It seems that I have located a missing OP_EQUAL at the end of my OP_RETURN output script.

This now brings me to a next error message: "64: scriptpubkey". I am now documenting myself on this error, maybe I will find something related to OP_RETURNs about this.

Here is the latest Transaction Bytes Data I have been trying to Push:

Code:
0100000002515b4e1ebff9fb500ecb1d94b184042b9d3d580829eee288b55fa4006534419101000000b500483045022100a4c41919ca7b9f5371f6dc90b8064defc03c89b6c938f04928cedcb60b1d6f4002207620c409448bfe88d78fb0ecb970c3986e01325b39b68460a94406c8f6b55797014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53aeffffffffcb0e9efba54a6acee3d8b09df2b9527ca05fb1c61b6f893ad5c8ee2cc4d6f54e00000000b500483045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53aeffffffff030000000000000000176a146f6d6e69000000000000001f000000002faf080087c4090000000000001976a914f40da014c137ad88006608834887556944e2dfeb88acf0490200000000001976a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ac00000000

It's a 554 Bytes transaction which translates to the following JSON:

Code:
{
    "success": true,
    "transaction": {
        "Version": "1",
        "LockTime": "0",
        "Vin": [
            {
                "TxId": "9141346500a45fb588e2ee2908583d9d2b0484b1941dcb0e50fbf9bf1e4e5b51",
                "Vout": "1",
                "ScriptSig": {
                    "Asm": "0 3045022100a4c41919ca7b9f5371f6dc90b8064defc03c89b6c938f04928cedcb60b1d6f4002207620c409448bfe88d78fb0ecb970c3986e01325b39b68460a94406c8f6b55797[ALL] 51210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae",
                    "Hex": "00483045022100a4c41919ca7b9f5371f6dc90b8064defc03c89b6c938f04928cedcb60b1d6f4002207620c409448bfe88d78fb0ecb970c3986e01325b39b68460a94406c8f6b55797014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae"
                },
                "CoinBase": null,
                "TxInWitness": null,
                "Sequence": "4294967295"
            },
            {
                "TxId": "4ef5d6c42ceec8d53a896f1bc6b15fa07c52b9f29db0d8e3ce6a4aa5fb9e0ecb",
                "Vout": "0",
                "ScriptSig": {
                    "Asm": "0 3045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876[ALL] 51210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae",
                    "Hex": "00483045022100d7845a9e0e854d675451863027eefaa7b01d5ae87ee700c3b40012e2c94a30760220053e223dca51f234887226871cbbe94678913ab8b96c60edff8e454a2efc4876014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53ae"
                },
                "CoinBase": null,
                "TxInWitness": null,
                "Sequence": "4294967295"
            }
        ],
        "Vout": [
            {
                "Value": 0,
                "N": 0,
                "ScriptPubKey": {
                    "Asm": "OP_RETURN 6f6d6e69000000000000001f000000002faf0800 OP_EQUAL",
                    "Hex": "6a146f6d6e69000000000000001f000000002faf080087",
                    "ReqSigs": 0,
                    "Type": "nonstandard",
                    "Addresses": null
                }
            },
            {
                "Value": 0.000025,
                "N": 1,
                "ScriptPubKey": {
                    "Asm": "OP_DUP OP_HASH160 f40da014c137ad88006608834887556944e2dfeb OP_EQUALVERIFY OP_CHECKSIG",
                    "Hex": "76a914f40da014c137ad88006608834887556944e2dfeb88ac",
                    "ReqSigs": 1,
                    "Type": "pubkeyhash",
                    "Addresses": [
                        "1PFSCWbPdfQfwtRidBxj5x2HxigG7JGFNb"
                    ]
                }
            },
            {
                "Value": 0.0015,
                "N": 2,
                "ScriptPubKey": {
                    "Asm": "OP_DUP OP_HASH160 2168fe52d8c1cbc656a544859c4193dd4b92e237 OP_EQUALVERIFY OP_CHECKSIG",
                    "Hex": "76a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ac",
                    "ReqSigs": 1,
                    "Type": "pubkeyhash",
                    "Addresses": [
                        "143f5QPkc5mJurEr2kGPPoecJqkhvaQ2u2"
                    ]
                }
            }
        ],
        "TxId": "fb756851da8832f85696c3e4b56de16706ccc623d9993f70a070d7292b878e9d"
    }
}

The first few searches on forums made me try to use Elligius Miner PushTX API at the following URL: http://eligius.st/~wizkid057/newstats/pushtxn.php

This API seems to respond with "Response = 0" though and I get no error message from them. When I use Smartbit API as I used before, I get the error message mentioned above "64: scriptpubkey".

Any help appreciated! Smiley
newbie
Activity: 11
Merit: 0
Hello all!

I have been asked to recover some tether that have been sent to the wrong address... Sitting on the blockchain in a multisig copay account.

I have written small php command line tools to reproduce the case and learn more about how Bitcoin works. I am a software developer working mostly with NEM where the blockchain is very different. Ok, so all that gives me is enthusiasm and passion when it comes to blockchains, lots of hours passed... and I have learned a lot about multisig on Bitcoin, OP_RETURNs used in omni (usdt being a smartproperty on the omni layer), and many more awesome things about hierarchical key generation, key derivation functions, and many more subjects.

But I struggle getting back those tether to another address Sad Of course, I own the 3 cosigners configured with copay, but I am too much of a noob to get those tether back. Fact is, the NEM blockchain is very different when it comes to multisig and custom assets. So I went through the learning process for HD keys and XPRV and XPUBs. Which I also built a command for. A command that, provided with the right derivation path and xpubs or mnemonics, will generate the same cosigners xpubs as copay displays in the multisig wallet information page.

I also built a command that, out of XPUBs, will display a *redeemScript* for the given derivation path as well as the scriptPubKey of the derived account (copay uses m/44'/0'/0' for your main accounts (the cosigners) but uses m/0/x  where x is the addresses counter, for generating payment addresses.

I am able to reproduce exactly the same OP_HASH160 THE_HASH OP_EQUAL.  And i am referring to a valid bitcoin transaction's output in my transactions inputs.

I have 2 inputs (both multisig output scripts generated with the bitcoin php lib from Bit-Wasp), the first input contains the tether OP_RETURN along with a OP_HASH160 multisig verification. The second input contains enough BTC to pay the miner fee (0.002 BTC for 487 Bytes transaction) and also has a OP_HASH160 multisig verification.

So both my generated inputs are equal to the scriptPubKey that I am able to generate with my HD derivation tool. The redeemScript generated by this tool tells me the order of cosignatories (lexicographically ordeded public keys) and the path for copay multisig addresses are xpub/0/1 xpub/0/2, etc. where xpub is the xpubs of cosigners which are generated with the derivation path m/44'/0'/0'. So the absolute path to the generated addresses are: m/44'/0'/0'/0/1, next address would be m/44'/0'/0'/0/2, etc.

Great, I have learned so much about key derivation and how multisig is represented on Bitcoin!!!

Yet now the real fun happens.. How to get this OP_RETURN statement to be reproduced on a tether address? Turns out they are always bitcoin addresses.

So I thought I need 2 outputs, same as what happened to the tether originally, I would reproduce by sending the bundle to a omniwallet address.

Here comes my problem.. I don't really understand the omni transaction fully. I have converted the hash into a suit of big endian numbers (also working for little endian and machine byte order code so.. maybe i pick the wrong).

But from my understanding of the redeemScript and scriptPubKey, I have to reproduce the OP_RETURN hash with in my output, or is it right to only copy it into a new sequence of opcodes?. Thats what I did now, so one of my output specifies the exact same OP_RETURN xxxx as the Bitcoin input transaction I am referring to and a value of 0. In the second output which is a payToAddress with the omni address, I put a 0.0005 btc amount which will leave 0.0015 btc for the fee. Transaction is 487 bytes big.

So I am unsure here.. I have gone through a few errors coming from a pushtx API, the error i am stuck on now is 16: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)

Ok, this error is really not the worse I have seen, its very explicit.. and thats what I need help with. I need to know how to read the omniwallet Op_Return data correctly so that the script is evaluated correctly, or is it something else that I am missing?

I am able to provide with screenshots, and unsigned transaction data and will do so, but I need a little input first, maybe my mistake is obvious to experts of the Bitcoin network.

I have reproduced this case on an address with not a lot of money and will provide with screenshots and source code in the morning.

Please people, I love blockchains and I have yet to learn about cryptography. I have coded a lot around the NEM blockchain for my personal progress and professional abilities and I really enjoy the Bitcoin scene as a software developer. It is a very entertaining community, we have to say too Smiley

Thank you for reading and I hope someone can help me out!

Sources Codes & Screenshots

    1) BIP32+44 HD Addresses Generation Tool on Github
  
    2) BIP39 Seed Derivation (get Private Keys) on Github

    3) My P2SH Colored Transaction creation on Github

    4) SCREENSHOT OF THE ERROR

    5) OP_RETURN hexadecimal payload reading (All it does it read Integer values, please tell me there is more behind)

With those source codes, passing the right parameters as explained below, I am able to produce the transaction that I will add to a screenshot below. Sadly the Transaction is rejected with the message specified above and also displayed in the screenshot. I don't think the problem lies in the smartbit API I am using, this is only a quick broadcast tool I integrated to my script.

Code:
$ php application wallet:p2sh-colored \
            --colored-tx "9141346500a45fb588e2ee2908583d9d2b0484b1941dcb0e50fbf9bf1e4e5b51" \
            --btc-input-tx "4ef5d6c42ceec8d53a896f1bc6b15fa07c52b9f29db0d8e3ce6a4aa5fb9e0ecb" \
            --path="m/44'/0'/0'"  \
            --min 1 --cosig1="this is not the right mnemonic" \
            --cosig2="this one isn't either" \
            --cosig3="and of course, nor is this one" \
            --destination "1PFSCWbPdfQfwtRidBxj5x2HxigG7JGFNb" \
            --change "143f5QPkc5mJurEr2kGPPoecJqkhvaQ2u2" \
            --bitcoin 200000

Another *insurances* I get from calling the following command:

Code:
$ php application wallet:hd-from-xpub --xpubs="my_cosigner_lists_xpubs,separated_by_comma,very_basic" --path="m/0"

This command just above will return the following scriptPubKey: OP_HASH160 d7fb889271798a9244f47320aec28b926a2bb7a4 OP_EQUAL - as well as a redeemScript containing the lexicographically ordered Public Keys of the cosigners of the copay account. So, as you can see when checking the screenshot from the transaction creation, this d7fb8... is exactly what I am able to reproduce when I have signed the inputs. Now I am asking myself where the problem could be and hope all those details can help you people more for helping me! Smiley

Here is the Transaction bytes data to be copy/pasted into coin.bin for example:

Code:
0100000002515b4e1ebff9fb500ecb1d94b184042b9d3d580829eee288b55fa4006534419101000000b4004730440220533476590d6f978491499559c34916a4318c36ff6656f00449ba8bc41c4c1b47022007e8fc60706abcc0d1523f3bc0e5768cc4a32fd3774eb69d8621527ad15d340e014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53aeffffffffcb0e9efba54a6acee3d8b09df2b9527ca05fb1c61b6f893ad5c8ee2cc4d6f54e00000000b4004730440220787016c5ad971514fd925b7407230430d365242a679e7237d492101a7b1c31d5022055098842dc35764b498ab4633fad4b9da929f00a34a07aa5e8dfd3b9e5b760d8014c6951210247bcd2c9e1bf8bfc9e567c8f9c81ef5f2c5356e544ab7b9141b7ef93f272da9f2102771dbfd6b9e6183e893c07ea49cfc781d1836e42b6425ff2a59100cc2e9b11222102ab0456bde3a2a8f5066fa4827c8a00c9388e6da1fdc22f90c406d89112c8bacb53aeffffffff030000000000000000166a146f6d6e69000000000000001f000000002faf0800c4090000000000001976a914f40da014c137ad88006608834887556944e2dfeb88acf0490200000000001976a9142168fe52d8c1cbc656a544859c4193dd4b92e23788ac00000000

I think my problem lies in the OP_RETURN output because all I did is copy it from the input transaction and I am unsure If I have to solve the script or whatever. I would appreciate any help from people knowing our OP_RETURN could work in my case of a Copay Multisig (which I seem to be reproducing fine)

For people who didn't click the screenshot, here is the *var_dump()* output of my transaction content after signing, this is similar to what *coin.bin* will display for the transaction bytes data above.

Code:
array (
  'version' => 1,
  'inputs' =>
    array (
      0 => 'OP_HASH160 d7fb889271798a9244f47320aec28b926a2bb7a4 OP_EQUAL',
      1 => 'OP_HASH160 d7fb889271798a9244f47320aec28b926a2bb7a4 OP_EQUAL',
    ),
  'outputs' =>
    array (
      0 =>
        array (
          'value' => 0,
          'script' => 'OP_RETURN 6f6d6e69000000000000001f000000002faf0800',
         ),
      1 =>
        array (
          'value' => 2500,
          'script' => 'OP_DUP OP_HASH160 f40da014c137ad88006608834887556944e2dfeb OP_EQUALVERIFY OP_CHECKSIG',
        ),
      2 =>
        array (
          'value' => 150000,
          'script' => 'OP_DUP OP_HASH160 2168fe52d8c1cbc656a544859c4193dd4b92e237 OP_EQUALVERIFY OP_CHECKSIG',
        ),
    ),
)

And the error when I broadcast this transaction:

Code:
array (
  'success' => false,
  'error' =>
    array (
      'code' => 'REQ_ERROR',
      'message' => '16: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)',
    ),
)

This API response is from the Smartbit API at: https://www.smartbit.com.au/api  which lets you push transactions quickly with POST requests. This message seems to be a bitcoin scripting error and that's why I am pretty sure I missed something!

Have a nice day.
Greg

[EDIT 1]: Added some phpbb formatting to replace MD.
[EDIT 2]: Changed title to reflect content.
[EDIT 3]: Add Transaction creation Screenshots + Source codes
[EDIT 4]: Added `script:op-return` github source link
Jump to: