Slide 1

Slide 1 text

OP_CATとSchnorrトリックを利用した 
 コベナンツ 


Slide 2

Slide 2 text

1 OP_CAT
 スタック上の2つの要素を連結するシンプルなopcode 
 Bitcoinの初期に存在したものの、2010年に 
 実行時に大量のメモリ消費をさせる攻撃が可能なことから無効化 
 <1 byte> OP_DUP OP_CAT OP_DUP OP_CAT …
 【BIP347】
 TapscriptのOP_SUCCESS系 opcodeにOP_CATを割り当てるソフトフォークの提案 
 Tapscriptの制限により、連結したデータのサイズが520 byteに制限されるため、メモリDoSも回避 
 https://github.com/bitcoin/bips/blob/master/bip-0347.mediawiki


Slide 3

Slide 3 text

2 Schnorrトリック
 【Schnorr署名のスキーム】
 ● 秘密鍵:x、公開鍵:P = xG(Gは楕円曲線のベースポイント) 
 ● メッセージ:m
 
 1. ランダムなnonce kを選択し、
 2. R = kGを計算
 3. e = H(P || R || m) を計算
 4. s = k + exを計算
 5. (R, s)がSchnorr署名
 
 
 https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html 
 【Schnorrトリック】
 P = R = G に固定する、つまりx = k = 1 
 生成されるSchnorr署名はs = 1 + e 
 (G, 1 + e) 
 sの値が署名対象のメッセージダイジェストに 1を加算した値になる 
 
 このSchnorr署名の検証をパスするためには、 
 トランザクションが指定された形式( m)になっている必要がある 
 つまり、コベナンツが可能になる! 


Slide 4

Slide 4 text

3 OP_CAT × Schnorrトリック
 Lock Script Spending Tx In コベナンツUTXO Out 規定の宛先、規定の金額 witness ● 適用するアウトプットのデータ 
 ○ ロックスクリプト
 ○ 金額
 ● コベナンツスクリプト 
 
 OP_2DUP OP_SWAP OP_CAT OP_SWAP OP_CHECKSIG 
 ● コベナンツUTXOの参照情報 
 ○ OutPoint
 ○ nSequence
 ● nLocktime
 1. ロックスクリプトとwitnessのデータから OP_CAT を利用してスタック上で Txを組み立て
 2. OP_SHA256 でハッシュH(P || R || m) を計算し、
 3. コベナンツスクリプトによりSchnorrトリックを使って 
 Spending Tx がTxと同じになることを検証 


Slide 5

Slide 5 text

4 OP_CAT × Schnorrトリック
 OP_2DUP OP_SWAP OP_CAT OP_SWAP OP_CHECKSIG 
 
 Schnorr署名のデータの一部となる Txをハッシュしたデータ sが提供された際のスタックの動作 
 s
 G
 s
 G
 s
 G
 s
 G
 s
 s
 G
 G
 s
 Gs
 Gs
 s
 G
 
 OP_2DUP
 OP_SWAP
 OP_CAT
 OP_SWAP
 OP_CHECKSIG 
 s
 G = P→公開鍵
 Gs = (R, s)→ Schnorr署名
 Schnorrトリックによる署名検証 
 


Slide 6

Slide 6 text

5 +1対応
 実際にはsの値はTxのハッシュ+1の値である必要がある 
 
 
 1. witnessで提供する値(nSequenceやnLocktimeなど)を変更しながら 
 H(P || R || m) の最下位byteが0x01 で終わるようなTxを見つける(平均256回の試行) 
 ※ 最下位byteが0x01 であれば、sの値の最下位byteは 0x02 になる
 2. witnessに追加で、H(P || R || m) の上位31byteを提供させ(仮に σとする)
 3. OP_CAT を使用して、
 a. σ || 01 がTxのハッシュと一致するか OP_EQUALVERIFY で検証し、
 b. σ || 02 を使ってSchnorrトリックの署名を検証させる 


Slide 7

Slide 7 text

6 ECDSAトリック
 【ECDSA署名のスキーム】 
 ● 秘密鍵:x、公開鍵:P = xG (Gは楕円曲線のベースポイント) 
 ● メッセージ:m
 
 1. ランダムなnonce kを選択し、
 2. R = kG を計算し、
 3. RのX座標をrとする
 4. s = (H(m) + r × x)/k 
 5. (r, s) がECDSA署名 
 
 
 https://gist.github.com/RobinLinus/9a69f5552be94d13170ec79bf34d5e85 
 https://techmedia-think.hatenablog.com/entry/2024/12/03/142109 
 【ECDSAトリック】
 k = 1, R = G、x = 1/r, P = (1/r)G と固定する
 生成されるECDSA署名はs = H(m) + 1 
 (G, H(m) + 1) 
 sの値が署名対象のメッセージダイジェストに 1を加算した値になる 
 
 このECDSA署名の検証をパスするためには、 
 トランザクションが指定された形式( m)になっている必要がある 
 つまり、コベナンツが可能になる!