ビットコインスクリプトを知っている人なら誰でも、それが一連の計算命令(つまりオペコード)とデータで構成されていることを知っています。スクリプトの実行は、命令を使用してデータに対して操作を実行するプロセスです。つまり、このプログラムの入力は、実行される前に決定されます。十分に「柔軟性」がないため、多くの人が無意識のうちにその機能の範囲も非常に限られていると考えるのは、まさにこの設定のためです。
今日紹介したいのは、実際にこの固定観念を打ち破り、スクリプトの力と興味をより深く理解できるようにすることです。
スクリプトが実行されている現在のトランザクションデータにスクリプトがアクセスできるように、アルゴリズムを設計しました。これをOP_PUSH_TXと呼びます。これは、現在のトランザクションを疑似オペコードのようにスタックに置くことができます。ビットコインのネイティブスクリプトにコンパイルできる高級言語であるsCryptを使用して実装しました。例を使用して、OP_PUSH_TXの使用法を示します。
OP_CHECKSIG
OP_CHECKSIGは、ECDSA署名を検証するために使用される操作コードです。理論的には、次の2つのステップが含まれます。
- 現在のトランザクションは、ハッシュ値を計算します。
- このハッシュ値に対して署名検証を実行します。
手順1のハッシュ値は現在のトランザクションのハッシュ値にしかなり得ないため、OP_CHECKSIGは、署名されたデータが現在のトランザクションのハッシュ値である場合にのみ正常に機能することに注意してください。他のデータへの署名は正しく機能しません。
OP_PUSH_TX
概要概要
通常、OP_CHECKSIGで使用される署名はオフチェーンで生成され、パラメーターとしてロック解除スクリプトに渡されます。現在のトランザクションにアクセスするために、代わりにスクリプトを使用してチェーン上の署名を直接計算します。このため、パラメータとしてロック解除スクリプトに渡されるのは、署名ではなく、現在のトランザクションです。署名の計算に使用されるECDMA公開鍵と秘密鍵のペアも、パラメータとしてロック解除スクリプトに渡されます。現在のトランザクションパラメータと秘密鍵パラメータを使用して、ECDMA署名を計算でき、OP_CHECKSIGは公開鍵パラメータを使用して計算された署名を検証できます。検証に合格すると、ロック解除スクリプトで渡された現在のトランザクションパラメータが実際の現在のトランザクションであることが確認できます。OP_CHECKSIGは、署名されたデータが現在のトランザクションのハッシュ値である場合にのみ渡されるためです。
詳細
スクリプトを使用してOP_PUSH_TXを実装するためのアルゴリズムは次のとおりです。
- 現在のトランザクションをスタックの一番上に置きます。
- 秘密鍵をスタックの一番上に置きます(秘密鍵はスクリプトで公開され、署名の計算にのみ使用され、ビットコインを制御しません)。
- スクリプトでECDSA署名アルゴリズムを実行し、手順1と2でスタックに配置されたトランザクションと秘密鍵を使用して署名を計算します。
- 手順2の秘密鍵に対応する公開鍵をスタックの一番上に置きます。
- OP_CHECKSIGを実行します。
ステップ1、2、および4はロック解除スクリプトにあり、ステップ3および5はロックスクリプトにあります。
最初のステップ5場合OP_CHECKSIGを介して署名を確認し、その後、我々は、現在のトランザクションによりOP_CHECKSIG署名検証なるので、現在のトランザクションのステップ1でスタック上に配置されたトランザクションパラメータは、実際に真であることを確認することができる1。OP_CHECKSIGは、署名がチェーン外の外部プログラムによって生成されたのか(P2PKHの場合のように)、チェーン上のスクリプトによって生成されたのか(OP_PUSH_TXの場合のように)を気にしません。
手順2の秘密鍵は注目に値します。通常、秘密鍵は秘密にされますが、スクリプトでは公開されています。この秘密鍵はビットコインを制御せず、署名計算に参加して、ステップ1のパラメーターが実際に現在のトランザクションであることを証明するだけなので、これは問題ありません。実際、この秘密鍵は再利用することもできます。
Sighash Preimage
より正確には、ステップ1のトランザクションは、完全な現在のトランザクションデータではなく、完全なデータから生成されたプリイメージです。後続の計算では、2つのSHA256操作が実行されます。プレイメージフォーマットは次のように事前に決定されています。
入力スクリプトは含まれていないことに注意してください。
成し遂げる
sCryptは、OP_PUSH_TXアルゴリズムを実装し、それを標準のコントラクト関数Tx.checkPreimage
にカプセル化して、着信パラメーターが現在のトランザクションのプリイメージであるかどうかを確認します。のは、例を示しましょう。私たちは、開発するためにそれを使用する契約と呼ばれるCheckLockTimeVerifyその中にコインがに似た一定の時間、前に費やすことができないようにすることができ、OP_CLTVを。検証に合格すると(つまりrequire(Tx.checkPreimage(sighashPreimage))
)、現在のトランザクションのデータにアクセスできます。
contract CheckLockTimeVerify {
int matureTime;
public function spend(bytes sighashPreimage) {
// this ensures the preimage is for the current tx
require(Tx.checkPreimage(sighashPreimage));
// parse nLocktime
int len = length(sighashPreimage);
int nLocktime = this.fromLEUnsigned(sighashPreimage[len - 8 : len - 4]);
require(nLocktime >= this.matureTime);
}
function fromLEUnsigned(bytes b) returns (int) {
// append positive sign byte. This does not hurt even when sign bit is already positive
return unpack(b + b'00');
}
}
拡張する
OP_PUSH_TXを使用すると、コントラクトコードは、すべての入力と出力を含むトランザクションデータ全体にアクセスできます。契約では、これらのデータに任意の制約を設定できます。これにより、ビットコインネットワーク上でさまざまなスマートコントラクトを実行するための無限の可能性が開かれます。今後、さらに多くの例を示します。
この記事は、ビットコインのスマートコントラクトで何ができるか、そしてその方法を説明する一連の記事の最初の記事です。
ありがとう
オリジナルのアイデアを提供してくれたnChainに特に感謝します。
ハッシュの衝突がない限り(2つの異なる情報が同じハッシュ値を持っている)、この衝突はほとんど不可能であると見なされます。デジタル署名では、署名されたデータは情報自体ではなく、情報のハッシュ値です。↩︎