Subject: [bitcoin-dev] [Pre-BIP] Motivating Address type for OP_RETURN

From: Jeremy <[email-masked]>
Date: Tue, 20 Apr 2021 08:46:07 -0700

Hi All,

Introducing the notion that we might want to have an address type defined
for OP_RETURN.

I came across this when writing some code that wanted to handle common
classes of user transactions generically, it's kind of annoying that you
have to write code that's effectively:

```
try {
   print(script.address());
} catch {
   try {
       print(script.op_return());
   } catch {
      print("unknown thing");
   }
}
```

I think that OP_RETURN, being relatively well defined, could have an
address type.

This would aid in simplifying types for programs. E.g., in Rust I want to
have:

```
struct Coin(Address, Amount)
impl Coin {
  fn get_coin(o: Outpoint) -> Result<Coin, Error>{/**/}
}
enum Error {
  UnknownType,
  CoinDoesNotExist,
}
```

and without Address defining OP_RETURN I can't read a Coin containing an
OP_RETURN. It would be possible to define Coin to store script, but then
everywhere I want an address I would have to perform a conversion and
Script is technically "too wide" a type as what I really want is to only
return coins with known output types.

More concretely this is a challenge for me as I'm building the Sapio
compiler and I want to make it so that all contract compilations result in
an Address, but I need to support OP_RETURN for various reasons, so I
cannot make Sapio only output addresses.

As far as I understand the counterargument against this, it is (thanks to
Luke Jr):

1) We should only have addresses or descriptors for things we know exactly
what they are, and also for things that represent something that is not
only payable but also potentially spendable.
2) OP_RETURN, being unspendable and usually proprietary in purpose, should
not have an address.
3) Further, most uses of OP_RETURN are proprietary (e.g., we don't know
what it represents) so therefore it would be lying to the user to pretend
we know how to interpret it.

My counterargument is that:

1) Addresses should represent things that people commonly create outputs
for -- perhaps regrettably, OP_RETURN is such a thing so software (e.g.,
https://citp.github.io/BlockSci/reference/addresses/address.html) already
does treat OP_RETURN as an address type, just without a standard
representation.
2) Many things are unspendable. E.g., a 0 value payment to an address, a
payment to P2SH(OP_RETURN <data>), etc. We can't know spendability based on
address type.
3) All scripts can have proprietary interpretations, the job of the address
is to do our best job of interpreting standard types to the best of our
ability. An example where this has been (ab)used previously is P2SH wrapped
SegWit, where one cannot distinguish if the underlying is to be evaluated
as P2SH or SegWit. Further, future OP_RETURN address types could take
precedence if they are well specified.

Do folks agree with the motivations for defining an address type? Are there
any design constraints?

Some starter thoughts
1) Should it be human readable & checksummed or encoded?
2) Should it have a fixed length of max 40-80 bytes or should we support
arbitrary length strings?
3) Should it be possible (i.e., from core) to pay into such an OP_RETURN or
should we categorize OP_RETURNS as a non-payable address type (and just use
it for parsing blockdata)

(my answers are 1. human readable + checksum, 2. arbitrary to support
nonstandard ones which miners create 3. non payable in standard software)

Cheers,

Jeremy

Best,

Jeremy

--
@JeremyRubin <https://twitter.com/JeremyRubin>
<https://twitter.com/JeremyRubin>