隔離見(jiàn)證

隔離見(jiàn)證的新簽名算法
Pay-to-Witness-Script-Hash (P2WSH)
區(qū)塊鏈中的隔離見(jiàn)證是什么匈庭?
深入比特幣原理(十五)——隔離見(jiàn)證(Segregated Witness)

交易結(jié)構(gòu)的區(qū)別

交易原始json數(shù)據(jù):

1帚呼、以1為開(kāi)頭的地址到以1為開(kāi)頭的地址
2暴备、以1為開(kāi)頭的地址到以3為開(kāi)頭的地址
3、以1為開(kāi)頭的地址到以bc為開(kāi)頭的地址
4央碟、以3為開(kāi)頭的地址到以1為開(kāi)頭的地址
5酱固、以3為開(kāi)頭的地址到以3為開(kāi)頭的地址
6、以3為開(kāi)頭的地址到以bc為開(kāi)頭的地址
7兔跌、以bc為開(kāi)頭的地址到以1為開(kāi)頭的地址
8、以bc為開(kāi)頭的地址到以3為開(kāi)頭的地址
9峡蟋、以bc為開(kāi)頭的地址到以bc為開(kāi)頭的地址
以bc為開(kāi)頭的地址到以bc為開(kāi)頭的地址(兩個(gè)輸入)

1坟桅、2相满、3、4桦卒、5立美、6相同
7、8方灾、9相同

Legacy交易結(jié)構(gòu):


Legacy交易結(jié)構(gòu)

隔離見(jiàn)證(Segregated Witness)交易結(jié)構(gòu):


隔離見(jiàn)證(Segregated Witness)交易結(jié)構(gòu)

結(jié)構(gòu)對(duì)比

對(duì)于那些沒(méi)有升級(jí)為支持隔離見(jiàn)證的節(jié)點(diǎn)來(lái)說(shuō)建蹄,他們?cè)讷@取到隔離見(jiàn)證交易時(shí)是完全感知不到的,因?yàn)閷?duì)于舊節(jié)點(diǎn)來(lái)說(shuō)裕偿,交易結(jié)構(gòu)并沒(méi)有改變洞慎。

對(duì)于升級(jí)為支持隔離見(jiàn)證的節(jié)點(diǎn)來(lái)說(shuō),他們不僅能看到屬于交易結(jié)構(gòu)中的內(nèi)容嘿棘,并且還能看到這筆交易結(jié)構(gòu)外部包含的一小塊信息劲腿,這里的信息才是隔離見(jiàn)證的信息。信息里鸟妙,包括了marker焦人、flag、witness三個(gè)部分重父。
marker和flag都是標(biāo)記花椭,marker要求必須是1個(gè)字節(jié)的0,即0x00房午,flag要求必須是1字節(jié)的非0值矿辽,目前是0x01。
witness就是隔離見(jiàn)證(SegWit)中的見(jiàn)證(Wit)郭厌。即袋倔,對(duì)交易簽名。

P2PKH交易類(lèi)型的交易折柠,如果用了隔離見(jiàn)證宾娜,是什么樣子的:
witness:
scriptSig: (empty)
scriptPubKey: 0
我們可以看到,witness部分液走,存放的是之前解鎖工具里的東西碳默。scriptSig是指原交易結(jié)構(gòu)中的解鎖工具,隔離見(jiàn)證的交易里缘眶,此處置空嘱根。scriptPubKey是指那把鎖,也就是鎖定腳本巷懈,包含兩個(gè)部分该抒,一個(gè)是0,另一個(gè)是20個(gè)字節(jié)的加密數(shù)據(jù)顶燕。
0的意思凑保,是指隔離見(jiàn)證交易的版本號(hào)是0冈爹。未來(lái)可能會(huì)支持其它版本的交易。

這樣的話欧引,當(dāng)未升級(jí)的節(jié)點(diǎn)在進(jìn)行驗(yàn)證時(shí)频伤,發(fā)現(xiàn)解鎖腳本中竟然是空的,并且鎖定腳本也沒(méi)有什么CHECK相關(guān)的操作芝此,那么舊節(jié)點(diǎn)會(huì)認(rèn)為這個(gè)地址里的幣誰(shuí)都可以花憋肖,但并不符合標(biāo)準(zhǔn)的交易類(lèi)型,于是對(duì)于這種交易來(lái)說(shuō)婚苹,他會(huì)拒絕岸更, 對(duì)于包含這種交易的區(qū)塊來(lái)說(shuō),會(huì)驗(yàn)證通過(guò)膊升。(復(fù)雜的比特幣升級(jí)分析(4)里講過(guò)為什么對(duì)交易拒絕怎炊,對(duì)區(qū)塊接受)

對(duì)于升級(jí)了的節(jié)點(diǎn),首先要驗(yàn)證鎖定腳本里開(kāi)頭是不是0廓译,如果是0评肆,判斷后面的是不是20個(gè)字節(jié)。如果是责循,再去用witness里的公鑰經(jīng)過(guò)HASH160加密后與鎖定腳本中的20字節(jié)數(shù)據(jù)對(duì)比是否一致糟港。如果一致,再用witness中的私鑰簽名與公鑰通過(guò)CHECKSIG操作進(jìn)行驗(yàn)證院仿,是否會(huì)返回TRUE。

采用P2PKH交易類(lèi)型的隔離見(jiàn)證交易稱(chēng)為P2WPKH速和,即pay-to-witness-public-key-hash歹垫。
采用P2SH交易類(lèi)型的隔離見(jiàn)證交易稱(chēng)為P2WSH,即pay-to-witness-script-hash颠放。
原文鏈接 隔離見(jiàn)證交易的結(jié)構(gòu)排惨、規(guī)則、驗(yàn)證過(guò)程
復(fù)雜的比特幣升級(jí)分析(4)

區(qū)塊分析

比特幣交易中的簽名與驗(yàn)證
比特幣原始交易解析
隔離驗(yàn)證交易解析
比特幣中對(duì)交易進(jìn)行簽名的詳細(xì)過(guò)程

腳本類(lèi)型 簽名驗(yàn)證的規(guī)則

簽名方式:

P2PKH(1),     // pay to pubkey hash (aka pay to address)
P2PK(2),      // pay to pubkey
P2SH(3),      // pay to script hash
P2WPKH(4),    // pay to witness pubkey hash
P2WSH(5),     // pay to witness script hash
P2WPKHSH(6),  // P2WPKH nested in P2SH
普通腳本類(lèi)型 隔離見(jiàn)證腳本類(lèi)型
P2PKH(Pay-to-Public-Key-Hash) P2WPKH(Pay-to-Witness-Public-Key-Hash)
P2PK(Pay-to-Public-Key)
P2SH(Pay-to-Script-Hash) P2WSH(Pay-to-Witness-Script-Hash)

區(qū)塊鏈中的隔離見(jiàn)證是什么碰凶?

不同地址生成過(guò)程

交易簽名流程

構(gòu)建交易信息:

fun buildTransaction(unspentOutput: UnspentOutput, toAddress: String, feeRate: Int, sortType: TransactionDataSortType): FullTransaction {
     交易信息實(shí)體
    val mutableTransaction = MutableTransaction(false)
    
    recipientSetter.setRecipient(mutableTransaction, toAddress, unspentOutput.output.value, mapOf(), false)
    添加輸入信息
    inputSetter.setInputs(mutableTransaction, unspentOutput, feeRate)
    lockTimeSetter.setLockTime(mutableTransaction)
    添加接受地址和金額
    outputSetter.setOutputs(mutableTransaction, sortType)
    簽名信息
    signer.sign(mutableTransaction)

    return mutableTransaction.build()
}

普通交易:

    / / 秘鑰處理過(guò)程
    val networkParameters = NetParamsService.getNetworkParameters(wallet.chainType)
    val bytes = WalletManager.getBtcPriKey(wallet.keystore, password)
    val xprv = String(bytes, Charset.forName("UTF-8"))
    val xprvKey = DeterministicKey.deserializeB58(xprv, networkParameters)
    val privateKey = xprvKey.privKey
    val ecKey = ECKey.fromPrivate(privateKey)
    val tran = Transaction(networkParameters)

    val totalMoney = feeDelegate.getTotalAmount()
    val amount = feeDelegate.getAmount()
    val fee = feeDelegate.getFee()

    val changeAmount = totalMoney - amount - fee
    // 添加收賬地址和金額數(shù)據(jù)
    tran.addOutput(Coin.valueOf(amount), Address.fromString(networkParameters, toAddress))
    // 添加找零地址輸出
    if (changeAmount > DUST_THRESHOLD) {
        tran.addOutput(Coin.valueOf(changeAmount), Address.fromString(networkParameters, wallet.getAddress()))
    }
    // 添加輸入信息和簽名信息
    for (output in feeDelegate.getOutputs()) {
        val transactionOutPoint = TransactionOutPoint(networkParameters, output.vout.toLong(), Sha256Hash.wrap(output.txHash))
        //這個(gè)添加簽名輸入的最后一個(gè)參數(shù)就是添加了SIGHASH_FORKID(0x40)
        tran.addSignedInput(transactionOutPoint, Coin.valueOf(BigDecimal(output.amount).toLong()),
                Script(NumericUtil.hexToBytes(output.scriptPubKey)), ecKey, Transaction.SigHash.ALL, true, isFork())
    }
    // 交易字節(jié)數(shù)據(jù)轉(zhuǎn)化
    val signedHex = NumericUtil.bytesToHex(tran.bitcoinSerialize())
    val txHash = NumericUtil.beBigEndianHex(Hash.sha256(Hash.sha256(signedHex)))

隔離見(jiàn)證普通交易

    // 添加收賬地址和轉(zhuǎn)賬金額
    mutableTransaction.recipientAddress = addressConverter.convert(toAddress)
    mutableTransaction.recipientValue = value
    
    // 添加inputs信息
    fun setInputs(mutableTransaction: MutableTransaction, feeRate: Int, senderPay: Boolean, sortType: TransactionDataSortType) {
    val value = mutableTransaction.recipientValue
    val dust = dustCalculator.dust(changeScriptType)
    val unspentOutputInfo = unspentOutputSelector.select(
            value,
            feeRate,
            mutableTransaction.recipientAddress.scriptType,
            changeScriptType,
            senderPay, dust,
            mutableTransaction.getPluginDataOutputSize()
    )
    
    // 對(duì)未花費(fèi)的消費(fèi)列表進(jìn)行排序
    val sorter = transactionDataSorterFactory.sorter(sortType)
    val unspentOutputs = sorter.sortUnspents(unspentOutputInfo.outputs)

    // 添加inputs 信息并簽名
    for (unspentOutput in unspentOutputs) {
        mutableTransaction.addInput(inputToSign(unspentOutput))
    }

    mutableTransaction.recipientValue = unspentOutputInfo.recipientValue

    // Add change output if needed
    // 添加找零地址
    unspentOutputInfo.changeValue?.let { changeValue ->
        val changePubKey = publicKeyManager.changePublicKey()
        val changeAddress = addressConverter.convert(changePubKey, changeScriptType)

        mutableTransaction.changeAddress = changeAddress
        mutableTransaction.changeValue = changeValue
    }

    pluginManager.processInputs(mutableTransaction)
}

 // 添加outputs
 fun setOutputs(transaction: MutableTransaction, sortType: TransactionDataSortType) {
    val list = mutableListOf<TransactionOutput>()

    transaction.recipientAddress.let {
        list.add(TransactionOutput(transaction.recipientValue, 0, it.lockingScript, it.scriptType, it.string, it.hash))
    }

    transaction.changeAddress?.let {
        list.add(TransactionOutput(transaction.changeValue, 0, it.lockingScript, it.scriptType, it.string, it.hash))
    }

    if (transaction.getPluginData().isNotEmpty()) {
        var data = byteArrayOf(OP_RETURN.toByte())
        transaction.getPluginData().forEach {
            data += byteArrayOf(it.key) + it.value
        }

        list.add(TransactionOutput(0, 0, data, ScriptType.NULL_DATA))
    }

    val sorted = transactionDataSorterFactory.sorter(sortType).sortOutputs(list)
    sorted.forEachIndexed { index, transactionOutput ->
        transactionOutput.index = index
    }

    transaction.outputs = sorted
}

以上代碼基于unstoppable錢(qián)包源碼分析

錢(qián)包生成的隔離見(jiàn)證的數(shù)據(jù)

02000000000101ce846254bb6eeb32e71b8c1710da46fd91b4b9de50ba638f138e7eac7dae19be000000001716001488828e4385c9d7b31767ec24b0d8eb335cd3f13bffffffff02102700000000000017a914ec4341563a037db8ad7d5a756243d76f5d625d0a876c2200000000000017a914ec4341563a037db8ad7d5a756243d76f5d625d0a8702473044022040b0b80a733be983593eb6c22ac324c1326ef9e604cda45150f1f0c3c3a5a502022052a4c82d59c12e3a9bb0e498ade9edd4ff47a9e24fed73d7bd7234ed3b8808970121029741dc8ec4561502b884e20ef743a85e346a0aa95bb2ef2885f81f60addd620800000000

可以通過(guò)這里

附錄:
隔離見(jiàn)證由以下BIPs定義:
BIP-141隔離見(jiàn)證的主要定義
BIP-143版本0見(jiàn)證程序的交易簽名驗(yàn)證
BIP-144對(duì)等服務(wù)——新的網(wǎng)絡(luò)消息和序列化格式
BIP-145隔離見(jiàn)證(對(duì)于礦工)的 getblocktemplate 升級(jí)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暮芭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子欲低,更是在濱河造成了極大的恐慌辕宏,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砾莱,死亡現(xiàn)場(chǎng)離奇詭異瑞筐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)腊瑟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)聚假,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)块蚌,“玉大人,你說(shuō)我怎么就攤上這事膘格∏头叮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵瘪贱,是天一觀的道長(zhǎng)纱控。 經(jīng)常有香客問(wèn)我,道長(zhǎng)政敢,這世上最難降的妖魔是什么其徙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮喷户,結(jié)果婚禮上唾那,老公的妹妹穿的比我還像新娘。我一直安慰自己褪尝,他們只是感情好闹获,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著河哑,像睡著了一般避诽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上璃谨,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天沙庐,我揣著相機(jī)與錄音,去河邊找鬼佳吞。 笑死拱雏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的底扳。 我是一名探鬼主播铸抑,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衷模!你這毒婦竟也來(lái)了鹊汛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤阱冶,失蹤者是張志新(化名)和其女友劉穎刁憋,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體熙揍,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡职祷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片有梆。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡是尖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泥耀,到底是詐尸還是另有隱情饺汹,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布痰催,位于F島的核電站兜辞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏夸溶。R本人自食惡果不足惜逸吵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缝裁。 院中可真熱鬧扫皱,春花似錦、人聲如沸捷绑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)粹污。三九已至段多,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壮吩,已是汗流浹背进苍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸭叙,地道東北人琅捏。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像递雀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚀浆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345