CHIP 2021-02 Unforgeable Groups for Bitcoin Cash

That sounds very optimistic. I don’t think it’s the case since until SLP there was no reason for wallets to do this besides p2pkh and p2sh. Or at best p2pkh, p2sh, p2sh-multisig. Electron is the most capable power-wallet that exists for BCH. It’s capabilities should not be considered representative.

2 Likes

Then I guess we should consider building a list of wallets and see how they deal with non-p2pkh and non-p2sh outputs. If consensus would allow it, what would happen if a miner would mine a 0xEE <gibberish> output? What if that <gibberish> contained a P2PKH template? Maybe some wallet implementation processing it from the back would think it’s just a P2PKH output and ignore the prefix? But then, couldn’t a miner even now prefix it with some currently-valid opcodes to make it unspendable and confuse such wallets?

To add some fresh context, in response to all the comments I’m reworking the CHIP to reduce the scope down to TRANSFER, GENESIS, MINT, MELT, and BATON features. The working branch is here. Merged. There I have already reduced the scope in both tech. description and the spec, those parts are like 90% done and I intend to add a flowchart if it will added a flowchart to clear some concepts and help with security analysis later. Also, Calin’s proposal is now implemented and it would help us close the following issues: layer mixing, number format for qty can now be VarInt (aka CompactSize), simplify parsing for non-VM aware code (could be relevant for HW), and the issue of multiple OP_GROUPs in script

2 Likes

Yes that seems like a reasonable thing for the CHIP authors to organize and execute. I’m predicting that the result will be “Vast majority of unupgraded wallets and services will become unreliable in the case that they receive a GROUP utxo.” If so, this is a massive cost and risk. Enough to make me consider that the design of group needs to be redone so that it does not cause this.

If that’s what Calin’s idea is referring to, e.g. something like stuffing all of this into p2sh, then big :+1: from me.

2 Likes

Would feel good to get that :+1: but that’s not what’s proposed. The prefix and group fields would still live outside the P2SH hash, but here they would also live outside the Script VM and only make use of the TX serialization script field to store the prefix.
Nodes have to be in consensus so after an upgrade they’d all be aware of this and wouldn’t treat the prefix as part of the script, they’d slice it off before passing the rest to the Script VM.
However, unupgraded wallets would think it’s all a script, and to them could look like 0xEE <gibberish> or 0xEE <gibberish> <p2pkh>.

Stuffing it all into p2sh would make the proposal lose the appeal, at least to me. Because then you couldn’t tell that some output is a token output without also receiving the actual script through some side-channel. This would complicate a lot of things, how would you build a token explorer if you couldn’t tell where those tokens are on the blockchain? You’d have to somehow collect all those scripts externally, and there’d be no way to tell whether you got them all.

1 Like

There are already other things that require a side channel regarding GROUP. Is it an NFT? Is it fixed supply? I think the question here is which is less palatable:

a) potentially huge number of wallets becoming unreliable
b) shiny new tokens aren’t quite as cool as originally envisioned

Seems pretty clear to me unless I’m missing something.

Is it an NFT? Is it fixed supply?

You can think of MINT as nothing but a “magical” token amount which can be fanned out to any number of other magical amounts or ordinary amounts. So, you answer both questions by filtering all UTXOs having that token ID, summing their quantities, and checking for existence of a MINT authority in the UTXO set. If token amounts add up to 1 and no MINT exists then it’s a NFT with a fixed supply. A token database can be built in a single pass over the blockchain, and then updated as new TX-es are published. You don’t need this database to only verify consensus rules, though, so only services such as block explorers would need that database and only if they’re interested in supporting tokens.

For light wallets interested in some token features a SPV proof of fixed supply can be provided by filtering for only transactions of that token ID which have a MINT bit in either inputs or outputs, and providing them alongside Merkle proof of their existence. To be fair, these proofs could grow large if a token had a lot of MINT operations before spending the last MINT.

So these questions can both be answered by information contained on the blockchain. The same goes for metadata. We write it in the OP_RETURN of the GENESIS transaction, and by including that data in the hash which pseudo-randomly generates the token ID, we’re compressing the metadata inside the token ID, as it becomes a commitment to the metadata.

Any token DB can answer the “what is the metadata?” question by a simple lookup of the genesis TX for the token, and the person asking the question can be 100% sure it’s the correct metadata without having to look past the UTXO he owns. Just compare the hash of the metadata being served with the token ID you’ve received. It’s trustless.

Re. other points:

a) I expect the outcome of studying wallets to be quite the opposite of what you expects so we’ll have to hold this one until we actually get some new information. Before asking/studying wallets I’d like to complete at least the tech.description & spec sections so everyone can be on the same page.

b) More work needed on this one too :slight_smile: For now, a simple question - is SLP cool and shiny enough? Because Group solves a lot of security/trust issues with SLP architecture as demonstrated above.

Here we can refer to another topic investigating the possibility to simply put SLP into consensus as-is. Here I will repeat my own argument to make a point which would be off-topic there.

If we’re breaking out of “as-is” then why not polish it further… this is kind of what Group does with the current scope.

After lots of feedback throughout almost 2 months since the first draft, the CHIP has significantly matured and I invite everyone interested to have another look. I have been told that the technical description flows much better and makes it easier to understand, and I’m so glad to be hearing that! I couldn’t have produced this alone, you’ll notice the difference in quality from my first draft. It is everyone’s feedback that made this possible, because I learned from you all, and with the goal to really make this proposal ironclad!

Group Tokenization For Bitcoin Cash CHIP rev. 2021-04-13

Group Tokenization For Bitcoin Cash CHIP rev. 2021-04-14

  • Scope is reduced to just the GENESIS, TRANSFER, MINT, MELT, and BATON features.
  • Scheme for storing token data changed so it doesn’t require living inside Script.
  • Still lots of TODOs, but this is a milestone and we’re moving ahead!

Update: If you already read the rev. 2021-04-13 kindly note that there was an erroneous claim regarding SPV proofs for current token supply when MINT and MELT authorities still exist. Such proofs are only verifiable if all MINT and MELT authorities have been destroyed, which can be proven. This is because verifier has no way of knowing that descendant branches spending some authority UTXO and affecting the supply don’t exist. He’d have to check the UTXO set from the proof VS the UTXO set obtained from a trusted full node.

1 Like

Have you considered allowing miners to claim excess tokens? The rule could be that the coinbase outputs can include token outputs. Given that burning tokens normally isn’t allowed, I guess the point is moot.

It would move the tokens to nearer equal status to BCH, and that may be undesirable.

Hi thanks for reading! Note that line will only hold until we introduce the MELT authority later in the document. Before that we’re describing only a minimal token system. In technical description, we’re introducing the whole system bottom-up, building it up from the minimal system which is just the TRANSFER+GENESIS where you can do minting exactly 1 time, and there you can only transfer and freely melt. Then we introduce MINT to let you mint later and transfer ownership of minting capability, and then we introduce MELT and set the balancing rule to == so no more accidental melts. With MELT authority there is clear intent and authority to melt, which makes auditing the “official” supply easy while also preventing accidental burns by users. Finally, the BATON makes the distinction between one-time use authorities, and those that are allowed to be transferred.

This is not-applicable to the scope of the proposal, and as you said it may be undesirable. In an old draft, I did ponder a hypothetical solution where tokens would be really equal, and it would have problems.

While tokens can be plugged into all interfaces where BCH can, they’re not really equal and shouldn’t be – because we need the incentives around BCH not only for the blockchain to work, but for the whole ecosystem to align their incentives and share the same goal, and also for security because the price will not just have an impact for lives of everyone holding BCH, it will also have an impact on increasing our % of the SHA256 hash-power.

Adding token based transaction fees would be of moderate complexity. It is conceptually pretty simple and doesn’t have to many side effects.

Miners could be paid from multiple sources. It could make tx fees/tipping miners less hassle for users. OTOH, it removes the need to obtain BCH to pay tx fees.

Minting tokens to pay miners would be a free rider problem though. All tokens benefit from the security of paying miners with minted tokens but only some tokens pay towards it.

Having a primary currency that all the tokens reference seems reasonable.

Your point that having BCH in every output ensures the incentive to consolidate outputs is a good point. This can be maintained even if tokens can be paid as tx fees.

I agree that keeping things simple is better though.

1 Like

True, it could be as simple as introducing another authority, e.g. a FEE authority which would work exactly like MELT but the excess wouldn’t be destroyed and instead would be claimed by miners. Just to be clear, I have no intention of including such a feature in the current proposal, because assessing the impact could detract the proposal from moving forward.

Glad we agree here!

After a days long discussion with Emil Oldenburg, I accepted his proposal to simplify the authority system to just one UTXO per tokenID, now called the baton output, have fixed minting capacity, and add lockable metadata fields to the baton. I believe that this will give the CHIP wider acceptance, make it more friendly for full stack product builders, address previous concerns about complexity, and make it more defensible and likely to be activated.

More details here: New Group Tokenization Scheme - One Token Standard (WIP)

and it’s already been implemented into the CHIP, which is still WIP and now the Specification needs to be rewritten too.

I would like the ability to provably back tokens with BCH similar to how ETH contracts can have coins deposited into them. There are 4 prerequisites to having this functionality thought and I have made a new issue in on gitlab for each one. Issues 30, 31, 32, and 33.

To summarise here the following 4 features are needed

  1. infinite mint capability
  2. Separate MELT and MINT permissions
  3. Allow for fenced BCH groups
  4. Subgroups

The least trivial of those changes is subgroups. Subgroups are required because a fenced BCH group can not also have a token, the token needs to be a subgroup of the fence to have the token be backed by BCH (or the token can be the main group and the fenced bch group can be the subgroup).

I’ll add back 1. & 2. to the proposal, IMO there isn’t a strong argument NOT to have them, as you say they’re trivial to implement, and having them has its merits.

Best I got against 1. was sum overflow, but isn’t this, like, trivial to guard against? As for 2., it’s rather awkward NOT to have it which I realized while trying to write a spec where 0-flag baton could still melt even when MINT was given up.

3. and 4. require some additional logic circuits on the consensus layer, but the bulk of the cost would be on other layers: block explorers, wallets, etc. would have to deal with more kinds of tokens, check for token balance in 2 places instead of 1 (BCH amount for colored / tokenAmount for others), and so on.

Compared with some pure Script solution the advantage of 3. and 4. would be that we could lock only their authority UTXO in a Script covenant and have it be publicly accessible to apply BCH coloring or token coloring (subgroups) if the right stuff was presented to the TX, so only such operations would have to be P2SH. The tokens themselves would remain P2PKH so could move more easily on the blockchain and be more widely supported by wallets etc.

If anyone wants to weigh in, here are the threads for each feature:
1. infinite MINT, 2. MELT flag, 3. fence/coloredBCH, 4. subgroups/coloredTokens

The other applications need to add support for a new token scheme regardless of which is used.
There is only one kind of token in op_group. the only difference between a group and a subgroup is the group ID of a subgroup will indicate a parent group and applications will have to parse the groupids anyway. At most subgroups are asking the wallets to make an indication of a relationship between two groups and not much else.
Fenced BCH values are in the same location as regular BCH transaction values.

Assuming parsing group tokens is already implemented, the additional burden of checking for fenced bch and subgroups consists of a couple more if statements.

1 Like

@Griffith I worked out an example of how you could create backed tokens even without the “fence” feature. It is possible as a consequence of locking the authority (aka baton) to exactly 1 UTXO in the “base” proposal. Maybe an easy SmartBCH bridge could be created this way, too! Including hash of the first prevout output in the tokenID preimage could allow a token authority to prove it was created by another token’s authority.

Token Group Script Covenant

The below example requires CHIP-2021-02: Native Introspection Opcodes.

It also assumes that introspection opcodes for reading Group annotation will be added:

  • OP_TOKENID,
  • OP_TOKENQTY,
  • OP_TOKENFLAGS,
  • OP_TOKENLEFTTOMINT,
  • OP_TOKENMETA,
    all with variations for accessing different TX local outputs.

Recall that tokenID is generated by hashing a preimage consisting of parts of that token’s genesis transaction:

  1. Hash of first input’s prevout output;
  2. First input’s prevout TXID;
  3. First input’s prevout output index;
  4. Output index of the genesis output being generated.
  5. The genesis output being generated with tokenID left out;

Recall that consensus also enforces that:

  • The genesis output must be of token authority type;
  • When an authority output is spent, it can create any number of ordinary token outputs but only one authority output.

Because of consensus rules placed on token genesis and token authorities, it takes little to prove that a pubKeyScript placed on a token authority is the same as the one set at genesis and that it couldn’t have been tampered with.
The pubKeyScript only has to prove that it’s been tied to the token authority output since genesis, and such proof will be of fixed size.

Redeem script:
OP_DUP OP_DUP
OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUAL // I must be carried forward…
OP_SWAP
OP_OUTPUTTOKENQTY OP_NOT OP_AND // … to a token authority output…
OP_SWAP
OP_OUTPUTTOKENID OP_TOKENID OP_EQUAL OP_AND// … with the same tokenID as me.
OP_SWAP
OP_INPUTINDEX OP_UTXOBYTECODE OP_CAT OP_HASH256 // Also, my pubKeyScript…
OP_TOKENID OP_EQUAL OP_AND // … must be the same as set on my token’s genesis.
OP_SWAP<...>OP_AND // Any other conditions.

Signature:
<...><genDataHeader><outputIndex>

The genDataHeader part of the signature is the tokenID preimage with genesis pubKeyScript left out, and the outputIndex refers to the “change” output of the token authority being spent.

The size of the above covenant boilerplate code is given below:

6   Signature push opcodes (3+1+1+1)
1   OP_0
25  Redeem script boilerplate code
63  Covenant proof part of signature, assuming NULL metadata.
-------------------------------------------------------------
95

Because token authorities can be created with or without capability to mint tokens, such covenanted output could be used as:

  • As NFT with a BCH balance entirely controlled by the covenant;
  • As a token authority with variable BCH balance.

When used as a NFT the covenant could serve as BCH vault, requiring arbitrary proofs to add or remove BCH.

When used with token minting and melting capability, the covenant could require BCH to be paid in/out of the covenant which would make tokens backed by BCH possible where such tokens would remain free P2PKH citizens.

Covenanted Ordinary Token Outputs

If the covenant is placed at token’s genesis then it is possible to envelop ordinary token outputs in the covenant by extending the code above to require indexes of a number of ordinary token outputs.

The covenant could then verify that it’s being passed on to them and tally up the balances in order to verify that outputs haven’t been omitted.

This would allow fanning out of covenanted outputs.

The above would work only with finite mint tokens.

For infinite mint the covenant would have to enforce that the total number of outputs in a transaction matches the number of provided indexes.

Supporting covenanted outputs merging would be achieved the same way, by requiring indexes of a number of inputs to be included in the balance calculation.

For example, this could be used to implement “colored” BCH where the covenant could enforce tokenQty == satoshiAmount.

It could also allow any owner to burn the color and reclaim the BCH by coding the covenant so that it allows being spent to a token OP_RETURN under some conditions.

MAJOR UPDATE - 4.1 Unforgeable Groups for Bitcoin Cash

This was prompted by some discussions I had with @im_uname and after realizing that the groupID can be used as a cryptographic “commitment” primitive required to construct unforgeable Script covenants. These would then let us implement all advanced supply and metadata management features from within Script, while letting token amounts be free P2PKH citizens, giving us the best of both worlds, consensus and Script.

Also, pure commitment mode is supported, which would enable fixed-size inductive proof covenant contracts that would work the same as PMv3 “detached proof” examples but reconstructing the groupID preimage instead of TXID preimage as proof.

4.1 Tweak GENESIS and add NFT group flag

  • Add a NFT group flag so we can have NFTs that carry some state
  • Tweak GENESIS to compress each input in the preimage
  • Add PMv3 GENESIS and SIGHASH sections
  • Wording

4.0 Unforgeable Groups

  • Simplified the output format and consensus layer
  • Generalized output groups as “carried witness”, having only the GENESIS rule enforced
  • Amount field is now optional and indicated using the LSB of groupID so the whole group must have or not have it
  • Native token groups and Satoshi token groups (aka “holds BCH”) are then a more restricted variant of a generalized group, having token logic enforced over respective amount fields, and NFT logic enforced over amountless token groups.
  • 0-amount indicates “singulary” i.e. an infinite source or an infinite sink which allows token amount creation and destruction
  • Any advanced features, such as metadata updating, are to be implemented using unforgeable Script covenants, as demonstrated in the examples section
  • Reworked CHIP sections
2 Likes

MAJOR UPDATE - 5.0

After some more iterations, and a brainstorming session on how to marry with PMv3 features (detached signatures and detached proofs), the proposal was made much less complex while still preserving the possibility to implement desired behaviors by using Script covenant placed on token baton.

In short, the proposal now only introduces:

  • A simple genesis setup: 1st prevout txid and vout index + genesis output index + genesis output itself
  • Only the “native token” group type, which enforces a “super-contract” over grouped outputs by using native consensus code to enforce token balances across a TX, and by induction the accounting equation is then guaranteed for the whole group.
  • 4 unary introspection opcodes to access groupID and groupAmount that will allow interaction with covenants

Most sections are now written, including specification (3 pages), security considerations and rather elaborate costs analysis.

MAJOR UPDATE - 6.0

This was prompted by exchanging notes with @bitjson and revisiting @tom 's idea of declaring the genesis, and it enables group tokens to interact so much better with Script!

Changes:

  • Whole new approach to group genesis: instead of inferring it from the TX, it will be explicitly declared as an input prefix that can use the same byte because it will be exclusive to input context.
  • One more introspection opcode to access the genesis input’s generated groupID preimage.
  • Change group amount format from VarInt to fixed width uint.

Instead of inferring genesis from orphan outputs and allowing orphans only if the groupID matches the hash, we require the genesis to be declared on the inputs, conceptually similar to a coinbase input. A new introspection opcode is added to access the input’s genesis preimage.
Advantages:

  • enables flexibility in deciding which input will be a genesis input
  • enables flexibility in deciding which input’s prevout will be committed to for later use in smart contracts
  • enables better interaction with contracts requiring or verifying the genesis operation
  • removes malleability from group genesis (outputs are signed, and orphans disallowed)
  • more consistent with Bitcoin design (coinbase input)
  • enables versioning the genesis preimage construction without having to spend scarce group type bits which will be reserved for potential “super-contract” optimizations in the future
  • opens the path to a future upgrade where user-defined parts of the genesis TX could be appended to the preimage
  • enables a dedicated genesis nonce field which simplifies grinding the group type, making the group type encoding time-space trade-off more convenient
  • opens the path to synergies with detached proofs and signatures, where hash of the real unlocking script could be appended to the groupID preimage

Example - “Jason’s Challenge” Contract - Link to Bitauth IDE Template

The user pays 10,000 satoshis to get a token. They can transfer that token to use 2-of-3, then back to single sig, then deposit the token and get back their 10,000 satoshis from the parent covenant.

There are 2 contracts:

  1. NFT, placed on the prevout which will be spent as group genesis input and generate the NFT. The prevout script will require that 10,000 sats are paid into a fixed P2SH address (depository corporation covenant). Only the 1st spend is from a P2SH, the genesis input spend: the NFT can then be moved to an ordinary P2PKH and still be able to reclaim the 10,000 by burning itself in the same TX as any covenant UTXO.

  2. The depository corporation covenant is an anyone-can-spend kind of thing, but it requires any NFT that can satisfy the proof of payment at genesis to be burned to an OP_RETURN. The NFT’s genesis script is verified to match the template hardcoded in the P2SH covenant.

Not only does this create a BCH-backed NFT, it also lets NFT holders reclaim the BCH from any covenant UTXO :slight_smile: I suspect there’s a way to make some kind of BCH mixer based on this.

UPDATE - 6.1 Fungible Tokens

Changes:

  • Acknowledge existence of “CHIP-2022-02-CashTokens: Token Primitives for Bitcoin Cash” and start working towards merging the two proposals
  • Extract groupType to its own field to enable signing group genesis from the redeem Script without the problem of malleating the nonce
  • Align groupType with CT2.0
  • Remove singularity amount overload, entire fungible token supply of the group must be minted at genesis
  • Modify genesis - prevout hash now optional

With this and the exception of genesis setup (which I argue should be implemented by CT2.0), Group is now a subset of CashTokens, and I’ll be working my way to implementing CT2.0’s way of doing NFTs which I feel is the breakthrough that eluded me.

Group v6.0 and CT2.0 were released around the same time and I feel both made some key breakthroughs:

  1. Genesis naturally belongs on inputs, and as such fits perfectly with other Script VM primitives (Group v6.0) and makes certain covenant constructions rather easy
  2. NFT is not a special type of FT with supply=1 and they must be independent (CT2.0)
  3. Allowing both the FT and NFT to be carried by the same output elegantly solves the problem of “baton”, where it’s nothing but a labelled FT amount. (CT2.0)

My goal with Group now is to use it as a sort of “peer review” document, where it could ultimately be just for information, while CT2.0 could carry this technology through the finish line.

1 Like