Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zkVM POC: Port an ordinals indexer to zkVM #3

Closed
nud3l opened this issue Aug 25, 2023 · 2 comments
Closed

zkVM POC: Port an ordinals indexer to zkVM #3

nud3l opened this issue Aug 25, 2023 · 2 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request prio:high Important due to deadlines and/or clear customer needs/benefits. roadmap
Milestone

Comments

@nud3l
Copy link
Contributor

nud3l commented Aug 25, 2023

Is your feature request related to a problem? Please describe.
One major drawback of overlay protocols like ordinals is that the data is not subject to Bitcoin consensus and thus BRC20 and ord NFT require additional verification by some entity. In practice, these are either trusted third parties or some form of committees that act as TTP. There are several issues with this as the TTP or committee can change the way the data is interpreted and in the committee setting, disagreements might occur between the members which would require implementing some form of consensus protocol to resolve the disagreements.

Describe the solution you'd like
zkVM allows executing off-chain code written in Rust with an on-chain component in Solidity. It might be an avenue to enable Rust off-chain contracts together with a counterpart Solidity contract on the EVM side.

Port an ordinals indexer to zkVM. Porting an indexer in zkVM is an alternative to using some form of committee/TTP. zkVM would allow anyone to submit a bitcoin block that includes some ordinals following various standards and then verify that the ordinals inside are correctly processed by the indexer. The STARK proof can be verified by anyone and zkVM also gives you back return values, e.g., BRC20 deposits/withdrawals between a rollup that would support zkVM. If eventually BTC would support a ZK verify op code, you could also verify it there.

The approch is inspired by Zeth (https://www.risczero.com/news/zeth-release) to work with ord indexers/bitcoin instead of ethereum.

My hope is to understand the following:

@nud3l nud3l added documentation Improvements or additions to documentation enhancement New feature or request prio:high Important due to deadlines and/or clear customer needs/benefits. labels Aug 25, 2023
@nud3l nud3l added this to the BOB-PoC milestone Aug 25, 2023
@nud3l nud3l mentioned this issue Aug 30, 2023
12 tasks
@nud3l nud3l changed the title Try writing the BRC21 contracts in zkVM Port an ordinals indexer to zkVM Sep 11, 2023
@nud3l nud3l changed the title Port an ordinals indexer to zkVM zkVM POC: Port an ordinals indexer to zkVM Sep 11, 2023
@nud3l
Copy link
Contributor Author

nud3l commented Sep 14, 2023

Rust Starter template and Foundry template should have information on how to connect everything together.

Here are the best places to get started:
https://dev.risczero.com/bonsai/quickstart
https://github.com/risc0/risc0/tree/main/templates/rust-starter
https://api.bonsai.xyz/swagger-ui/

@gregdhill
Copy link
Contributor

gregdhill commented Sep 29, 2023

Joint investigation by @gregdhill and @sander2:

Port an ordinals indexer to zkVM

Allow anyone to submit a bitcoin block that includes some ordinals following various standards and then verify that the ordinals inside are correctly processed by the indexer

If we use the existing SPV relay to prove a block is valid, then parsing any inscriptions inside that block is trivial. The issue is with ordinals and determining their lineage, which depends on the contents of previous blocks. To do this in zkVM we need to store state similar to how Bitcoin Core / ord keeps the transaction history.

The problem is that we cannot store state in zkVM since it only verifies computation. Any state has to be passed as input, ZETH does this by passing a (succinct) DB state and then verifies block construction over that. We cannot feasibly supply this state via Solidity since it is too big - we would have to pass both the full Bitcoin block (~4 MB) and the ordinals DB of the previous block (this would contain the latest state of every ordinal at that height).

There exists one workaround:

  1. zkVM guest program updates Ordinal DB + outputs hash of DB state (Solidity relay stores the hash in the callback)
  2. Off-chain component submits Ordinal DB state. After completion, it stores the new DB and the Solidity contract waits for callback to update latest hash
  3. We need to maintain linearly growing list of Ordinal state hashes for future verification and somehow handle forks
  4. User wants to verify Ordinal transfer at some height (provides state hash and transaction) we still can’t submit Ordinal state via Solidity so we require two-step process:
    1. User requests proof of transfer (emit event containing Ordinal state hash and Txid)
    2. Off-chain client reads the event and calls bonsai on behalf of the user, fetching the ordinal state given the hash and passing it to the guest program.
    3. Solidity contract registers callback which passes the result back, guest program emits Ordinal state hash for verification

Problems

  • Massively complicated, we don’t really know how the source Ordinal indexer stores state and how it accesses bitcoin state - sequentially building from blocks vs using existing RPCs (either way significant refactorings are required)
  • Off-chain client needs to store copies of the Ordinal database for every block (separate DA layer - need to incentivize)
    Might need DoS protection somehow? We need to prevent useless runs since each call is potentially very expensive)
  • This doesn’t support BRC20s which requires a separate indexer
    • There is no BRC20 indexer written in Rust

NOTE: We can already use zkVM for some other problems, for example we were able to move the OKD logic into a guest program. It was not possible to use the rust-bitcoin secp256k1 C lib due to compilation issues but for a toy example the Parity library worked well.

BRC20

The goal of verifying BRC-20 transfers can be achieved in one of three ways:

  • Add indexing support to Ordinal indexer above
  • Build separate BRC20 indexer in Solidity
    • Iterate over every transaction in Block
    • (again) problem with fork handling
    • Potentially expensive
  • Focus on BRC20 swaps (again in Solidity - below)
  1. Seller puts order with inscription (taproot UTXO) containing brc20 transfer + amount
  2. Buyer checks (off-chain) that brc20 balance is valid and accepts
  3. Seller spends that output and provides proof (we check it transfers the linked output and the new inscription is valid)

This is very simple to build but there are a few caveats:

  • The buy order requires another step to accomplish the same thing (the buyer needs to accept the seller’s offer)
  • We cannot provide partial fulfilment - the amount sent must be that shown in step 1
  • Off-chain verification is not ideal but we can use the unisat API in the UI

@nud3l nud3l closed this as completed Oct 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request prio:high Important due to deadlines and/or clear customer needs/benefits. roadmap
Projects
Archived in project
Development

No branches or pull requests

2 participants