Ordinals

1 bitcoin = 100,000,000 satoshis(亿)

初始时每个区块奖励 50 个比特币。

A sat has an output that contains it.

A satpoint consists of an outpoint, i.e., a transaction ID and output index, with the addition of the offset of the ordinal within that output.

satoshis 按挖出的顺序编号;

转账时输入和输出一一对应,first-in-first-out;

  • 可以在钱包端编辑对应关系;
  • 采用 Ordinals 规则,历史上的区块也都是编号的,并且 ordinals 随着交易在不同持有者间发生流转;
[2] [1] [3] → [4] [2]
[a b] [c] [d e f] → [? ? ? ?] [? ?]
[a b] [c] [d e f] → [a b c d] [e f]

Fees paid by transactions are treated as extra inputs to the coinbase transaction, and are ordered how their corresponding transactions are ordered in the block.

[2] [1] [3] → [4]
[a b] [c] [d e f] → [a b c d]
[SUBSIDY] [e f] → [SUBSIDY e f]
# subsidy of block at given height
def subsidy(height):
  return (50 * 100_000_000) >> (height // 210_000) # floor division

# first ordinal of subsidy of block at given height
def first_ordinal(height):
  start = 0
  for height in range(height):
    start += subsidy(height)
  return start

# assign ordinals in given block
def assign_ordinals(block):
  first = first_ordinal(block.height)
  last = first + subsidy(block.height)
  coinbase_ordinals = list(range(first, last))

  # 只有 coinbase 交易的区块,只创建出了 coinbase_ordinals 范围内的 ordinals;
  # 包含普通交易的区块创建出了,创建出 coinbase_ordinals 范围内的 ordinals 的同时,
  # 把 inputs 中的 ordinals(之前挖矿过程创建出来的)依次分配给 outputs,最后剩下的 gas fee 分配给矿工;
  for transaction in block.transactions[1:]:
    ordinals = []
    for input in transaction.inputs:
      ordinals.extend(input.ordinals) 

    for output in transaction.outputs:
      output.ordinals = ordinals[:output.value] # output.value 指定转出的 satoshis 数量
      del ordinals[:output.value]

    coinbase_ordinals.extend(ordinals)

  for output in block.transaction[0].outputs:
    output.ordinals = coinbase_ordinals[:output.value]
    del coinbase_ordinals[:output.value]

Inscriptions

Inscription content is entirely on-chain, stored in taproot script-path spend scripts.

Taproot scripts have very few restrictions on their content, and additionally receive the witness discount, making inscription content storage relatively economical.

Since taproot script spends can only be made from existing taproot outputs, inscriptions are made using a two-phase commit/reveal procedure. First, in the commit transaction, a taproot output committing to a script containing the inscription content is created. Second, in the reveal transaction, the output created by the commit transaction is spent, revealing the inscription content on-chain.

Inscription content is serialized using data pushes within unexecuted conditionals, called “envelopes”. Envelopes consist of an OP_FALSE OP_IF … OP_ENDIF wrapping any number of data pushes. Because envelopes are effectively no-ops, they do not change the semantics of the script in which they are included, and can be combined with any other locking script.

OP_FALSE
OP_IF
  OP_PUSH "ord"
  # OP_1 indicates that the next push contains the content type
  OP_1
  OP_PUSH "text/plain;charset=utf-8"
  # OP_0 indicates that subsequent data pushes contain the content itself
  OP_0
  OP_PUSH "Hello, world!"
OP_ENDIF

Multiple data pushes must be used for large inscriptions, as one of taproot’s few restrictions is that individual data pushes may not be larger than 520 bytes.

The inscription content is contained within the input of a reveal transaction, and the inscription is made on the first sat of its first output.

Working with inscriptions requires a Bitcoin full node, to give you a view of the current state of the Bitcoin blockchain, and a wallet that can create inscriptions and perform sat control when constructing transactions to send inscriptions to another wallet.

SegWit

Segregated Witness 实质上是扩容,将区块大小从 1MB 扩大到 4MB。

旧交易的组成:outputs,inputs,signatures + witness scripts

新区块:

  1. 1MB base block
    • 交易的 signatures + witness scripts 被移到 extended block,对于未升级的节点而言,尽管交易的这两个部分是空的,仍是合法交易;
    • witness 占据交易 65% 的空间;
  2. 3MB extended block
    • 新交易 ID 的计算不再包含 signatures + witness scripts,解决了篡改未确认交易的 ID 的问题(transaction malleability issue);
    • 未升级的节点不会受到 extended block;

这样的好处是不用硬分叉。

segwit 地址 3 开头,旧地址 1 开头。

https://www.youtube.com/watch?v=d82-MPwpiYs

https://www.youtube.com/watch?v=f3CFUbeehc8

taproot

Taproot erases the distinction between a payment-to-a-public-key and a payment-to-a-script.

增强隐私性;

merkle root

https://youtu.be/nf_GCdCaQww?t=614

brc-20

Procedures:

  • Create a brc-20 with the deploy function;
  • Mint an amount of brc-20’s with the mint function;
  • Transfer an amount of brc-20’s with the transfer function;

brc-20 balance state can be found by aggregating all of these functions’ activity together.

Mints provide a balance to only the first owner of the mint function inscription.

Transfers deduct from the senders balance and add to the receivers balance, only upon the first transfer of the transfer function.

Deploy:

{ 
  "p": "brc-20",        // protocol name
  "op": "deploy",       // deploy, mint, transfer
  "tick": "ordi",       // 4 letter identifier of the brc-20
  "max": "21000000",    // max supply of the brc-20
  "lim": "1000",        // (Optional) Mint limit: If letting users mint to themsleves, limit per ordinal
  "dec": "18",          // (Optional) set decimal precision, default to 18
}

Mint:

{ 
  "p": "brc-20",
  "op": "mint",
  "tick": "ordi",
  "amt": "1000"         // Amount to mint: States the amount of the brc-20 to mint. Has to be less than "lim"
}

Transfer:

{ 
  "p": "brc-20",
  "op": "transfer",
  "tick": "ordi",
  "amt": "100"
}

A better standard:

  • being able to distribute tokens in the deploy transaction (e.g. to the token founder);
  • using a data structure that wouldn’t consume as much block space as JSON;

op

https://www.youtube.com/watch?v=sWnNNZ8MlUg


References