diff --git a/src/mining/coinbase.go b/src/mining/coinbase.go index d555e1e..b382e49 100644 --- a/src/mining/coinbase.go +++ b/src/mining/coinbase.go @@ -18,7 +18,6 @@ func NewCoinbaseTransaction(fees int) txn.Transaction { var zeroTxid [32]byte t := txn.Transaction{} t.Version = CoinbaseTransactionVersion - t.Locktime = 0 vin := txn.Vin{} vin.IsCoinbase = true @@ -26,31 +25,83 @@ func NewCoinbaseTransaction(fees int) txn.Transaction { vin.Vout = int(MaxVoutIndex) // push 3 bytes, 951a06 - which is the block height vin.ScriptSig = "03951a06" - vin.ScriptSigAsm = "PUSH_3 951a06" vin.Sequence = math.MaxUint32 t.Vin = append(t.Vin, vin) vout := txn.Vout{} // OP_TRUE - anyone can redeem this vout.ScriptPubKey = "51" - vout.ScriptPubKeyAsm = "OP_TRUE" vout.Value = BlockSubsidy + fees t.Vout = append(t.Vout, vout) return t } +var WitnessMagicBytes = []byte{ + 0x6a, + 0x24, + 0xaa, + 0x21, + 0xa9, + 0xed, + } + +func AddWitnessCommitmentX(coinbaseTx *txn.Transaction, + blockTxns []*txn.Transaction) []byte { + + var witnessNonce [32]byte + coinbaseTx.Vin[0].Witness = []string{hex.EncodeToString(witnessNonce[:])} + + // Next, obtain the merkle root of a tree which consists of the + // wtxid of all transactions in the block. The coinbase + // transaction will have a special wtxid of all zeroes. + witnessMerkleRoot := CalcMerkleRoot(blockTxns, true) + + // The preimage to the witness commitment is: + // witnessRoot || coinbaseWitness + var witnessPreimage [64]byte + copy(witnessPreimage[:32], witnessMerkleRoot[:]) + copy(witnessPreimage[32:], witnessNonce[:]) + + // The witness commitment itself is the double-sha256 of the + // witness preimage generated above. With the commitment + // generated, the witness script for the output is: OP_RETURN + // OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading + // prefix is referred to as the "witness magic bytes". + witnessCommitment := utils.DoubleHashRaw(witnessPreimage[:]) + witnessScript := append(WitnessMagicBytes, witnessCommitment[:]...) + + // Finally, create the OP_RETURN carrying witness commitment + // output as an additional output within the coinbase. + commitmentOutput := txn.Vout{ + Value: 0, + ScriptPubKey: hex.EncodeToString(witnessScript), + } + coinbaseTx.Vout = append(coinbaseTx.Vout, + commitmentOutput) + + return witnessCommitment[:] +} + +/* + What parts are all involved in witness commitment? + 1. Calculation of Merkle root + 2. Witness Commitment = HASH256(witnessMerkleRoot | witnessNonce) + 3. Add (Witness Magic Bytes | Witness commitment) as the ScriptPubKey of the last output in the coinbase transaction + +*/ func AddWitnessCommitment(coinbase *txn.Transaction, txns []*txn.Transaction) error { var witnessNonce [32]byte coinbase.Vin[0].Witness = append(coinbase.Vin[0].Witness, WitnessReserveHexString) + // assuming that the merkle root is right witnessMerkleRoot := CalcMerkleRoot(txns, true) var witnessPreimage [64]byte copy(witnessPreimage[:32], witnessMerkleRoot[:]) copy(witnessPreimage[32:], witnessNonce[:]) witnessCommitment := utils.DoubleHashRaw(witnessPreimage[:]) - witnessCommitment = [32]byte(utils.ReverseBytes(witnessCommitment[:])) + witnessCommitment = [32]byte(witnessCommitment[:]) witnessScript := []byte{ // OP_RETURN 0x6a, diff --git a/src/mining/merkle_tree.go b/src/mining/merkle_tree.go index 4261e35..c045af0 100644 --- a/src/mining/merkle_tree.go +++ b/src/mining/merkle_tree.go @@ -13,7 +13,7 @@ func HashMerkleBranches(left, right *[32]byte) [32]byte { copy(hash[:32], left[:]) copy(hash[32:], right[:]) - return [32]byte(utils.DoubleHash(hash[:])) + return [32]byte(utils.DoubleHashRaw(hash[:])) } // rollingMerkleTreeStore calculates the merkle root by only allocating O(logN) diff --git a/src/mining/mining.go b/src/mining/mining.go index 44d59e5..c73b606 100644 --- a/src/mining/mining.go +++ b/src/mining/mining.go @@ -42,7 +42,7 @@ func GetCandidateBlock(txns []*txn.Transaction, hasWitness bool) Block { } if(hasWitness){ - AddWitnessCommitment(&cb, blockTxns) + AddWitnessCommitmentX(&cb, blockTxns) } candidateBlock.Coinbase = cb