Successfully calculating the wtxid merkle root, and the commitment header inside of a coinbase output

This commit is contained in:
Chris Stewart 2016-12-22 15:41:18 -06:00
parent 95cd5df9a9
commit 80d843e6a0
7 changed files with 57 additions and 32 deletions

View file

@ -2,7 +2,7 @@ package org.bitcoins.core.consensus
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.protocol.blockchain.Block
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.protocol.transaction.{BaseTransaction, Transaction, WitnessTransaction}
import org.bitcoins.core.util._
import scala.annotation.tailrec
@ -11,7 +11,7 @@ import scala.annotation.tailrec
* Created by chris on 5/24/16.
* This trait contains all functionality related to computing merkle trees
* Mimics this functionality inside of bitcoin core
* https://github.com/bitcoin/bitcoin/blob/master/src/consensus/merkle.cpp
* [[https://github.com/bitcoin/bitcoin/blob/master/src/consensus/merkle.cpp]]
*/
trait Merkle extends BitcoinSLogger {
@ -72,6 +72,28 @@ trait Merkle extends BitcoinSLogger {
val hash = CryptoUtil.doubleSHA256(bytes)
Node(hash,tree1,tree2)
}
/** Computes the commitment of the block to the wtxids
* See the definition of a block commitment in BIP141
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#commitment-structure]]
* [[https://github.com/bitcoin/bitcoin/blob/7490ae8b699d2955b665cf849d86ff5bb5245c28/src/consensus/merkle.cpp#L168]]
*/
def computeBlockWitnessMerkleTree(block: Block): MerkleTree = {
val coinbaseWTxId = CryptoUtil.emptyDoubleSha256Hash
val hashes = block.transactions.tail.map {
case wtx: WitnessTransaction => wtx.wTxId
case btx: BaseTransaction => btx.txId
}
build(coinbaseWTxId +: hashes)
}
/** Computes the merkle root for the committment inside of a coinbase txs scriptPubKey
* See BIP141
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#commitment-structure]]
* */
def computeBlockWitnessMerkleRoot(block: Block): DoubleSha256Digest = {
computeBlockWitnessMerkleTree(block).value.get
}
}
object Merkle extends Merkle

View file

@ -168,7 +168,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
val isNotSigHashSingle = !(HashType.isSIGHASH_SINGLE(hashType.num))
val isNotSigHashNone = !(HashType.isSIGHASH_NONE(hashType.num))
val inputIndexInt = inputIndex.toInt
val emptyHash = DoubleSha256Digest("0000000000000000000000000000000000000000000000000000000000000000")
val emptyHash = CryptoUtil.emptyDoubleSha256Hash
val outPointHash: Seq[Byte] = if (isNotAnyoneCanPay) {
val bytes: Seq[Byte] = spendingTx.inputs.flatMap(_.previousOutput.bytes)

View file

@ -10,29 +10,20 @@ import org.bitcoins.core.util.{BitcoinSLogger, Factory}
* Created by chris on 5/19/16.
* Represents a block in our blockchain
* Bitcoin Core implementation:
* https://github.com/bitcoin/bitcoin/blob/master/src/primitives/block.h#L73
* [[https://github.com/bitcoin/bitcoin/blob/master/src/primitives/block.h#L73]]
* Bitcoin Developer Reference link:
* https://bitcoin.org/en/developer-reference#serialized-blocks
* [[https://bitcoin.org/en/developer-reference#serialized-blocks]]
*/
sealed trait Block extends NetworkElement with BitcoinSLogger {
sealed trait Block extends NetworkElement {
/**
* The block header for this block
* @return
*/
/** The block header for this block */
def blockHeader : BlockHeader
/**
* The total number of transactions in this block,
* including the coinbase transaction.
* @return
*/
/** The total number of transactions in this block,
* including the coinbase transaction. */
def txCount : CompactSizeUInt
/**
* The transactions contained in this block
* @return
*/
/** The transactions contained in this block */
def transactions : Seq[Transaction]
override def hex = RawBlockSerializer.write(this)

View file

@ -60,6 +60,8 @@ trait CryptoUtil {
messageDigest.doFinal(out, 0)
RipeMd160Digest(out.toList)
}
val emptyDoubleSha256Hash = DoubleSha256Digest("0000000000000000000000000000000000000000000000000000000000000000")
}
object CryptoUtil extends CryptoUtil

File diff suppressed because one or more lines are too long

View file

@ -7,7 +7,7 @@ import org.bitcoins.core.script.ScriptProgram
import org.bitcoins.core.script.interpreter.ScriptInterpreter
import org.bitcoins.core.script.result.ScriptOk
import org.bitcoins.core.serializers.transaction.RawBaseTransactionParser
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, TestUtil}
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, CryptoUtil, TestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
import spray.json._
@ -58,12 +58,11 @@ class TransactionTest extends FlatSpec with MustMatchers with BitcoinSLogger {
val hex = "0100000000010115e180dc28a2327e687facc33f10f2a20da717e5548406f7ae8b4c811072f8560100000000ffffffff0100b4f505000000001976a9141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b92888ac02483045022100df7b7e5cda14ddf91290e02ea10786e03eb11ee36ec02dd862fe9a326bbcb7fd02203f5b4496b667e6e281cc654a2da9e4f08660c620a1051337fa8965f727eb19190121038262a6c6cec93c2d3ecd6c6072efea86d02ff8e3328bbd0242b20af3425990ac00000000"
val wtx = WitnessTransaction(hex)
wtx.txId.hex must be (BitcoinSUtil.flipEndianness("d869f854e1f8788bcff294cc83b280942a8c728de71eb709a2c29d10bfe21b7c"))
wtx.wTxId must be (CryptoUtil.doubleSHA256(hex))
}
it must "read all of the tx_valid.json's contents and return ScriptOk" in {
val source = Source.fromURL(getClass.getResource("/tx_valid.json"))

View file

@ -1,16 +1,13 @@
package org.bitcoins.core.script.constant
import org.bitcoins.core.script.crypto.OP_CHECKMULTISIGVERIFY
import org.bitcoins.core.script.interpreter.ScriptInterpreter
import org.bitcoins.core.script.{ScriptOperation, ScriptProgram}
import org.bitcoins.core.script.ScriptProgram
import org.bitcoins.core.script.bitwise.OP_EQUAL
import org.bitcoins.core.script.flag.{ScriptVerifyMinimalData, ScriptFlag}
import org.bitcoins.core.script.result.{ScriptErrorMinimalData, ScriptErrorBadOpCode}
import org.bitcoins.core.script.crypto.OP_CHECKMULTISIGVERIFY
import org.bitcoins.core.script.flag.{ScriptFlag, ScriptVerifyMinimalData}
import org.bitcoins.core.script.result.{ScriptErrorBadOpCode, ScriptErrorMinimalData}
import org.bitcoins.core.util.{ScriptProgramTestUtil, TestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
import scala.util.Try
/**
* Created by chris on 1/24/16.
*/