RGB-WG / rgb-std

RGB standard libs for WASM & low-level integrations (no FS/networking)
https://rgb.tech
Apache License 2.0
66 stars 31 forks source link

fail spending opret and tapret allocations together #246

Closed zoedberg closed 1 month ago

zoedberg commented 1 month ago

I've added a test that tries to receive with a tapret wallet using opret as closing method. You can run it by checking out to https://github.com/zoedberg/rgb-integration-tests/tree/tapret_opret and running cargo +1.79 test --test transfers tapret_wlt_receiving_opret. The transfer is succesful but when the wallet tries to spend the opret allocation together with a tapret one (the change from the 1st transfer) the pay method fails with:

Composition(Stock("the spent UTXOs contain too many seals which can't fit the state transition input limit."))

I recall this functionality (closing both an opret and a tapret seal in a single RGB transfer) was inteded to work, as discussed in Viareggio (because we discovered this wasn't working). A refactor should have then fixed this.

dr-orlovsky commented 1 month ago

yes, there was a huge work done to make this work, and I had an impression that it was working before. Maybe I am wrong that we had checked that. Anyway this is a bug which I will work on

zoedberg commented 1 month ago

With https://github.com/RGB-WG/rgb-std/pull/252 the error changed from

Composition(Stock("the spent UTXOs contain too many seals which can't fit the state transition input limit."))

to

Composition(Stock("the invoice requirements can't be fulfilled using available assets or smart contract state."))
dr-orlovsky commented 1 month ago

This is how it should work: the tapret wallet can't use opret funds; a manual hacking Is required. Since you lack tapret RGB funds you can't fulfill the invoice.

Spending opret results in creating a second transition bundle, since each transition bundle commits to the used closing method and can't spend both opret and tapret. But the second transition bundle can't pay to the seal defined in the first transition bundle - the receiver's wallet won't recognize that payment.

Thus, if you received invalid opret transfer into a tapret wallet, you need: 1) add some RGB tapret funds to the same UTXO which already has opret funds (you already have that in your case) 2) pay an invoice which can be covered by your existing tapret balance (you can create tiny self-invoice for that); with that opret funds will convert into tapret in your own change; 3) after that you will be able to spend funds which came through opret.

dr-orlovsky commented 1 month ago

I actually was able to write logic allowing creating two different transition bundles spending from both opret and tapret inputs - and figuring out which ones have enough funds (or how to combine them). The logic is extremely complex, especially in part related to change etc. I am not sure whether that complexity (with all the risks for bugs) worth UX improvements.

Here is separate PR adding that specific bit for your consideration: https://github.com/RGB-WG/rgb-std/pull/256

zoedberg commented 1 month ago

I confirm that with https://github.com/RGB-WG/rgb-std/pull/256 the test wallet is able to spend both allocations. The fix seems like a completion of the huge work that has been done to allow spending both tapret and opret allocations. In this context, the solution doesn't seem excessively complex and the added code looks reasonable.