Skip to content

Use of P2SH with cryptoconditions

dimxy edited this page Sep 1, 2021 · 4 revisions

How to use cryptoconditions addresses as P2SH

What is the CC address and what is it used for?

A CC address of a transaction cc output is obtained by a blockchain internal function ExtractDestination() which actually extracts from a transaction output some part specific for each type of the output and makes it an address by hashing it and converting to base58 system, so all address types look similar although they are obtained from different destination types.

For example, for a P2PK output its destination is simply a pubkey, so the address is the pubkey hashed with (SHA256+RIPEMD160 algorithms) and converted to base58. For a P2PKH output the destination is the address itself. For a CC output the destination is a fingerprinted serialised cryptocondition, so the CC address is again a RIPEMD160 hash transformed into base58. A CC address looks like a normal address (by 'normal' we usual addresses from commonly used P2PK and P2PKH outputs) however we cannot use them like normal addresses, that is to send coins to a cc address with sendtoaddress rpc - such coins would be lost because could not be spent ever.

But addresses (including cc addresses) are used for yet another purpose - in the chain's AddressIndex or UnspentIndex, as a unified unique key to utxo's data. So the CC address currently is used only internally for indexing purpose.

How could we use CC addresses in transactions

Currently to create a transaction with cc outputs we use some cc module's rpc which needs a destination pubkey to create a condition for a tx output (cryptoconditions are not aware of blockchain addresses and use pubkeys themselves). The created cryptocondition is serialised and fingerprinted and put into the transaction output's scriptPubKey as a script <condition> OP_CHECKCRYPTOCONDITION. When such a script is evaluated the OP_CHECKCRYPTOCONDITION opcode triggers verifying signatures, thresholds and other cryptoconditions in the counterpart called 'fulfilment' stored in the transaction input (spending this output). The fulfilment is actually the serialised condition with the difference that it is not fingerprinted and its content is readable.

The original cc scriptPubKey and scriptSig structure is:

  • CC scriptPubKey is <condition> OP_CHECKCRYPTOCONDITION
  • CC scriptSig is <fulfilment> ...

We remember that there is the Pay-to-Script-Hash (P2SH) output which is actually a construct where the original script from the scriptPubKey is moved into the spending scriptSig and its hash is placed and OP_HASH160 and OP_EQUAL opcodes to check that this hash matches the original script (which now is in the scriptSig).

We can do the same for cryptconditions outputs too and create P2SH scriptPubKeys and scriptSigs with cryptoconditions:

  • P2SH scriptPubKey is OP_HASH160 <cc-address> OP_EQUAL
  • P2SH scriptSig is <condition> OP_CHECKCRYPTOCONDITION <fulfilment> So everything looks great and we do not need pubkeys if we know the CC addresses. There are several issues however:
  • to create a multisignature cc address we cannot use several unilateral cc addresses, we still need all the pubkeys to create the multisignature cc address
  • each CC address is different for cc each module (because each cc module stores its own evalcode in the cryptocondition)
  • CC addresses potentially could be used only for very basic transactions (like transfer tokens to a user). Most cc modules create pretty complicated transactions with several pubkeys inside conditions. So user may still need the target pubkeys to create such complex conditions.

There is yet another issue with P2SH outputs.

Some cc modules need to know which transaction outputs belong to the cc module, that is contain this module evalcode in the output conditions. For example, if a transaction has two cc outputs one of them is a token output, cc module validation code must know which it is to preserve token value balance in the transaction, to prevent tokens injection from non-tokens vouts.

For that the cryptoconditions version 2 was developed where conditions in scriptPubKeys are serialised only partially and cc evalcodes are exposed for reading. But this exposure could not be done in P2SH outputs where the whole original script is hashed. To use P2SH we need to stick with cryptoconditions v1 (where the whole condition was fingerprinted) but have some metadata about its content, like evalcodes in the condition. Such metadata could be put in OP_DROP field, after the P2SH script in the scriptPubKey.

Of course, the metadata in OP_DROP must be checked on spending the output. For example, when the token validation code finds the token evalcode inside an output's metadata and identifies it as a token output and verifies the token balance, it must also check later that this evalcode is indeed present in the condition - it can do this at the spending event because the condition is readable in the spending scriptSig.

Some work on the source code is required to implement this CC address usage extension, and to add this to existing chains a hardfork is needed.

TLDR:

  • A CC address as not a normal P2PK or P2PKH address although it may look similar! It cannot be used in the same way for sending coins to it with the simple sendtoaddress rpc
  • We can use CC addresses instead of pubkeys in some simple cc transactions by creating pay-to-script-hash (P2SH) outputs with CC addresses.
  • We may need to add some data about the content of the condition matching to the script hash, for the cc modules validation code
  • This feature needs to be implemented yet and a hardfork is required to apply it to existing chains
Clone this wiki locally