Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement BIPs 141, 142, 143, 145 and 147 (Segregated Witness) #656

Merged
merged 33 commits into from Aug 14, 2017

Conversation

@Roasbeef
Copy link
Member

@Roasbeef Roasbeef commented Apr 8, 2016

This PR makes several modifications across btcd, and many of the sub-packages in order to add compatibility for the upcoming Segregated Witness soft-fork. As the set of changes is rather expansive, this PR has been split up into several commits to in order to facilitate thorough code review of each change.

This PR currently implements the changes dictated by the following BIPS:

As of the writing of this PR description, with this patch set btcd is able to successful sync up, and correctly validate all blocks and witness commitments on Bitcoin'stestnet. This PR is still being extensively tested in order to ensure all new consensus critical decision related to transactions, blocks, and script validation are functioning properly.

The changes across all packages are briefly summarized below:

  • blockchain:
    • New functions have been added to calculate block, and transaction "cost".
    • The previous BuildMerkleTreeStore function is now able to calculate the witness merkle root. This allowed the creation of new functions to extract, and validate the witness commitment.
    • The new "cost" metrics are now used when validating blocks, and transactions.
    • The txscript.ScriptVerifyWitness is now used by default when validating transaction scripts. Once BIP9 support is in place, this will instead be gated by the appropriate versionbits stage threshold.
    • Script validation performed by txValidator now also uses the new HashCache in order to more efficiently validate inputs spending witness program outputs.
    • When checking BIP34 for blocks below height 16, we now attempt to extract just a small integer. This behavior never came when BIP34 was rolled out, as it was deployed around height 100k or so.
  • chaincfg:
    • The parameters for segnet4 have been added, along with the new address bytes for the new standard output types.
  • database:
    • Blocks, and transactions are always stored using the witness encoding if they have witness data. Additionally, all blocks are attempted to be decoded using the witness encoding.
  • peer:
    • Detecting if a peer supports segwit has been added.
    • A new queue function QueueMessageWithEncoding has been added in order to allow callers to specify the encoding type to use when serializing messages. This was required in order to allow callers to selectively send witness data to peers.
    • The MaxProtocolVersion has been increased to 70012 in order to signal to other peers we support segwit.
  • txscript:
    • Validation logic for p2wsh, p2wkh, and nested p2sh outputs have been added. In the process txscript.Engine now takes an optional HashCache as well as the input value of the output being spent.
    • Support for the new sighash digest algorithm defined in BIP143 has been added. In order to make full use of the new optimizations, a new caching structure, the HashCache has been introduced which caches partial sighashes to be re-used within the mempool, and block across all concurrent script validation goroutines.
    • New functions have been added to calculate sig op cost using the new sig op calculation introduced as part of segwit.
    • Several new utility functions have been introduced for analyzing, creating, and classifying the new standard output types.
  • wire:
    • The new SFNodeWitness service bit has been added along with new inventory types for segwit, and and increase in the MaxBlockPayload size.
    • New methods have been added to support the new encoding format for transaction with witness data. In the process, a new field has been added to the wire.Message interface in order to cleanly facilitate optinoally encoding or decoding the witness data. Finally, a new methods has been added to wire.MsgTx to compute the wtxid, and ascertain if a transaction has any witness data.
  • btcd itself:
    • Only peers supporting segwit are chosen to be the syncPeer.
    • All wire.MsgGetData sent will request with the new witness inv types by default. Additionally the new inv types are no longer ignored when received by other peers (TODO(roasbeef): thought they were only to be used within getdata?).
    • The new cost metrics are used across the mempool when validating transactions.
    • Peers created by the server advertise support for segwit.

Thanks to @T909 for the initial work which laid the base for much of this PR, along with coming up with the initial idea for the HashCache.

TODO

  • Implement BIP 145 support
  • Update the rpcserver, and btcjson to display the new transactions, and block related data. The display changes can be summarized as: display of witness data needs to be added to the transaction display, add a new hash field to show the wtxid, add vsize (virtual size) to transaction display, show cost for blocks.
  • Significantly improve test coverage across all packages which have been modified, or had new functionality introduced.
  • Integrate Bitcoin Core's new tests within script_tests.json
  • Integrate Bitcoin Core's segwit transaction tests within tx_valid.json, and tx_invalid.json
  • Add new, proper error messages within txscript.Engine to be returned when a new segwit specific error is encountered. At the moment, it returns some ad-hoc errors I created to facilitate debugging.
  • Clean up the new witness validation logic in txscript.Engine.
  • Update cpuminer.go, and the GBT logic to account for the new cost metrics.
  • Add test coverage for the new sig op counting code, and witness commitment validation code.
  • Once BIP 9 has been implemented for btcd, guard new seg wit behavior with a checking of the versionbits state.
  • Add passive partial sighash eviction to HashCache
  • Modify the addrindex, and txindex to enable support for fully indexing blocks with witness data.

Closes #962.

PrevBlock: wire.ShaHash{}, // 0000000000000000000000000000000000000000000000000000000000000000
MerkleRoot: segNetGenesisMerkleRoot, // 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
Timestamp: time.Unix(1452831101, 0), // 2016-01-15 04:11:41 +0000 UTC
Bits: 0x1e01ffff, // ?? [000007ffff000000000000000000000000000000000000000000000000000000]

This comment has been minimized.

@davecgh

davecgh Apr 8, 2016
Member

?? == 503447551

This comment has been minimized.

@davecgh

davecgh Apr 8, 2016
Member

Also, the bits equate to 000001ffff000000000000000000000000000000000000000000000000000000 as opposed to the value in the comment.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed. The value in the comment was left over from segnet3.

@@ -34,6 +34,10 @@ var (
// simNetPowLimit is the highest proof of work value a Bitcoin block
// can have for the simulation test network. It is the value 2^255 - 1.
simNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne)

// segnet4 has a pow limit of 1e01ffff which is 19 0-bits in front, I think

This comment has been minimized.

@davecgh

davecgh Apr 8, 2016
Member

It's 23 0-bits, but I'd prefer this to be consistent with the other comments:

    // segnet4PowLimit is the highest proof of work value a Bitcoin block
    // can have for the segregated witness test network.  It is the value
    // 2^233 - 1.

The math checks out: 2^233-1 == 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff which when compacted to the Bits representation is 0x1e01ffff as expected.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

@@ -272,6 +276,57 @@ var TestNet3Params = Params{
HDCoinType: 1,
}

// SegNet4Params defines the network parameters for the test Bitcoin network
// (version 4). Not to be confused with the regression test network, this
// network is sometimes simply called "testnet".

This comment has been minimized.

@davecgh

davecgh Apr 8, 2016
Member

This is "segnet", not "testnet", right? That is unless it's replacing testnet version 3.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Correct, removed the left over comment fragment from a copy-paste.

config.go Outdated
if cfg.SegNet4 {
numNets++
activeNetParams = &segNet4Params
}
if numNets > 1 {
str := "%s: The testnet, regtest, and simnet params can't be " +

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Need to update the error for the new network.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Done.

params.go Outdated
@@ -55,6 +55,13 @@ var simNetParams = params{
rpcPort: "18556",
}

// segNet4Params contains parameters specific to the simulation test network

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

to the simulation test ... -> to the segregated witness test ...

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

// new witness serialization defined in BIP0141. The final output is used within
// the Segregated Witness commitment of all the witnesses within a block. If a
// transaction has no witness data, then the witness sha, is the same as its txid.
func (msg *MsgTx) WitnessSha() ShaHash {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Can we call this WitnessHash?

I realize Sha is used in the other things and this is just being consistent, but I'd like to eventually change the funcs to be be XHash because I don't like that the algorithm is baked into the name since it might not always be using SHA.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fair point, I've changed the function name to WitnessHash.

var flag [1]byte
if count == 0 && pver == WitnessVersion {
// Next, we need to read the flag, which is a single byte.
if _, err = r.Read(flag[:]); err != nil {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

This needs to be io.ReadFull(r, flag[:]). Regular r.Read(flag[:]) does not enforce the byte to be read if it's not ready. That condition is also not an error (since the number of bytes read will simply be 0) and therefore this code, which is not checking the number of read bytes, could end up failing incorrectly when it checks the flag below and finds it to be 0x00 instead of 0x01 due to it not actually being read.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Great catch, I've changed the line to instead use io.ReadFull.

return messageError("MsgTx.BtcDecode", str)
}

// Wit the Segregated Witness specific fields decoded, we can

This comment has been minimized.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

// A count of zero (meaning no TxIn's to the uninitiated) indicates
// this is a transaction with witness data.
var flag [1]byte
if count == 0 && pver == WitnessVersion {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Shouldn't this be looking at msg.Version >= 2 rather than pver and a bogus WitnessVersion?

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

See comments below concerning the encoding type.

return err
}
}

// Prevent more input transactions than could possibly fit into a
// message. It would be possible to cause memory exhaustion and panics
// without a sane upper bound on this count.

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Need to verify if maxTxInPerMessage is still a constant under a witness-style transaction. The same goes for maxTxOutPerMessage. It might not have changed, but need to double check that since the tx structure did change.

@@ -300,6 +360,33 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error {
msg.TxOut[i] = &to
}

// If the transaction's flag byte isn't 0x00 at this point, then one
// or more of its inputs has accompanying witness data.
if flag[0] != 0 && pver == WitnessVersion {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Same here regarding msg.Version >= 2

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

See comments below concerning the encoding type.

// Then for witCount number of stack items, each item
// has a varint length prefix, followed by the witness
// item itself.
txin.Witness = make([][]byte, witCount)

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

The witCount needs to be checked against some type of sane maximum based on the max possible that could fit in a transaction. Otherwise it would be trivial for an attacker to craft a message with a huge varint encoded here to force a massive allocation of memory and crash the process.

Remember the first rule of reading data from external sources is you can never trust it.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Excellent suggestion. I've changed this fragment to limit the possible size of witCount.

// item itself.
txin.Witness = make([][]byte, witCount)
for j := uint64(0); j < witCount; j++ {
witPush, err := ReadVarBytes(r, pver, MaxMessagePayload,

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

I don't think MaxMessagePayload is a correct value here. At the very most, it would be limited by the maximum block size. A more accurate value would the maximum block size minus the minimum possible bytes it could take to encode the other fields assuming none of them have any data.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

I've opted to limit the maximum size of a witness element we'll read to just over the maximum size allowed for a single stack item. The rationale is that a transaction with a witness element over that size would be rejected during script execution anyway.

// encoded transaction format within r may possibly utilize the new serialization
// format created to encode transactions bearing witness data within inputs.
func (msg *MsgTx) DeserializeWitness(r io.Reader) error {
return msg.BtcDecode(r, WitnessVersion)

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

As mentioned above the transaction version should be used instead and then there is no need for a separate function. Plus, using the WitnessVersion is incorrect since DeserializeX, as mentioned elsewhere, is intended for the long term stable storage format for the database to which the network protocol version must not apply. It's fine (and preferable) if they happen to be the same encoding, but the distinction must be kept because future versions can change the serialization format on the wire, but it still must be able to read whatever the database format is.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

First, note that this is an outdated diff. In the latest version BtcDecode has gained an additional parameter which controls the encoding type.

Using the transaction version is insufficient, because this function might be deserializing the transaction encoded without the witness data because the transaction has been received from a non-upgraded peer. The server will never request the transaction from such a peer since it detects if it is witness enabled before sending the getdata message.

This comment has been minimized.

@davecgh

davecgh Apr 10, 2016
Member

Right, I realized you changed it as I got through the diffs and also read through the BIPs after making this comment, so I understand why the extra parameter is needed. Feel free to ignore this.

// MsgTx aren't 0x00, then this indicates the transaction is to be
// encoded using the new witness inclusionary structure defined in
// BIP0141.
if pver == WitnessVersion {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Again, this doesn't seem like a correct way to handle it. I would think it should be looking at msg.Version >= 2.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Note that this is an out dated diff. Looks I goofed a bit re-organizing the commits. I now utilize a separate wire.MessageEncoding field to gate this behavior.

// one. The second byte is the Flag field, which at the moment is
// always 0x01, but way be extended in the future to accommodate
// auxiliary non-commited fields.
w.Write([]byte{0x00})

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Errors are being ignored here. Bad!

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Also, I'd do a single write with a constant that has []byte{0x00, 0x01} along with the appropriate commenting to explain it.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Bad indeed :)

I now properly check the error. I've also condensed it down to a single write with both bytes.

server.go Outdated
if p.ProtocolVersion() >= wire.WitnessVersion &&
p.Services()&wire.SFNodeWitness == wire.SFNodeWitness {

sp.witnessEnabled = true

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

This will race since it's not protected by a mutex.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed, all variable access are now properly protected by a mutex.

witness := vm.tx.TxIn[vm.txIdx].Witness
if vm.witnessVersion == 0 {
switch len(vm.witnessProgram) {
case 20: // P2WKH

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Please use constants for this and the case below.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Done.

@@ -198,6 +205,8 @@ func (vm *Engine) curPC() (script int, off int, err error) {
return vm.scriptIdx, vm.scriptOff, nil
}

//func (vm *Engine) verifyWitnessProgram(uint version, wi

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

This appears to be left over. I suspect the intention was to factor the code out of Step which I think makes sense.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Yeah this was left over as an un-finished thought. I've extracted out the new code in Step to a separate function.

// stack, then append the pkScript
// generated above as the next script to execute.
vm.scripts = append(vm.scripts, pops)
vm.SetStack(witness)

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Doesn't this need to include the stack data from vm.savedFirstStack with the witness at the top of the stack (appended)? Otherwise it would wipe that data out. We need to carefully compare what Core does here because it's possible it's just wiping the stack out too, but it seems to me that it should be appended because a nested P2SH witness program could have other data pushed.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

This case will only be executed for p2wkh transactions. During core's execution, they start with an empty stack, then assign this stack variable to point to the transaction's included witness stack (vm.tx.TxIn[vm.txIdx.Witness). This verification is done locally within a separate function so there was nothing on the stack before hand. Therefore I feel this sections is correct for p2wkh programs. But as you point out, it's very important that we verify so.

The witness program for nested P2SH outputs must be the variant which pushes the 32-byte hash. So it will never execute this case which is reserved for p2wkh programs. To my current knowledge, when core validates nested P2SH outputs, it again calls the VerifyWitnessProgram function which begins with a fresh empty stack, assigning the stack to the transaction's provided witness data. Therefore once again the execution starts with solely the transaction's witness data on the stack. However, once the program execution concludes, the stack is resized forcing the stack to only contain a single value. This value is then checked for "truthyness", as well as the clean stack assertion.

My opinions of correct are drawn only from the fact that this branch currently sync successfully, and my my manual execution of p2wkh, p2wsh, and nested p2sh programs. However, of course there may be lingering edge cases this code doesn't yet address. Once I finish the lingering TODO's all add the new script, and transaction tests to ensure the code at least passes those additionally.

// set the pkScript to be the next script
// executed.
vm.scripts = append(vm.scripts, pops)
vm.SetStack(witness[:len(witness)-1])

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Same thing here regarding vm.savedFirstStack.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

See comment above.


// ExtractWitnessCommitment attempts to locate, and return the witness
// commitment for a block. The witness commitment is of the form:
// SHA256(witness root || witness nonce).The function additionally returns a

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Missing spaces after period.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

// The public key script that contains the witness commitment
// must shared a prefix with the WitnessMagicBytes, and be at
// least 38 bytes.
if bytes.HasPrefix(msgTx.TxOut[i].PkScript, WitnessMagicBytes) &&

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

This is more efficient to check the length of the script before comparing the bytes. Also, I'd create a local for pkScript in order to avoid the overhead of checking the array bounds multiple times.

    for i := len(msgTx.TxOut) - 1; i >= 0; i-- {
        // The public key script that contains the witness commitment
        // must shared a prefix with the WitnessMagicBytes, and be at
        // least 38 bytes.
        pkScript := msgTx.TxOut[i].PkScript
        if len(pkScript) >= 38 &&
            bytes.HasPrefix(pkScript, WitnessMagicBytes) {

            witnessCommitment = pkScript[6:38]
            witFound = true
        }
    }

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Also, I'd prefer named constants for all of these magic offsets and lengths.

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Probably doesn't matter, but I'm not really sure returning whether or not the witness commitment was found is worth it here. It's easy enough to do if len(witnessCommitment) == 0 { /* not found */ }

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

I've modified the code with your suggestions, including adding some new constants for the magic offsets, and lengths.

As you've probably seen within ValidateWitnessCommitment, if the coinbase doesn't have something which looks like a witness commitment within any of its outputs, then if the transactions within the block contain any witness data, then the block itself is invalid. Therefore it's necessary to also return if the commitment was found or not. Hmm, but I guess the function could simply return nil if the commitment was not found.

msgTx := tx.MsgTx()
if len(msgTx.TxIn[0].Witness) != 0 {
str := fmt.Sprintf("block contains transaction with witness" +
" data, yet not witness commitment present")

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

s/not/no/

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

len(coinbaseTx.MsgTx().TxIn[0].Witness[0]) != 32 {
str := fmt.Sprintf("the coinbase transaction must have exactly " +
"one item within its witness stack, and that item " +
"should be exactly 32-bytes")

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

s/should/must/

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Please separate the error messages here so that they contain more details such as:

    // At this point the block contains a witness commitment, so the
    // coinbase transaction MUST have exactly one witness element within
    // its witness data and that element must be exactly
    // CoinbaseWitnessDataLen bytes.
    coinbaseWitness := coinbaseTx.MsgTx().TxIn[0].Witness
    if len(coinbaseWitness) != 1 {
        str := fmt.Sprintf("the coinbase transaction has %d items in "+
            "its witness stack when only one is allowed",
            len(coinbaseWitness))
        return ruleError(ErrInvalidWitnessCommitment, str)
    }
    witnessNonce := coinbaseWitness[0]
    if len(witnessNonce) != CoinbaseWitnessDataLen {
        str := fmt.Sprintf("the coinbase transaction witness nonce "+
            "has %d bytes when it must be %d bytes",
            len(witnessNonce), CoinbaseWitnessDataLen)
        return ruleError(ErrInvalidWitnessCommitment, str)
    }

Also notice I introduced a constant for that "32" magic and I created a witnessNonce variable which can be used below to make the code clearer.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Done, I've used the code fragment you provided, creating a new const for CoinbaseWitnessDataLen. As a result, the code is much clearer, and more explicit, thanks!

return ruleError(ErrInvalidWitnessCommitment, str)
}

// Finally, with the preliminary checks out of the way, we can finally

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

finally repeated.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.


witnessPreimage := make([]byte, 64)
copy(witnessPreimage[:], witnessMerkleRoot[:])
copy(witnessPreimage[32:], coinbaseTx.MsgTx().TxIn[0].Witness[0])

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

With the changes recommended above.

    copy(witnessPreimage[32:], witnessNonce)

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Done.

@@ -69,6 +69,87 @@ func IsPayToScriptHash(script []byte) bool {
return isScriptHash(pops)
}

// isWitnessScriptHash returns true if the passed script is a
// pay-to-witness-script-hash transaction, false otherwise.
func isWitnessScriptHash(pops []parsedOpcode) bool {

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Please move this and all of the others that represent standard scripts into standard.go since this is not consensus critical code.

This comment has been minimized.

@davecgh

davecgh Apr 9, 2016
Member

Also, these should really only be true depending on the witness script version which I don't see anything for properly detecting and handling that. I suspect this function, and the others in the same vain, should be taking the witness version and checking it against 0.

The BIP says:

If the version byte is 0, and the witness program is 32 bytes:

Followed by:

If the version byte is 1 to 16, no further interpretation of the witness program or witness happens, and there is no size restriction for the witness. These versions are reserved for future extensions. 

In other words, currently, it is only a P2WSH for version 0.

This comment has been minimized.

@Roasbeef

Roasbeef Jul 3, 2017
Author Member

I placed these functions here as the functions for the prior standard script templates resided in this file as well.

The predicates to decide if something is p2wkh or p2wsh don't need to take in the witness version as a parameter as their definition is based on the witness version being zero, hence the check to pops[0].opcode.value == OP_0.

@davecgh
Copy link
Member

@davecgh davecgh commented Apr 9, 2016

Thanks for all of the work on this. I know it was a lot of it. I also really appreciate the detail put into PR description regarding the changes.

@@ -0,0 +1,101 @@
// Copyright (c) 2013-2016 The btcsuite developers

This comment has been minimized.

This comment has been minimized.

@Roasbeef

Roasbeef Apr 10, 2016
Author Member

Fixed.

Roasbeef added 11 commits Apr 26, 2017
This commit adds verification of the post-segwit standardness
requirement that all pubkeys involved in checks operations MUST be
serialized as compressed public keys. A new ScriptFlag has been added
to guard this behavior when executing scripts.
This commit implements the new “weight” metric introduced as part of
the segwit soft-fork. Post-fork activation, rather than limiting the
size of blocks and transactions based purely on serialized size, a new
metric “weight” will instead be used as a way to more accurately
reflect the costs of a tx/block on the system. With blocks constrained
by weight, the maximum block-size increases to ~4MB.
This commit implements the new block validation rules as defined by
BIP0141. The new rules include the constraints that if a block has
transactions with witness data, then there MUST be a commitment within
the conies transaction to the root of a new merkle tree which commits
to the wtxid of all transactions. Additionally, rather than limiting
the size of a block by size in bytes, blocks are now limited by their
total weight unit. Similarly, a newly define “sig op cost” is now used
to limit the signature validation cost of transactions found within
blocks.
@Roasbeef Roasbeef force-pushed the Roasbeef:segwit-final branch from fee6f82 to 26a3aed Jul 31, 2017
Roasbeef added 8 commits Oct 19, 2016
…itment

This commit modifies the existing block selection logic to limit
preferentially by weight instead of serialized block size, and also to
adhere to the new sig-op cost limits which are weighted according to
the witness discount.
This commit adds set of BIP0009 (Version Bits) deployment parameters
for all networks detailing the activation parameters for the segwit
soft-fork.

Additionally, the BIP0009 integration test has been updated to test for
the proper transitioning of version bits state for the segwit soft
fork. Finally, the `getblockchaininfo` test has also been updated to
properly display the state of segwit.
This commit updates the new segwit validation logic within block
validation to be guarded by an initial check to the version bits state
before conditionally enforcing the logic based off of the state.
This commit updates the block template generation logic to only include
witness transactions once the soft-fork has activated and to also
include the OP_RETURN witness commitment (with additional block weight
accounting).
@Roasbeef Roasbeef force-pushed the Roasbeef:segwit-final branch from 812cb3f to a925475 Jul 31, 2017
@ysangkok

This comment has been minimized.

Copy link

@ysangkok ysangkok commented on wire/msgtx.go in b2efc18 Aug 5, 2017

@Roasbeef this should be witnessMarkerBytes

Copy link
Member

@davecgh davecgh left a comment

I'll take care of the test failure in another PR since it's a false positive and this is ready otherwise.

@davecgh davecgh merged commit 01f26a1 into btcsuite:master Aug 14, 2017
1 check failed
1 check failed
continuous-integration/travis-ci/pr The Travis CI build failed
Details
@dan-da
Copy link
Contributor

@dan-da dan-da commented Aug 15, 2017

congrats on merging it. any eta for next btcd release?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

9 participants
You can’t perform that action at this time.