Page MenuHomePhabricator

[ecash-agora] Add `AgoraOneshot`
ClosedPublic

Authored by tobias_ruck on Apr 30 2024, 15:20.

Details

Reviewers
bytesofman
Group Reviewers
Restricted Project
Commits
rABC7d2f38d2cad8: [ecash-agora] Add `AgoraOneshot`
Summary

This is a simplified Agora offer which can only be accepted in "one shot", e.g. all or nothing. This is useful for offers that offer exactly one token, especially NFTs.

The covenant is reasonably simple, see this article for an explanation of the covenant mechanism, but uses two optimizations:

  1. It uses ANYONECANPAY as sighash for the "accept" path, which makes the sighash preimage start with 2000....00000, which can be created with OP_2 68 OP_NUM2BIN, saving around 64 bytes.
  2. It uses OP_CODESEPARATOR before the OP_CHECKSIG, which cuts out the entire script code, leaving only the OP_CHECKSIG behind. The scriptCode part in the BIP143 sighash now just becomes 01ac, which is both easier to deal with in the OP_SPLIT and also saves 100 bytes or so (depending on the enforced outputs).

Note: This currently doesn't add any functionality for discovering trades on the blockchain, which will be done in a future diff.

Depends on D16081.

Test Plan

BUILD_DIR=../../build npm run integration-tests

  1. For understanding the covenant:
  2. Install meep
  3. Run the accept tx of the final tx to see how it works in meep (ignore the buggy sig density check of meep):
~/meep/bin/go debug -t 
01000000021f236483a002f7613f13da431e08ef6297350969ad1d2522766789b6a68d198801000000fd95012102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f2740e1d5d9bb0b6e4ca21db777709863933706be84057b36a4f6225ce4ceaaf925044531e9c694ed850d2a010cd882fa0ec4ed1fddeae8661aa5ede1a09fea829bcd4c5a1f236483a002f7613f13da431e08ef6297350969ad1d2522766789b6a68d19880100000001ac2202000000000000ffffffff4fae5c27fc0ba6b8fdf7bc7fe8a6f135c5821bb1f79c275f5554d9d8b8bbe70900000000c10000002222020000000000001976a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac514cb0634c6b0000000000000000406a04534c500001410453454e4420da400de527913c3bac117ef8dcc01c05439e9ebea95fe4cd339757ddf3206c9808000000000000000008000000000000000180380100000000001976a914fc7250a211deddc70ee5a2738de5f07817351cef88ac7c7eaa7801327f7701207f7588510144807c7ea86f7bbb7501c17e7c6721034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa68abacffffffff9f968972c1dce000a0d0c4fe781431df265117fdfec6bc4f39333f90df5bab25000000006441d1375981ee3e3e7fece31bc6cd2e5efe26ee5a082cfcd28ce3b97490ae4e3e66d4d9a79cb2eeabe92404ed20943e883e4974e658409e6c390fceee17b72b3b08412102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27ffffffff030000000000000000406a04534c500001410453454e4420da400de527913c3bac117ef8dcc01c05439e9ebea95fe4cd339757ddf3206c9808000000000000000008000000000000000180380100000000001976a914fc7250a211deddc70ee5a2738de5f07817351cef88ac22020000000000001976a914531260aa2a199e228c537dfa42c82bea2c7c1f4d88ac00000000 
-a 546 -s a9147d5915e36b8635a96aeba1698ce031f9be8e9d4687

Markdown

Use https://markdownlivepreview.com/ to make sure it looks good

Diff Detail

Repository
rABC Bitcoin ABC
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

run integration tests in CI

@bot ecash-agora-integration-tests

bytesofman added inline comments.
modules/ecash-agora/README.md
1 ↗(On Diff #47523)
  1. Add at least a couple of sentences about what this lib is
  1. We need some kind of user story about what is going on in the test file. Will need full documentation at some point, but even now, I don't feel comfortable getting this in the monorepo. I personally don't fully understand what is going on just reviewing the test, and an explanation would help.
modules/ecash-agora/src/oneshot.ts
42 ↗(On Diff #47523)
72 ↗(On Diff #47523)

how did you come up with this?

Is there some kind of tool suite or library for building this kind of tx up incrementally?

How can we best support developers innovating on complex-but-possible contract-like txs on eCash?

modules/ecash-agora/tests/oneshot.test.ts
181 ↗(On Diff #47523)

again with the [0,1] for Amounts[] -- is this syntax always required when sending qty 1 of a token with no expected change?

This revision now requires changes to proceed.Apr 30 2024, 16:54
modules/ecash-agora/src/oneshot.ts
72 ↗(On Diff #47523)

I built some tooling a while ago in Rust, but it's kind of a mess.

I write them using the bitcoin-cash crate, which as a feature tracks the preimages of hashes and names of bytestrings, and then run that in iguana.

Here's a basic example: https://github.com/be-cash/iguana/blob/master/examples/p2reversepk/src/main.rs

While the basic idea is super cool and it works quite well for me, it's not easy to use IMO, and requires a lot of flaky setup.

However, I think now that we have ecash-lib, we could think about doing this in the future:

  • Adding a mode that traces preimages of hashes + the ability to name byte slices
  • Adding a DSL or so that describes Scripts with named stack items
  • Adding a Script interpreter that uses ecash-lib
  • Moving Iguana over to ecash-lib so it can be run with a simple npm install
  • Adding a playground mode to iguana so people can write scripts in there super quickly

Maybe we can hire Rosco Kalis for some of these? He's built CashScript (which I never use), but it's super cool and relatively easy to use. Not sure if he'd come to the "dark side" though, so to speak.

modules/ecash-agora/tests/oneshot.test.ts
181 ↗(On Diff #47523)

No; it's only required for the contract here, because we enforce the first two outputs here, and the third one can be filled in by the buyer, which is the one the NFT is sent to via the OP_RETURN.

Not sure if that makes a ton of sense but that's the "magic" of the Script

add readme
add user story to oneshot test

improve AgoraOneshot doc comments

@bot ecash-agora-integration-tests

Change tx version used in the Script to 2

bytesofman added inline comments.
modules/ecash-agora/README.md
3 ↗(On Diff #47536)

image.png (499×509 px, 472 KB)

try to dumb down as much as possible

afaik this will be the only place in the monorepo to document "Script covenant"

modules/ecash-agora/tests/oneshot.test.ts
225 ↗(On Diff #47536)

what does "rejected" mean here?

From the test, looks like the seller gets 79999 sats, and the buyer gets nothing?

or wait, I see -- chronik just rejects it outright?

So chronik nows if a tx doesn't meat script conditions? Is this a preflight check or a node rejection?

This revision now requires changes to proceed.Apr 30 2024, 21:43
modules/ecash-agora/src/oneshot.ts
72 ↗(On Diff #47523)

the complexity is such that I don't think "lack of simple tools" is the main problem

Even today, ETH maintains a high level of complexity -- yet still manages to attract large teams of talented developers. sometimes they even manage to write contracts that aren't hacked.

imo we need to focus on making the value proposition of new tech discoveries on utxo blockchains extremely clear. Devs come to ETH bc that's where the funding is. The funding is there bc that's where the trading activity is. The trading activity is there because there is a very clear "what's in it for me" for both buyers (traders) and sellers (liquidity providers / stakers).

So, we need to have a clear "what's in it for me" to traders. This is a good first step, since people like to quickly and easily create NFTs, and I think it's a safe assumption they would like this even more if they could also sell them.

Getting a uniswap-esque experience -- allowing users to make markets by providing liquidity in a trading pair -- would be another major win. The uniswap experience is quite complex, unreliable, can result in wild swings and losses -- and yet it still dominates the market and on many days exceeds $1 billion in volume.

modules/ecash-agora/README.md
3 ↗(On Diff #47536)

Not sure exactly why we're using the term covenant, but basically a covenant is a contract that doesn't need to be enforced by an authority, it simply becomes void once one party violates it.

I guess it's similar enough to Script, where the transaction gets rejected if one party violates it, or like in many more BTC-esque Scripts like a Hash-Timelock-Contract where if one party violates the terms, the other party can still recover the funds, without needing an arbiter.

I use "covenant" for everything Script related these days, partially because it sounds hip and based and "smart contract" sounds lame and cringe.

Also, we really wanna avoid legal misunderstandings, in two ways:

  • These are not actual contracts that have any legal binding, they're just smart locks on your UTXOs
  • FinCEN considers smart contracts like virtual ATMs, so they can do unlicensed money transmission if used inproperly, as the TornadoCash situation shows.

Bitcoin's "contracts" are fundamentally different from ETH's, esp. legally speaking; so I think using a different term seems like a good idea.

modules/ecash-agora/tests/oneshot.test.ts
225 ↗(On Diff #47536)

tbh kinda fun to see you reverse-engineering this whole thing over time, I actually that's the best way to transfer this knowledge

Yes, it gets rejected by the network, it violates consensus rules. The idea behind Agora is to write a Script in such a way that any tx that doesn't send the correct amounts to the correct parties is invalid in the "consensus rule" term.

Here, we use OP_EQUALVERIFY, which verifies that the actual outputs that are in the transaction match the ones the seller wants them to be—which translates to "buyer has to send seller X amount of XEC for these tokens".

I can go into more detail in the test, README or doc comments of AgoraOneshot if you'd like

modules/ecash-agora/tests/oneshot.test.ts
225 ↗(On Diff #47536)

README pls

amend the README.md to make it even more hip

fix first paragraph of README

@bot ecash-agora-integration-tests

green with a couple of nits in the readme

modules/ecash-agora/README.md
31 ↗(On Diff #47551)
35 ↗(On Diff #47551)
This revision is now accepted and ready to land.May 2 2024, 12:48
This revision was automatically updated to reflect the committed changes.