Author

Topic: OP_RETURN <DATA> (Read 1635 times)

newbie
Activity: 3
Merit: 0
March 26, 2014, 05:00:01 AM
#4
You might find this site helpful for debugging:

http://coinsecrets.org/

Gideon
newbie
Activity: 19
Merit: 0
January 16, 2014, 07:27:35 AM
#3
Length is fine, I just had some confusion about what *exactly* was considered Standard by the reference client. I searched for a while to find any topics discussing the exact bytes in the scriptPubKey and couldn't find anything. So hopefully this helps anyone going through the same process.

99% of the time, OP_RETURN scriptPubKey will be (in hex):

  6a

If you need 76 - 78 bytes of data... add an OP_PUSHDATA1 (0x4c)

  6a 4c
legendary
Activity: 1526
Merit: 1129
January 16, 2014, 06:27:17 AM
#2
The goal was to allow a hash or two to fit, I think.
newbie
Activity: 19
Merit: 0
January 16, 2014, 06:12:48 AM
#1
While implementing the sample code for reusable addresses, I had to implement this line:

    stealthTx.Vout.Add(TxOut.OpReturn(P));

Generally the OP_RETURN support is talked about as "OP_RETURN " but sometimes it's also described as OP_RETURN followed by anything.

So my question was whether or not you have to pack the data inside an OP_PUSHDATA, e.g.

    public static TxOut OpReturn(byte[] data)
    {
        byte[] scriptRaw = new byte[data.Length + 1];
        scriptRaw[0] = (byte)Script.OpCode.OP_RETURN;
        scriptRaw[1] = (byte)Script.OpCode.OP_PUSHDATA1;
        scriptRaw[2] = (byte)data.Length;
        Array.Copy(data, 0, scriptRaw, 3, data.Length);

        return new TxOut()
        {
            Value = 0L,
            ScriptPubKey = Script.Parse(scriptRaw)
        };
    }

Note, I could save a byte there if data was between 1 and 75 bytes... and the function as written assumes data is less than 255 bytes, but I'm trying to keep the example simple.

In practice, if I did *not* pack the data, then I get something like this from 'decoderawtransaction':

{
   "value" : 0.00000000,
   "n" : 1,
   "scriptPubKey" : {
   "asm" : "OP_RETURN -30205 OP_UNKNOWN OP_UNKNOWN OP_NOP6 OP_UNKNOWN [error]",
   "hex" : "6a02fdf5c5e6b5d3419e42cc0e12a53b3bd42795a2bdd937739e5eb6eca5cf542206",
   "type" : "nonstandard"
}

And so in the test transactions I sent, I did pack the data inside OP_PUSHDATA1.

I did find an Issue #3313 - 'OP_RETURN is now standard':

  https://github.com/bitcoin/bitcoin/issues/3313

Reading the discussion it still wasn't really clear to me, no one really seems to come out and say that actually the code as-is does NOT allow ....

Looking at the actual Solver() code...

   mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));

It eventually becomes clear that OP_SMALLDATA (not really an OP) will allow a single block of data appropriately wrapped in a PUSHDATA (not necessarily PUSHDATA1, I don't think we force 'most efficient' encoding yet).

And so the following code in Solver()...

  else if (opcode2 == OP_SMALLDATA)
  {
    // small pushdata, <= 80 bytes
    if (vch1.size() > 80)
       break;
    }
  }

I think that allows up to 78 bytes of actual data payload in an OP_RETURN output.

Since you can PUSH up to 75 bytes with a single OP code, and pushing 76-78 bytes requires OP_PUSHDATA1 . Making the cutoff 80 bytes seems like a funny number, I would have gone with a cutoff at 77 -- which would discourage OP_PUSHDATA1/2/4.

Or to be even more explicit... require OP_RETURN (0x6a) followed by either nothing, or followed by a single byte 1 - 75 (0x01 - 0x4b) indicating length and the specified amount of data.
Jump to: