dtr-org / unit-e

A digital currency for a new era of decentralized trust
https://unit-e.io
MIT License
45 stars 15 forks source link

Proposal: V1 Witness Remote Staking Script #331

Closed scravy closed 5 years ago

scravy commented 5 years ago

The existing proposal for remote staking scripts (ADR-15 (not accepted as of yet) uses 256-bit addresses for remote staking scripts. There is a feature issue about these (#330), and it is highly recommended to read it before reading this issue, to understand the issues with it. That design is conceptually taken from particl as is.

Proposal: Segwit v1 addresses ~+ bech32 encoding~

The proposal is to use v1 segwit. v1 does not exist, so we're inventing it here. A remote staking script would look like this:

witness:      <signature> <pubkey>
scriptSig:    (empty)
scriptPubKey: 1 <20-byte-key-hash> <20-byte-key-hash>
              (0x0015{20-byte-key-hash}{20-byte-key-hash})

In code:

*script << OP_1 << ToByteVector(remotePubKeyhash) << ToByteVector(exitPubKeyHash);

This is a native v1 segwit program.

It could also support P2WSH as an exit script, in code:

*script << OP_1 << ToByteVector(remotePubKeyHash) << ToByteVector(scriptHash);

~bech32 addresses could be used to identify this, as they also encode the version (OP_0, OP_1, etc.). See BIP 173 Base32 address format for native v0-16 witness outputs for further details.~

Which type of address (2sh or 2pkh) is used can be identified the same way as in segwit v0, by looking at the length.

The benefits are the same as with native segwit in general. Smaller transactions, easier to parse (simpler code), etc. ~Due to the bech32 address format a recipient can once again be sure not to be sent funds which participate in remote staking as remote staking requires a v1 address as exit address.~

Alleged Benefits of Script

Segwit programs are not script. They are segwit programs. Script has the alleged advantage of being sort of detached from the code (just write a script, no code change needed). This is not true (at least in this case). Consensus rules have to be augmented to make sure that a remote staker only spends to the same remote staking address. If one looks at the code for this one can see that there is special code needed (this does not even touch the consensus rules in transaction validation, this is just the script logic to unmangle and identify such scripts): https://github.com/dtr-org/unit-e/pull/324

scravy commented 5 years ago

As also mentioned in https://github.com/dtr-org/unit-e/issues/330#issuecomment-443133327 I guess the 256 bit exit addresses are necessary I guess, but they should never face the user. That latter part is spelled out already in the ADR. The bech32 format is not necessary as addresses are not user facing and the sentence in this proposal that this would solve the problem which motivates these 256-bit destinations in the first place is not correct. A destination which on an opcode level looks different is needed.

I nevertheless very much advocate for the remote staking script layout as presented here, as I still believe that the one presented in here would be having advantages over the other one and plays well with the existing segwit infrastructure. Also I still don't see (and here I'm driven by the comment on the pull request which basically says that any script can be wrapped in between the IF/ELSE (a degree of freedom I believe is not necessary) how the native segwit would play with that nicely otherwise, especially given the possible confusion between script hashes and 256-bit public key hashes.

Nizametdinov commented 5 years ago

I had a similar idea for remote staking segwit programs, namely:

<version> <20-byte-key-hash> <32-byte-key-hash>

At first glance, they seem to be harder to implement than plain remote staking scripts because it is assumed everywhere in the code that witness program is a byte vector with the length from 2 to 40.

Due to the bech32 address format a recipient can once again be sure not to be sent funds which participate in remote staking as remote staking requires a v1 address as exit address.

I think v1 address can be easily converted to v0 address as long as they both are a Hash160 of the public key.

Which type of address (2sh or 2pkh) is used can be identified the same way as in segwit v0, by looking at the length.

If we decide to use 256-bit addresses then we will need some other way to distinguish between p2sh and p2pkh256. For example segwit version 3.

scravy commented 5 years ago

At first glance, they seem to be harder to implement than plain remote staking scripts because it is assumed everywhere in the code that witness program is a byte vector with the length from 2 to 40.

As far as I am aware that's in exactly one place:

// A witness program is any valid CScript that consists of a 1-byte push opcode
// followed by a data push between 2 and 40 bytes.
bool CScript::IsWitnessProgram(int& version, std::vector<unsigned char>& program) const
{
    if (this->size() < 4 || this->size() > 42) {
        return false;
    }

Looks simple enough to be changed or be made conditional on the version byte.

Please educate me about other places that I'm missing.

I think v1 address can be easily converted to v0 address as long as they both are a Hash160 of the public key.

You're absolutely right about that, I am wrong here, as I said in my previous comment. I had mistaken the whole 256-bit address thing for things that are exposed to the user hence the Usability tag and all that. I completely agree, just it must not be exposed to the user in my opinion.

If we decide to use 256-bit addresses then we will need some other way to distinguish between p2sh and p2pkh256.

As in the 256-bit addresses ticket: I think using address is a bit confusing. These are addresses:

There is, because it should not be exposed to the user, no 256-bit address. There is a 256-bit destination, and a remote staking script has two destinations.

For example segwit version 3.

Why version 3? Where does this come from? What about 1 and 2? Existing witness programs are all version 0 and come in two flavors: pay to public key and pay to script hash.

This proposal is about introducing version 1 which is the remote staking version. I agree that a 256-bit destination should be used as the exit destination and a regular pay to public key hash should be used as the remote staking destination.

Within version 1 segwit programs the length could (does not have to) distinguish (the same way as v0 programs do) decide whether the script is pay to public key hash or pay to script hash.

Do remote staking scripts really contain anything other than pay-to-public-key-hash scripts? I see in particl that they do match also p2sh scripts ( https://github.com/particl/particl-core/blob/90f5e523be429b04f3a2e47ac5fc5e7930ab7df1/src/script/script.cpp#L325 ), but how is that anything good? After all this means that now again 256-bit destinations can be confused - is it pay-to-public-key-hash-256 or pay-to-script (which already is 256-bit).

This is the essence of why this proposal introduces a new script version. Precisely because script hash and 256-bit pubkey hashes can be confused.

Nizametdinov commented 5 years ago

Why version 3? Where does this come from? What about 1 and 2? Existing witness programs are all version 0 and come in two flavors: pay to public key and pay to script hash.

I meant version 2. Version 1 for programs where exit address is a 256-bit destination and version 2 when exit address is a script hash.

I see in particl that they do match also p2sh scripts ( https://github.com/particl/particl-core/blob/90f5e523be429b04f3a2e47ac5fc5e7930ab7df1/src/script/script.cpp#L325 ), but how is that anything good?

I can imagine scenarios for p2sh and multisig in exit addresses (when large amounts are locked in P2SH or multisig it is beneficial to still be able to stake them). I'm going to check if someone uses it in Particl.

scravy commented 5 years ago

I agree that if script hash and 256-bit pubkey hash are both valid destination then different version would be required to distinguish them, as otherwise they are indistinguishable.

I can imagine such scenarios too, but: If the exit destination is pay-to-script-hash though do we not face the same issue as with ordinary pay-to-160bit-pubkeyhash? After all pay-to-script-hash is a valid mode of paying. A recipient using a scripthash address once again could not be sure whether the money is remote staked or not.

Nizametdinov commented 5 years ago

If the exit destination is pay-to-script-hash though do we not face the same issue as with ordinary pay-to-160bit-pubkeyhash?

This problem obviously exists. My assumption was that it was not so important for P2SH (if it's not P2SH-P2WSH). If some other developers implement a wallet which deals with P2SH they have to make decisions on how to work with remote staking scripts.

I might be wrong though.

scravy commented 5 years ago

A first iteration of remote staking does not have to cover everything. Why not start with a simple design that allwos for public key hashes only (including 256-bit key hashes), to get going.

mergeable[bot] commented 5 years ago

There has not been any activity in the past month. Is there anything to follow-up?

Nizametdinov commented 5 years ago

V1 witness remote staking scripts are specified in UIP-15 and partially implemented in #402.