Code Monkey home page Code Monkey logo

runestone's Introduction

runestone

This repo was for discussion of runes, a fungible token protocol for Bitcoin.

Fungible tokens are, without exaggeration and nearly without exception, a vile abyss of hopium, scams, and incompetence.

Runes are no different.

If you want to make money, buy bitcoin.

Runes has been implemented in ord, so all discussions, issues, and PRs should be directed there.

runestone's People

Contributors

bitspill avatar casey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

runestone's Issues

TODO: Payload Sentinel Value/Signature

"Finalize the payload signature. In order to discourage the proliferation of incompatible issuance transactions, this implementation uses a push of the bytes "RUNE_TEST" after an OP_RETURN to indicate a rune payload. This is intended to be temporary, and should be changed to a final."

Allocate input runes evenly to outputs

For a transaction with N outputs, given a transfer of [ID, AMOUNT, N] and M non OP_RETURN outputs, each non OP_RETURN output receives AMOUNT / M runes.

This allows evenly distributing runes to a large number of outputs, without having include a transfer in the runestone for each output.

Variable offers

Some of this has been discussed in #46 and #21.

Fixed offers are quite trivial, you put the runes you want to sell into a UTXO, then you sign a PSBT that spends that UTXO and pays you the sale price. The completed transaction looks like:

BTC_INPUT  | RUNE_OUTPUT
RUNE_INPUT | BTC_OUTPUT

However, that requires transferring a fixed number of runes for sale into UTXO. There should be some way of making a "variable offer", where you don't need to transfer runes to a separate UTXO.

I can't think of a way where a seller can commit to both a runestone and an output paying them BTC in a PSBT.

One idea is that you transfer some amount of runes in one step using a runestone that gives the exchange rate, and then, you use that UTXO as input to another transaction. However, you need to make sure the buyer can't do anything but supply btc and take their runes. So, for example, they can't insert their own runestone which modifies the transfer of runes.

Write `ord wallet etch`

Only support sending the output UTXO out of the wallet, and make it clear it's a test command, since the wallet won't initially support properly managing UTXOs with runes.

TODO: Select Activation Blockheight

"Decide on an activation height. The degens will surely REEEEEE loudly if there are any shenanigans around launch of the protocol. The best way to avoid this is to define an activation height well into the future."

Display rune on /rune/RUNE

  • block in which rune was etched
  • transaction in which rune was etched
  • associated inscription, if any
  • supply
  • block height
  • transaction index
  • id

Thoughts on Future Soft Forks vs Hard Forks

Curious if you have any thoughts on how Runestone could be upgraded in the future, and if there's a way to make it more likely that a great universe of things will be soft forks rather than hard forks.

Rune Metadata

Currently, rune metadata consists of the rune itself, and its divisibility. Divisibility is encoded as a 128 bit integer, but only 6 bits are needed since ceil(log2(len(str((1 << 128 - 1))))) == 6.

That leaves 122 unused bits. We should do something fun with them. I propose:

  • Foreground color: 12 bits
  • Background color: 12 bits
  • Currency symbol: 17 bits
  • Logo: 81 bits

Colors are 4 bits for red, green, and blue, and can be expressed as three-digit hex colors, e.g., #FFF for white.

Foreground and background color can be used on /rune pages. Probably not as background and foreground colors for the page, since that might be completely illegible, but we can use it for something else.

The currency symbol is a unicode symbol, like $, for displaying balances. 17 bits cover the Basic Multilingual Plane and the Supplementary Multilingual Plane, which max out at 0x1FFFF.

The logo is a 9x9 pixel bitmap, where on bits are the foreground color, and off bits are the background color.

IDEA: ADD INSCRIPTION TXID REF

RUNE is outside of Ordinals.
Add standard (could be additional tx output) to point to an inscription ID.
This allows easy association with broader Bitcoin content such as image, full metadata, contracts, anything.

Archive this repo

Since the index is being implemented in ord, this repo is a bit superfluous. I like using it for the initial discussion though, to avoid a lot of noise in the ord repo. We can archive this repo once the implementation is finished and all the issues are resolved.

Allow issuance to not specify rune, and receive shortest available rune?

A naive implementation would have to iterate backwards over the rune table every time an issuance didn't specify a rune.

A more sophisticated implementation would have to maintain a table of ranges of unallocated runes, and split/shrink them when a rune is allocated, and remove ranges when the last rune is allocated in a range.

Inscription metadata in rune deploy.

What if there was a way to do a inscription when a rune is deployed. You could inscribe the rune logo and additional metadata when a rune is created.

TODO: Determine Protocol Feasibility

"Decide whether or not I should do this at all. Fungible tokens are almost entirely meritless. However, alternative fungible token standards, like BRC-20, have a large on-chain footprint and have lead to a proliferation of UTXOs, and standards with no on-chain footprint have UX challenges and have been slow to see adoption."

Finalize activation parameters

This includes an activation block height, as well as finalizing the runestone signature.

Activation height:

  • The activation height is initially un-announced.
  • When the implementation is complete we will announce the activation height.
  • When it is announced, it will be at least 2016 blocks (144 * 14, the length of a difficulty adjustment) in the future.
  • It will fall on a difficulty adjustment, since that seems more auspicious.
  • This gives everyone a fortnight to prepare.

TODO: Define asset ID format

"Decide whether or not the ID of an asset is a sequentally assigned ID, or based on the block height and transaction index of the issuance transaction. The former is more compact, but the latter is less ambiguous and allows for compact SPV proofs."

Finalize varint implementation

  • Do we want a varint implementation, or variable length byte strings? The latter could be advantageous if we want to have byte string fields that are not numbers.
  • Should we use a bijective encoding? A bijective encoding makes test vectors more complex.
  • Should we use something which is more efficient given that we know what the distribution of numbers is likely to be? E.g., encodes zero as less than a single byte, encodes the distribution more efficiently.

Consider renaming Rune ID to Rune Pointer

Current rune IDs are a combination of block height and transaction offset. IDs are usually hashes, and we may want to refer to the txid of the transaction in which a rune is created as the "rune ID". Perhaps Rune ID should instead be called something like "rune pointer", so we can have both concepts.

Figure out how PSBTs work

Offering runes for sale via PSBT should be quite simple.

First, the seller transfers the runes for sale to output RUNE_INPUT. They then sign for RUNE_INPUT using SIGHASH_SINGLE | ANYONECANPAY committing to an output BTC_OUTPUT paying themselves the sale price.

The buyer then completes the transaction by supplying an input for the sale price, BTC_INPUT, along with an output to receive the runes, RUNE_OUTPUT.

The buyer puts their input and output first. Since the completed transaction has no runestone, all input runes transfer to to the first output, RUNE_OUTPUT.

The completed transaction looks like:

BTC_INPUT  | RUNE_OUTPUT
RUNE_INPUT | BTC_OUTPUT

Open Etching

Distribution via burn: after creation, some amount of un-allocated coins can be claimed by burning sats. Can be boxed to a certain block height after creation. (Credit to windsock on twitter.)

Note to self: One thing I dislike about BRC-20 style airdrops is that they aren't amenable to SPV proofs. E.g, you have to see every single transaction to know whether or not a mint transaction is valid. However, with burns that are limited to a block height, if the restriction is in place that even if every single sat is burned, you won't overflow the token maximum value, then you know that every single burn within a block range is valid, even if you don't see every single transaction.

You could support BRC-20 style airdrops that didn't require a burn if you ensured that even if every single transaction was a BRC-20 airdrop, it wouldn't overflow the max token value. This would require bounding by height, or by using such a low value that even if every transaction was a mint, until the end of time, you wouldn't overflow the token max value.

Some interesting questions:

  • How to specify exchange rate: runes/sat or sats/rune
  • Given an exchange rate, what is the minimum supply?
  • How to represent a max block height?
  • If rune A and rune B both require burning sats, you should need to burn sats for both.
  • If burn amount is 0, then we must ensure that even if all transactions up to stop height are mints, supply cannot be overflowed.
  • Add maximum mint amount per transaction.

The Wacky Zone

What are some wacky mechanics that runes might support? Crazy ideas welcome.

Some ideas:

  • Gambling. The result of a transaction depends on the hash of the block it is included in. So you can make a transaction which assigns runes to either the first or second output, and you don't know which output the runs are assigned to until the transaction is mined. Opens the door to MEV, so maybe not worth it. Some way of putting in a vig, i.e., a house edge, would be good, so people are incentivized to run literal shitcoin casinos.

  • Air drops. Right now, I think the best way to do this is with the ability to distribute tokens to outputs evenly. If this were combined with OP_CTV, you could create large fan out transactions, ending in a large number of anyone can spend outputs with an even number of tokens, with the cost of minting fully pushed to minters, since they need to pay the fees to splay out the tree of transactions to get to the anyone-can-spend outputs. This can be done without OP_CTV, but in this case the cost of issuing is on the issuer.

  • Some kind of efficient market making mechanic. Of course, you can create a whole bunch of PSBTs for different lot sizes, and maybe that's the best option. However, there could also be a mode where you put in X amount of rune Y, define a Y/BTC exchange ratio, and then the market taker puts in their own BTC input, and the tokens in the outputs are distributed according to how much BTC they put in. This would avoid a proliferation of PSBTs.

  • Yield. People love fucking yield, and they love shitcoin yield. One fundamentally hard part of yield is that you get more of the token than you put in. I guess a rune could have an additional parameter which states, if you don't move the runes for a particular amount of time, an interest rate, and you get more runes out when you eventually spend the UTXO. This has weird interactions with supply, and with a capped supply. I guess yield could come from whatever the un-allocated initial supply was. So you can run out of the source of yield if you yield out the full amount of the initial un-allocated supply.

  • Ponzi schemes. People fucking love ponzi schemes. I guess ponzi schemes are a form of yield where getting the yield isn't guaranteed. So it might emerge naturally from the above yield scheme, where you have a pool of coins you can get yield from, but when they're gone, they're gone, so if you're the last to move your coins, you only get what you put in, which is now worth dramatically less. Or maybe, it's a yield scheme, where the yield is taken out of the actual supply, so you might not get what you put in after a while.

  • Demmurage. Some people are insane about demmurage, and think it solves all kinds of problems. This could easily be implemented, with runes decaying according to some formula the longer they don't move. Let the wacky socialists have their weird demmurage experiments.

Airdrop without burn

We can also do an airdrop without burning sats. Such an airdrop must have a maximum amount of runes claimed per transaction such that the it cannot exceed the supply, even if all transactions from the etching to the block height in which the airdrop concludes were mints.

Define text representation of rune id

  • BLOCK/TX I like this, since it's similar to the familiar use of / in paths and URLs.
  • BLOCK.TX This works, but it conflicts with BLOCK.SAT for ordinals
  • BLOCK-TX

Ignore

"Decide on an activation height. The degens will surely REEEEEE loudly if there are any shenanigans around launch of the protocol. The best way to avoid this is to define an activation height well into the future."

TODO: Consider Space Efficient Output Format

"Decide whether or not we should encode transfer outputs as ceil(log2(output_count))-length bit strings instead of varints, since we know the number of transaction outputs. Saves space but somewhat tricky."

Use tags for extensibility

Currently, the etching is one or two trailing varints in the runestone, which are the rune, and a small amount of additional metadata. This is simple, but limits us to a small amount of metadata, and gives us limited extensibility. We might want additional metadata, or some way to extend or modify the protocol in the future, and using a separate push for the etching would make that easy.

Discussions on current TODO points

Decide whether or not I should do this at all. Fungible tokens are almost entirely meritless. However, alternative fungible token standards, like BRC-20, have a large on-chain footprint and have lead to a proliferation of UTXOs, and standards with no on-chain footprint have UX challenges and have been slow to see adoption.

You should, because otherwise others with no long-term thinking in mind will destroy the rune movement before it truly starts.

Finalize the varint encoding should be used. LEB128, VLQ, and a prefix varint are all contenders.

I am a large proponent of VLQ, it matches the UTF-8 endianness, and is used a lot everywhere.

Decide whether or not duplicate symbols are allowed.

I am in favor or duplicate symbols, symbol alone is not sufficient for degens to ape in anyhow, gotta DYOR.

Decide if symbols should be restricted to be no longer than the most recently mined sat name.

This is only useful if we want to keep unique symbols, it could also be interesting to restrict symbol to the set of sat names burned into the OP_RETURN, that's an unambiguous way of enforcing uniqueness of symbol name, and driving secondary demand of sats for nice-sounding sat names.

Decide whether or not the ID of an asset is a sequentally assigned ID, or based on the block height and transaction index of the issuance transaction. The former is more compact, but the latter is less ambiguous and allows for compact SPV proofs.

I like block height and transaction index, but the only correct way of encoding this is 2 integers; there's no good future proof way of combining this into a single integer, and loses out the possibility of using ID deltas. Another possibility that is slightly less compact is to use the symbol itself as the ID (if it is unique).

Decide whether or not ID should be a delta, which would be more compact, but would require that transfers be encoded in increasing order of asset ID.

I like it, only because it generalizes using 0 ID to continue reusing the previous rune ID as opposed to making 0 be a special case. (And in practice, people won't really care to handle multiple rune types in a single transaction, so its more about protocol consistency more than anything else).

Decide whether or not we should encode transfer outputs as ceil(log2(output_count))-length bit strings instead of varints, since we know the number of transaction outputs. Saves space but somewhat tricky.

This only practically saves space in the 128-255 outputs scenario, where the output could be encoded as 1 byte instead of 2. Given that the protocol doesn't really allow us to specify that many transfer instructions anyways due to 83 byte limitation in OP_RETURN output, I don't see this as being a practical saving only varint consistency.

Decide whether or not an amount of 0 in a transfer should be a shorthand for all remaining runes.

Not sure if this is necessary, since all remaining runes gets transferred to first non-OP_RETURN output already; no need for duplicate ways to do the same thing.

Decide on an activation height. The degens will surely REEEEEE loudly if there are any shenanigans around launch of the protocol. The best way to avoid this is to define an activation height well into the future.

I like this, not only to avoid handling the noise that is being generated now, but also so that indexers don't need to arbitrarily start indexer from the beginning when in practice there's nothing there anyways.

Hope others will chime in and come to consensus here!

Documentation

  • A plain-english high-level description of runes, similar to the current inscription handbook.
  • A non-normative lower-level specification. The specification must explicitly state that it is non-normative, and that the behavior of the reference implementation is the normative spec. The consequence of this is that the spec may be amended to match the implementation, if they differ.

document:

  • new batchfile fields
  • etching, minting, sending commands
  • the ten genesis runes

Explain cenotaphs, how they function as an upgrade mechanism, and ways a cenotaph can be created:

  • Unrecognized even tag
  • Unrecognized flag
  • Edict with output greater than number of outputs
  • Edict with rune ID with block == 0 and tx > 0

Include:

  • SPV
  • Fraud proofs
  • Comparison with BRC-20, Counterparty, RGB, Taproot Assets, and ERC-20
  • All tags are reserved for the protocol. Unused tags may be given new meaning at any time.
  • Consider, instead of a specification, documenting the code extremely throughly

Use deltas for all edict fields

Edict id, amount, and vout are all be deltas. Id is always a delta, amount is a delta if the ID is the same as the last, and output is a delta if the amount is the same as the last.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.