CashScript / cashscript

⚖️ Easily write and interact with Bitcoin Cash smart contracts
https://cashscript.org
MIT License
112 stars 79 forks source link

Support for CashTokens #130

Closed mr-zwets closed 1 year ago

mr-zwets commented 1 year ago

The Cashtokens upgrade adds 6 new introspection opcodes, these would map cleanly to the following 6 new cashscript expressions. These are just a suggestion but might be helpful for other devs thinking already about new contracts enabled by the cashtokens upgrade

bytes tx.inputs[i].tokenCategory

bytes tx.inputs[i].nftCommitment

int tx.inputs[i].tokenAmount

bytes tx.outputs[i].tokenCategory

bytes tx.outputs[i].nftCommitment

int tx.outputs[i].tokenAmount
rkalis commented 1 year ago

Nice suggestions! Those opcode mappings make sense to me. Here are some notes from our call today.

Compiler TODOs:

SDK TODOs:

Docs TODOs:

mr-zwets commented 1 year ago

Started working on the PR in my "CashTokens" branch. I suggest we first just upgrade the cashscript compiler & language documentation for the new functionality so new contracts can already be compiled for chipnet. Then afterwards upgrade the SDK for Cashtokens and add support for P2SH32 with a new expression LockingBytecodeP2SH32 and support in the SDK.

Compiler TODOs:

Docs TODOs:

rkalis commented 1 year ago

Great work so far @mr-zwets! Let me get to those AST test cases.

rkalis commented 1 year ago

AST test cases are added. I think we're probably almost ready on the compiler side so we can launch 0.8.0-next.0 this week and then work on the SDK between now and May after some other libraries have also added more support for CashTokens.

mr-zwets commented 1 year ago

I changed the type of tokenCategory from bytes32 back to bytes, as it can just return 0 or the tokenCategory concatenated together with the NFT's capability (mutable or minting).

I also added LockingBytecodeP2SH32 already because it fits better together with this first step of adding the new features to the compiler and only afterwards to the SDK. The migration notes now also make mention of the removal of the network options staging and testnet. So everything looks finished to me for release!

rkalis commented 1 year ago

Ok, in 0.8.0-next.0 we completed all the compiler TODOs. Today @mr-zwets and I had another call to refine the SDK TODOs.

Network functionality (depends on libs like electrum-cash):

Transaction signing functionality (depends on v2 of Libauth):

Depends on both transaction signing and transaction building:

cculianu commented 1 year ago

FWIW I'm adding additional API support to Fulcrum

blockchain.*.listunspent will spit out additional info for UTXOs that have token_data on them. Basically something like this will do in an additional optional token_data key in the results dict for each UTXO

{ 
  "height": 126184,
  "token_data": {
    "amount": "1000000", 
    "category": "8fd6a2f713beaa5907a776b8b3060cddd1c6ff0588554c2364698ae271321ce9",
    "nft": {"capability": "minting", "commitment":"f00fd00fb33f"}
  },
  "tx_hash": "87489c43bae69c297bbaf65276573b0001c20c647a3d54d2842a4425ff87bacc",
  "tx_pos":1,
  "value":1000000
}

The listunspent and get_balance APIs will have an optional second argument to control inclusion or filtering of token UTXOs from their results. The question for you guys is -- what should the default be if unspecified?

I was partial to including all UTXOs, including tokens, to all results if unspecified.

I encourage you to join the discussion on telegram to hash this out: https://t.me/electroncashserver

mr-zwets commented 1 year ago

Just for completeness I want to mention that the move to Bigint #140 is also a prerequisite for adding CashTokens and that it has been decided to use P2SH32 addresses for CashScript smart contracts for security reasons to prevent collision attacks.

So together with the ESM changes necessary to change to alpha version of libauth v2, this issue contains everything necessary to upgrade CashScript for the May 15 network upgrade.

mr-zwets commented 1 year ago

progress

rkalis commented 1 year ago

Note: "old style" covenants don't work any more with the upgrade to P2SH32, because they use OutputP2SH to send money back into the contract, which won't work any more if the SDK only supports P2SH32.

I see 3 options:

  1. Drop SDK support for "old style" covenants (compiler already dropped support for this in v0.7)
  2. Make it possible to get the P2SH20 address for a contract from the SDK
  3. Backport OutputP2SH32 to v0.6

I think option (1) probably makes the most sense. But I'd like to make sure that there are no legitimate use cases for why someone would want to use an "old style" covenant (that they'd need to compile with cashc v0.6), but then use it in a modern version of the SDK.

I don't think there are any cases where this make sense. But would love it if I can get some other eyes on that @mr-zwets @emergent-reasons.

emergent-reasons commented 1 year ago

Appreciate you asking. (1) is fine with GP.

mr-zwets commented 1 year ago

We decided to keep P2SH20 as an option when initiating a new contract which means old style covenants can still be used.

new Contract(
  artifact: Artifact,
  constructorArgs: Argument[],
  options? : {
    provider: NetworkProvider,
    addressType: 'p2sh20' | 'p2sh32',
  }
)
rkalis commented 1 year ago

For now we've decided not to implement automated UTXO selection for NFTs. So if you want to use NFTs with the CashScript SDK, you have to manually select your UTXOS. If we hear about any strong use cases that require this after launch, we can consider adding it after all.

rkalis commented 1 year ago

We're all ready to launch this after CashTokens goes live: https://twitter.com/CashScriptBCH/status/1651177916212948992. We'll keep this issue open until it's released in production.

rkalis commented 1 year ago

This is released in production and CashTokens is live. 🥳