Bitcoin Transaction - Part One

Transaction是什么墓造?

我們隨意看一個(gè)最簡(jiǎn)單的Transaction昆箕,看看什么是Transaction晰韵。在block exploper中經(jīng)過(guò)簡(jiǎn)單的查詢一個(gè)經(jīng)典的txid 7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18惹挟,可以看到蒲凶,他到底是什么气筋。

0100000001524d288f25cada331c298e21995ad070e1d1a0793e818f2f7cfb5f6122ef3e71000000008c493046022100a59e516883459706ac2e6ed6a97ef9788942d3c96a0108f2699fa48d9a5725d1022100f9bb4434943e87901c0c96b5f3af4e7ba7b83e12c69b1edbfe6965f933fcd17d014104e5a0b4de6c09bd9d3f730ce56ff42657da3a7ec4798c0ace2459fb007236bc3249f70170509ed663da0300023a5de700998bfec49d4da4c66288a58374626c8dffffffff0180969800000000001976a9147f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a888ac00000000

上邊是一個(gè)Transaction的hex邀泉,但是到底是什么意思呢豪墅?如何將其decode,可以看的比較明白运怖。

{
    hash 7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18
    inputs
    {
        input
        {
            address_hash 54a28c6ba2bebdb694fe487a87e3e8ed4eab1502
            previous_output
            {
                hash 713eef22615ffb7c2f8f813e79a0d1e170d05a99218e291c33daca258f284d52
                index 0
            }
            script "[3046022100a59e516883459706ac2e6ed6a97ef9788942d3c96a0108f2699fa48d9a5725d1022100f9bb4434943e87901c0c96b5f3af4e7ba7b83e12c69b1edbfe6965f933fcd17d01] [04e5a0b4de6c09bd9d3f730ce56ff42657da3a7ec4798c0ace2459fb007236bc3249f70170509ed663da0300023a5de700998bfec49d4da4c66288a58374626c8d]"
            sequence 4294967295
        }
    }
    lock_time 0
    outputs
    {
        output
        {
            address_hash 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8
            script "dup hash160 [7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8] equalverify checksig"
            value 10000000
        }
    }
    version 1
}

一個(gè)典型的bitcoin transaction由兩部分組成灵巧,input和output搀矫,input是這筆transaction的輸入,output是輸出刻肄。首先看input瓤球,因?yàn)閎itcoin是utxo model所以一個(gè)的輸出是另一transaction的輸出。仔細(xì)看上邊的trasaction肄方,input中有一個(gè)script冰垄,output中另外一個(gè)script,那么script是什么呢?

input中的script是unlocking script虹茶, output中的script是locking script逝薪。為什么說(shuō)input中的script是unlocking script呢?因?yàn)樗墙怄i上一筆transaction的output蝴罪。也就是說(shuō)礦工在verify transaction的時(shí)候董济,會(huì)找到utxo(上一筆交易的output中的locking script)如果unlocking script + locking script 返回的結(jié)果是true那么這個(gè)錢就能花了。具體來(lái)看看是怎么回事要门。

下邊是一個(gè)例子是典型的一個(gè)P2PKH Transaction的unlocking script + locking script虏肾,假設(shè)Alice在第n個(gè)transaction中,有一筆utxo欢搜,然后她在弟n+1筆transaction中將其花出封豪。那么她的unlocking script是在第n+1筆 transaction的input中,locking script是在第n的output中炒瘟。這一點(diǎn)一定要注意一下吹埠。

unlocking + locking

在圖中的PubkeyHash是Alice的公鑰Hash,Sig是Alice的簽名疮装,Pubkey是Alice的公鑰缘琅。所以如果手動(dòng)運(yùn)行一下這個(gè)script,那么得到的結(jié)果是什么呢廓推?

執(zhí)行結(jié)果

如果手動(dòng)運(yùn)行一下得到的結(jié)果是True刷袍。所以那么Alice就可以用這筆錢了。所以現(xiàn)在比較明確了為什么output中的script是locking script樊展,因?yàn)檫@個(gè)transaction將這個(gè)筆錢lock在一個(gè)publicKey中呻纹,只有你證明你是這個(gè)私鑰的owner你才能動(dòng)這筆錢,反過(guò)來(lái)這個(gè)key的owner因?yàn)橛兴借€专缠,通過(guò)簽名可以解鎖這筆錢居暖。所以通過(guò)這樣的方式把錢lock了起來(lái),Locking script由此得名藤肢。Brilliant!

是不是有另一問(wèn)題糯景?

上邊介紹transaction的基本的結(jié)構(gòu)嘁圈,那么這里有一個(gè)問(wèn)題是,那么簽名到底簽的是什么蟀淮,如果可以隨意簽名最住,例如簽名一個(gè)hello world,miner如何驗(yàn)證呢怠惶?第二如果簽名數(shù)據(jù)可以是一個(gè)任意的數(shù)據(jù)那么如果hacker or other任意修改locking script呢涨缚?本來(lái)是給A的,hacker or others給了B策治?這樣是否可能脓魏?或者如何應(yīng)對(duì)這個(gè)問(wèn)題兰吟?

第一個(gè)問(wèn)題,首先簽名簽的是transaction 或者說(shuō)是transaction的一部分 or hash茂翔,這樣miner就可以知道如何驗(yàn)證簽名了混蔼。

第二問(wèn)題,這就引出了sign的type珊燎。bitcoin中的sign hash Type有這幾種惭嚣。

SIGHASH flag Value Description 類比
ALL 0x01 Signature applies to all inputs and outputs 基本類型,from 和 to都簽名
NONE 0x02 Signature applies to all inputs, none of the outputs 空白支票悔政,收款人隨便填
SINGLE 0x03 Signature applies to all inputs, none of the outputs inputs全簽晚吞,output只簽一個(gè)

另外還有其他的modifier

SIGHASH flag Value Description 類比
ALL_ANYONECANPAY 0x81 Signature applies to one input and all outputs 募資transaction,outputs鎖定
NONE_ANYONECANPAY 0x82 Signature applies to one input, none of the outputs 空白支票谋国,output隨便
SINGLE_ANYONECANPAY 0x83 Signature applies to one input and the output with the same index number inputs全簽槽地,output只簽一個(gè)

一般說(shuō)最近基本的transaction sign hash type 就是ALL,看一下具體的代碼中的實(shí)現(xiàn)。

// TODO: remove keyPair.network matching in 4.0.0
  if (keyPair.network && keyPair.network !== network)
    throw new TypeError('Inconsistent network');
  if (!inputs[vin]) throw new Error('No input at index: ' + vin);

  hashType = hashType || Transaction.SIGHASH_ALL;
  if (needsOutputs(hashType)) throw new Error('Transaction needs outputs');

  const input = inputs[vin];

  // if redeemScript was previously provided, enforce consistency
  if (
    input.redeemScript !== undefined &&
    redeemScript &&
    !input.redeemScript.equals(redeemScript)
  ) {
    throw new Error('Inconsistent redeemScript');
  }

tx_builder

    const txTmp = this.clone();

    // SIGHASH_NONE: ignore all outputs? (wildcard payee)
    if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
      txTmp.outs = [];

      // ignore sequence numbers (except at inIndex)
      txTmp.ins.forEach((input, i) => {
        if (i === inIndex) return;

        input.sequence = 0;
      });

      // SIGHASH_SINGLE: ignore all outputs, except at the same index?
    } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
      // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60
      if (inIndex >= this.outs.length) return ONE;

      // truncate outputs after
      txTmp.outs.length = inIndex + 1;

      // "blank" outputs before
      for (let i = 0; i < inIndex; i++) {
        txTmp.outs[i] = BLANK_OUTPUT;
      }

      // ignore sequence numbers (except at inIndex)
      txTmp.ins.forEach((input, y) => {
        if (y === inIndex) return;

        input.sequence = 0;
      });
    }

    // SIGHASH_ANYONECANPAY: ignore inputs entirely?
    if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
      txTmp.ins = [txTmp.ins[inIndex]];
      txTmp.ins[0].script = ourScript;

      // SIGHASH_ALL: only ignore input scripts, leave all the outputs
    } else {
      // "blank" others input scripts 
      txTmp.ins.forEach(input => {
        input.script = EMPTY_SCRIPT;
      });
      txTmp.ins[inIndex].script = ourScript;
    }

    // serialize and hash
    const buffer: Buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4);
    buffer.writeInt32LE(hashType, buffer.length - 4);
    txTmp.__toBuffer(buffer, 0, false);

tx_build_sign

private __byteLength(_ALLOW_WITNESS: boolean): number {
    const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();

    return (
      (hasWitnesses ? 10 : 8) +
      varuint.encodingLength(this.ins.length) +
      varuint.encodingLength(this.outs.length) +
      this.ins.reduce((sum, input) => {
        return sum + 40 + varSliceSize(input.script);
      }, 0) +
      this.outs.reduce((sum, output) => {
        return sum + 8 + varSliceSize(output.script);
      }, 0) +
      (hasWitnesses
        ? this.ins.reduce((sum, input) => {
            return sum + vectorSize(input.witness);
          }, 0)
        : 0)
    );
  }

tx, outs

上述的的代碼實(shí)現(xiàn)中烹卒,可以看出默認(rèn)的hashType是ALL闷盔,所以上邊提的問(wèn)題,就可以通過(guò)這樣的方式解決旅急,但是這么看hash Type中各種形式可以用于實(shí)現(xiàn)不同的功能逢勾。

最后看看unlocking scirpt的中簽名是什么。

3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e381301

簽名是DER格式的藐吮。

  • 0x30—indicating the start of a DER sequence

  • 0x45—the length of the sequence (69 bytes)

  • 0x02—an integer value follows

  • 0x21—the length of the integer (33 bytes)

  • R—00884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb

  • 0x02—another integer follows

  • 0x20—the length of the integer (32 bytes)

  • S—4b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813

  • A suffix (0x01) indicating the type of hash used (SIGHASH_ALL)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溺拱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谣辞,更是在濱河造成了極大的恐慌迫摔,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泥从,死亡現(xiàn)場(chǎng)離奇詭異句占,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)躯嫉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門纱烘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人祈餐,你說(shuō)我怎么就攤上這事擂啥。” “怎么了帆阳?”我有些...
    開(kāi)封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵哺壶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)山宾,這世上最難降的妖魔是什么至扰? 我笑而不...
    開(kāi)封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮塌碌,結(jié)果婚禮上渊胸,老公的妹妹穿的比我還像新娘。我一直安慰自己台妆,他們只是感情好翎猛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著接剩,像睡著了一般切厘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上懊缺,一...
    開(kāi)封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天疫稿,我揣著相機(jī)與錄音,去河邊找鬼鹃两。 笑死遗座,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的俊扳。 我是一名探鬼主播途蒋,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼馋记!你這毒婦竟也來(lái)了号坡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤梯醒,失蹤者是張志新(化名)和其女友劉穎宽堆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體茸习,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畜隶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了号胚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片代箭。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涕刚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乙帮,我是刑警寧澤杜漠,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響驾茴,放射性物質(zhì)發(fā)生泄漏盼樟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一锈至、第九天 我趴在偏房一處隱蔽的房頂上張望晨缴。 院中可真熱鬧,春花似錦峡捡、人聲如沸击碗。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稍途。三九已至,卻和暖如春砚婆,著一層夾襖步出監(jiān)牢的瞬間械拍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工装盯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坷虑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓埂奈,卻偏偏與公主長(zhǎng)得像迄损,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挥转,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容