[DEV-68] Revert block version to 1 everywhere

* revert block version to 1

* [DEV-68] remove dersig flag

* [DEV-68] get rid of vbLegacyBlockVersion

* [DEV-68] remove isBIP0030Node
This commit is contained in:
Ori Newman 2018-08-13 12:35:20 +03:00 committed by stasatdaglabs
parent 56fb7f09c1
commit d9abfa0fd3
20 changed files with 149 additions and 300 deletions

View File

@ -84,7 +84,7 @@ func TestHaveBlock(t *testing.T) {
{hash: dagconfig.MainNetParams.GenesisHash.String(), want: true}, {hash: dagconfig.MainNetParams.GenesisHash.String(), want: true},
// Block 3b should be present (as a second child of Block 2). // Block 3b should be present (as a second child of Block 2).
{hash: "00000033119c0f74eff8b4711fce3769ea33e8a69670d9c0366179a9a5b8aec3", want: true}, {hash: "000000bce70562ed076f269c5c4e39c590abb29428c573c02ab970e17931f8a4", want: true},
// Block 100000 should be present (as an orphan). // Block 100000 should be present (as an orphan).
{hash: "000000824dca82828b9a18ac09ed7c93292f6a042fae580c1192c8cd086fd990", want: true}, {hash: "000000824dca82828b9a18ac09ed7c93292f6a042fae580c1192c8cd086fd990", want: true},
@ -120,7 +120,7 @@ func TestHaveBlock(t *testing.T) {
func TestCalcSequenceLock(t *testing.T) { func TestCalcSequenceLock(t *testing.T) {
netParams := &dagconfig.SimNetParams netParams := &dagconfig.SimNetParams
blockVersion := int32(0x20000000) blockVersion := int32(0x10000000)
// Generate enough synthetic blocks for the rest of the test // Generate enough synthetic blocks for the rest of the test
chain := newTestDAG(netParams) chain := newTestDAG(netParams)

View File

@ -105,8 +105,6 @@ var regressionNetParams = &dagconfig.Params{
PowLimit: regressionPowLimit, PowLimit: regressionPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
BIP0034Height: 100000000, // Not active - Permit ver 1 blocks
BIP0066Height: 1251, // Used by regression tests
SubsidyReductionInterval: 150, SubsidyReductionInterval: 150,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
TargetTimePerBlock: time.Minute * 10, // 10 minutes TargetTimePerBlock: time.Minute * 10, // 10 minutes

View File

@ -31,7 +31,7 @@ type hashIDPair struct {
func TestPhantom(t *testing.T) { func TestPhantom(t *testing.T) {
netParams := dagconfig.SimNetParams netParams := dagconfig.SimNetParams
blockVersion := int32(0x20000000) blockVersion := int32(0x10000000)
tests := []struct { tests := []struct {
k uint32 k uint32
@ -40,7 +40,7 @@ func TestPhantom(t *testing.T) {
expectedReds []string expectedReds []string
}{ }{
{ {
//Block hash order:DEBHICAKGJF //Block hash order:AKJIHGFEDCB
k: 1, k: 1,
virtualBlockID: "K", virtualBlockID: "K",
expectedReds: []string{"D"}, expectedReds: []string{"D"},
@ -98,8 +98,8 @@ func TestPhantom(t *testing.T) {
parents: []string{"E", "G"}, parents: []string{"E", "G"},
id: "I", id: "I",
expectedScore: 5, expectedScore: 5,
expectedSelectedParent: "G", expectedSelectedParent: "E",
expectedBlues: []string{"G"}, expectedBlues: []string{"G", "D", "E"},
}, },
{ {
parents: []string{"F"}, parents: []string{"F"},
@ -113,12 +113,12 @@ func TestPhantom(t *testing.T) {
id: "K", id: "K",
expectedScore: 9, expectedScore: 9,
expectedSelectedParent: "H", expectedSelectedParent: "H",
expectedBlues: []string{"I", "G", "J", "F", "H"}, expectedBlues: []string{"I", "J", "G", "F", "H"},
}, },
}, },
}, },
{ {
//block hash order:DQKRLHOEBSIGUJNPCMTAFV //block hash order:AVUTSRQPONMLKJIHGFEDCB
k: 2, k: 2,
virtualBlockID: "V", virtualBlockID: "V",
expectedReds: []string{"D", "J", "P"}, expectedReds: []string{"D", "J", "P"},
@ -205,7 +205,7 @@ func TestPhantom(t *testing.T) {
id: "M", id: "M",
expectedScore: 10, expectedScore: 10,
expectedSelectedParent: "F", expectedSelectedParent: "F",
expectedBlues: []string{"L", "K", "H", "I", "E", "G", "B", "F"}, expectedBlues: []string{"L", "K", "I", "H", "G", "E", "B", "F"},
}, },
{ {
parents: []string{"G", "K"}, parents: []string{"G", "K"},
@ -233,7 +233,7 @@ func TestPhantom(t *testing.T) {
id: "Q", id: "Q",
expectedScore: 10, expectedScore: 10,
expectedSelectedParent: "P", expectedSelectedParent: "P",
expectedBlues: []string{"O", "N", "K", "I", "J", "E", "P"}, expectedBlues: []string{"O", "N", "K", "J", "I", "E", "P"},
}, },
{ {
parents: []string{"L", "Q"}, parents: []string{"L", "Q"},
@ -273,7 +273,7 @@ func TestPhantom(t *testing.T) {
}, },
}, },
{ {
//Block hash order:NRSHBUXJTFGPDVCKEQIOWLMA //Block hash order:AXWVUTSRQPONMLKJIHGFEDCB
k: 1, k: 1,
virtualBlockID: "X", virtualBlockID: "X",
expectedReds: []string{"D", "F", "G", "H", "J", "K", "L", "N", "O", "Q", "R", "S", "U", "V"}, expectedReds: []string{"D", "F", "G", "H", "J", "K", "L", "N", "O", "Q", "R", "S", "U", "V"},
@ -373,15 +373,15 @@ func TestPhantom(t *testing.T) {
parents: []string{"F", "G", "J"}, parents: []string{"F", "G", "J"},
id: "O", id: "O",
expectedScore: 5, expectedScore: 5,
expectedSelectedParent: "G", expectedSelectedParent: "F",
expectedBlues: []string{"J", "F", "G"}, expectedBlues: []string{"J", "G", "F"},
}, },
{ {
parents: []string{"B", "M", "I"}, parents: []string{"B", "M", "I"},
id: "P", id: "P",
expectedScore: 6, expectedScore: 6,
expectedSelectedParent: "B", expectedSelectedParent: "B",
expectedBlues: []string{"I", "M", "C", "E", "B"}, expectedBlues: []string{"M", "I", "E", "C", "B"},
}, },
{ {
parents: []string{"K", "E"}, parents: []string{"K", "E"},
@ -415,15 +415,15 @@ func TestPhantom(t *testing.T) {
parents: []string{"K", "L"}, parents: []string{"K", "L"},
id: "U", id: "U",
expectedScore: 4, expectedScore: 4,
expectedSelectedParent: "L", expectedSelectedParent: "K",
expectedBlues: []string{"K", "L"}, expectedBlues: []string{"L", "K"},
}, },
{ {
parents: []string{"U", "R"}, parents: []string{"U", "R"},
id: "V", id: "V",
expectedScore: 6, expectedScore: 5,
expectedSelectedParent: "U", expectedSelectedParent: "R",
expectedBlues: []string{"R", "U"}, expectedBlues: []string{"U", "R"},
}, },
{ {
parents: []string{"S", "U", "T"}, parents: []string{"S", "U", "T"},
@ -449,10 +449,10 @@ func TestPhantom(t *testing.T) {
//you to point to all the parents that you know, and //you to point to all the parents that you know, and
//propagate your block as soon as it's mined //propagate your block as soon as it's mined
//Block hash order: HRTGMKQBXDWSICYFONUPLEAJZ //Block hash order:AYXWVUTSRQPONMLKJIHGFEDCB
k: 1, k: 1,
virtualBlockID: "Y", virtualBlockID: "Y",
expectedReds: []string{"B", "C", "D", "E", "F", "G"}, expectedReds: []string{"B", "C", "D", "E", "F", "G", "L"},
dagData: []*testBlockData{ dagData: []*testBlockData{
{ {
parents: []string{"A"}, parents: []string{"A"},
@ -514,15 +514,15 @@ func TestPhantom(t *testing.T) {
parents: []string{"H", "I"}, parents: []string{"H", "I"},
id: "J", id: "J",
expectedScore: 3, expectedScore: 3,
expectedSelectedParent: "I", expectedSelectedParent: "H",
expectedBlues: []string{"H", "I"}, expectedBlues: []string{"I", "H"},
}, },
{ {
parents: []string{"H", "I"}, parents: []string{"H", "I"},
id: "K", id: "K",
expectedScore: 3, expectedScore: 3,
expectedSelectedParent: "I", expectedSelectedParent: "H",
expectedBlues: []string{"H", "I"}, expectedBlues: []string{"I", "H"},
}, },
{ {
parents: []string{"I"}, parents: []string{"I"},
@ -534,105 +534,105 @@ func TestPhantom(t *testing.T) {
{ {
parents: []string{"J", "K", "L"}, parents: []string{"J", "K", "L"},
id: "M", id: "M",
expectedScore: 6, expectedScore: 5,
expectedSelectedParent: "J", expectedSelectedParent: "J",
expectedBlues: []string{"K", "L", "J"}, expectedBlues: []string{"K", "J"},
}, },
{ {
parents: []string{"J", "K", "L"}, parents: []string{"J", "K", "L"},
id: "N", id: "N",
expectedScore: 6, expectedScore: 5,
expectedSelectedParent: "J", expectedSelectedParent: "J",
expectedBlues: []string{"K", "L", "J"}, expectedBlues: []string{"K", "J"},
}, },
{ {
parents: []string{"N", "M"}, parents: []string{"N", "M"},
id: "O", id: "O",
expectedScore: 8, expectedScore: 7,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"N", "M"}, parents: []string{"N", "M"},
id: "P", id: "P",
expectedScore: 8, expectedScore: 7,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"N", "M"}, parents: []string{"N", "M"},
id: "Q", id: "Q",
expectedScore: 8, expectedScore: 7,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"O", "P", "Q"}, parents: []string{"O", "P", "Q"},
id: "R", id: "R",
expectedScore: 11, expectedScore: 10,
expectedSelectedParent: "P", expectedSelectedParent: "O",
expectedBlues: []string{"Q", "O", "P"}, expectedBlues: []string{"Q", "P", "O"},
}, },
{ {
parents: []string{"O", "P", "Q"}, parents: []string{"O", "P", "Q"},
id: "S", id: "S",
expectedScore: 11, expectedScore: 10,
expectedSelectedParent: "P", expectedSelectedParent: "O",
expectedBlues: []string{"Q", "O", "P"}, expectedBlues: []string{"Q", "P", "O"},
}, },
{ {
parents: []string{"G", "S", "R"}, parents: []string{"G", "S", "R"},
id: "T", id: "T",
expectedScore: 13, expectedScore: 12,
expectedSelectedParent: "S", expectedSelectedParent: "R",
expectedBlues: []string{"R", "S"}, expectedBlues: []string{"S", "R"},
}, },
{ {
parents: []string{"S", "R"}, parents: []string{"S", "R"},
id: "U", id: "U",
expectedScore: 13, expectedScore: 12,
expectedSelectedParent: "S", expectedSelectedParent: "R",
expectedBlues: []string{"R", "S"}, expectedBlues: []string{"S", "R"},
}, },
{ {
parents: []string{"T", "U"}, parents: []string{"T", "U"},
id: "V", id: "V",
expectedScore: 15, expectedScore: 14,
expectedSelectedParent: "U", expectedSelectedParent: "T",
expectedBlues: []string{"T", "U"}, expectedBlues: []string{"U", "T"},
}, },
{ {
parents: []string{"T", "U"}, parents: []string{"T", "U"},
id: "W", id: "W",
expectedScore: 15, expectedScore: 14,
expectedSelectedParent: "U", expectedSelectedParent: "T",
expectedBlues: []string{"T", "U"}, expectedBlues: []string{"U", "T"},
}, },
{ {
parents: []string{"T", "U"}, parents: []string{"U", "T"},
id: "X", id: "X",
expectedScore: 15, expectedScore: 14,
expectedSelectedParent: "U", expectedSelectedParent: "T",
expectedBlues: []string{"T", "U"}, expectedBlues: []string{"U", "T"},
}, },
{ {
parents: []string{"V", "W", "X"}, parents: []string{"V", "W", "X"},
id: "Y", id: "Y",
expectedScore: 18, expectedScore: 17,
expectedSelectedParent: "X", expectedSelectedParent: "V",
expectedBlues: []string{"W", "V", "X"}, expectedBlues: []string{"X", "W", "V"},
}, },
}, },
}, },
{ {
//Censorship mining attack: The attacker is mining blocks B,C,D,E,F,G in secret without propagating them, //Censorship mining attack: The attacker is mining blocks B,C,D,E,F,G in secret without propagating them,
//so all blocks except B should be red, because they don't follow the rules of //so all blocks except B and C should be red, because they don't follow the rules of
//PHANTOM that require you to point to all the parents that you know //PHANTOM that require you to point to all the parents that you know
//Block hash order:WZHOGBJMDSICRUYKTFQLEAPXN //Block hash order:AYXWVUTSRQPONMLKJIHGFEDCB
k: 1, k: 1,
virtualBlockID: "Y", virtualBlockID: "Y",
expectedReds: []string{"C", "D", "E", "F", "G"}, expectedReds: []string{"D", "E", "F", "G", "L"},
dagData: []*testBlockData{ dagData: []*testBlockData{
{ {
parents: []string{"A"}, parents: []string{"A"},
@ -694,15 +694,15 @@ func TestPhantom(t *testing.T) {
parents: []string{"H", "I", "B"}, parents: []string{"H", "I", "B"},
id: "J", id: "J",
expectedScore: 4, expectedScore: 4,
expectedSelectedParent: "I", expectedSelectedParent: "B",
expectedBlues: []string{"H", "B", "I"}, expectedBlues: []string{"I", "H", "B"},
}, },
{ {
parents: []string{"H", "I", "B"}, parents: []string{"H", "I", "B"},
id: "K", id: "K",
expectedScore: 4, expectedScore: 4,
expectedSelectedParent: "I", expectedSelectedParent: "B",
expectedBlues: []string{"H", "B", "I"}, expectedBlues: []string{"I", "H", "B"},
}, },
{ {
parents: []string{"I"}, parents: []string{"I"},
@ -715,50 +715,50 @@ func TestPhantom(t *testing.T) {
parents: []string{"J", "K", "L", "C"}, parents: []string{"J", "K", "L", "C"},
id: "M", id: "M",
expectedScore: 7, expectedScore: 7,
expectedSelectedParent: "K", expectedSelectedParent: "J",
expectedBlues: []string{"J", "L", "K"}, expectedBlues: []string{"K", "C", "J"},
}, },
{ {
parents: []string{"J", "K", "L", "C"}, parents: []string{"J", "K", "L", "C"},
id: "N", id: "N",
expectedScore: 7, expectedScore: 7,
expectedSelectedParent: "K", expectedSelectedParent: "J",
expectedBlues: []string{"J", "L", "K"}, expectedBlues: []string{"K", "C", "J"},
}, },
{ {
parents: []string{"N", "M", "D"}, parents: []string{"N", "M", "D"},
id: "O", id: "O",
expectedScore: 9, expectedScore: 9,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"N", "M", "D"}, parents: []string{"N", "M", "D"},
id: "P", id: "P",
expectedScore: 9, expectedScore: 9,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"N", "M", "D"}, parents: []string{"N", "M", "D"},
id: "Q", id: "Q",
expectedScore: 9, expectedScore: 9,
expectedSelectedParent: "N", expectedSelectedParent: "M",
expectedBlues: []string{"M", "N"}, expectedBlues: []string{"N", "M"},
}, },
{ {
parents: []string{"O", "P", "Q", "E"}, parents: []string{"O", "P", "Q", "E"},
id: "R", id: "R",
expectedScore: 12, expectedScore: 12,
expectedSelectedParent: "P", expectedSelectedParent: "O",
expectedBlues: []string{"O", "Q", "P"}, expectedBlues: []string{"Q", "P", "O"},
}, },
{ {
parents: []string{"O", "P", "Q", "E"}, parents: []string{"O", "P", "Q", "E"},
id: "S", id: "S",
expectedScore: 12, expectedScore: 12,
expectedSelectedParent: "P", expectedSelectedParent: "O",
expectedBlues: []string{"O", "Q", "P"}, expectedBlues: []string{"Q", "P", "O"},
}, },
{ {
parents: []string{"G", "S", "R"}, parents: []string{"G", "S", "R"},
@ -799,8 +799,8 @@ func TestPhantom(t *testing.T) {
parents: []string{"V", "W", "X"}, parents: []string{"V", "W", "X"},
id: "Y", id: "Y",
expectedScore: 19, expectedScore: 19,
expectedSelectedParent: "W", expectedSelectedParent: "V",
expectedBlues: []string{"V", "X", "W"}, expectedBlues: []string{"X", "W", "V"},
}, },
}, },
}, },
@ -825,6 +825,10 @@ func TestPhantom(t *testing.T) {
parents.add(parent) parents.add(parent)
} }
node := newTestNode(parents, blockVersion, 0, blockTime, test.k) node := newTestNode(parents, blockVersion, 0, blockTime, test.k)
node.hash = daghash.Hash{} //It helps to predict hash order
for i, char := range blockData.id {
node.hash[i] = byte(char)
}
blockDAG.index.AddNode(node) blockDAG.index.AddNode(node)
blockByIDMap[blockData.id] = node blockByIDMap[blockData.id] = node

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -38,10 +38,6 @@ const (
// used to calculate the median time used to validate block timestamps. // used to calculate the median time used to validate block timestamps.
medianTimeBlocks = 11 medianTimeBlocks = 11
// serializedHeightVersion is the block version which changed block
// coinbases to start with the serialized block height.
serializedHeightVersion = 2
// baseSubsidy is the starting subsidy amount for mined blocks. This // baseSubsidy is the starting subsidy amount for mined blocks. This
// value is halved every SubsidyHalvingInterval blocks. // value is halved every SubsidyHalvingInterval blocks.
baseSubsidy = 50 * btcutil.SatoshiPerBitcoin baseSubsidy = 50 * btcutil.SatoshiPerBitcoin
@ -77,15 +73,6 @@ func isNullOutpoint(outpoint *wire.OutPoint) bool {
return false return false
} }
// ShouldHaveSerializedBlockHeight determines if a block should have a
// serialized block height embedded within the scriptSig of its
// coinbase transaction. Judgement is based on the block version in the block
// header. Blocks with version 2 and above satisfy this criteria. See BIP0034
// for further information.
func ShouldHaveSerializedBlockHeight(header *wire.BlockHeader) bool {
return header.Version >= serializedHeightVersion
}
// IsCoinBaseTx determines whether or not a transaction is a coinbase. A coinbase // IsCoinBaseTx determines whether or not a transaction is a coinbase. A coinbase
// is a special transaction created by miners that has no inputs. This is // is a special transaction created by miners that has no inputs. This is
// represented in the block chain by a transaction with a single input that has // represented in the block chain by a transaction with a single input that has
@ -174,21 +161,6 @@ func IsFinalizedTransaction(tx *btcutil.Tx, blockHeight int32, blockTime time.Ti
return true return true
} }
// isBIP0030Node returns whether or not the passed node represents one of the
// two blocks that violate the BIP0030 rule which prevents transactions from
// overwriting old ones.
func isBIP0030Node(node *blockNode) bool {
if node.height == 91842 && node.hash.IsEqual(block91842Hash) {
return true
}
if node.height == 91880 && node.hash.IsEqual(block91880Hash) {
return true
}
return false
}
// CalcBlockSubsidy returns the subsidy amount a block at the provided height // CalcBlockSubsidy returns the subsidy amount a block at the provided height
// should have. This is mainly used for determining how much the coinbase for // should have. This is mainly used for determining how much the coinbase for
// newly generated blocks awards as well as validating the coinbase for blocks // newly generated blocks awards as well as validating the coinbase for blocks
@ -584,20 +556,19 @@ func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median
} }
// ExtractCoinbaseHeight attempts to extract the height of the block from the // ExtractCoinbaseHeight attempts to extract the height of the block from the
// scriptSig of a coinbase transaction. Coinbase heights are only present in // scriptSig of a coinbase transaction.
// blocks of version 2 or later. This was added as part of BIP0034.
func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) { func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) {
sigScript := coinbaseTx.MsgTx().TxIn[0].SignatureScript sigScript := coinbaseTx.MsgTx().TxIn[0].SignatureScript
if len(sigScript) < 1 { if len(sigScript) < 1 {
str := "the coinbase signature script for blocks of " + str := "the coinbase signature script" +
"version %d or greater must start with the " + "must start with the " +
"length of the serialized block height" "length of the serialized block height"
str = fmt.Sprintf(str, serializedHeightVersion) str = fmt.Sprintf(str)
return 0, ruleError(ErrMissingCoinbaseHeight, str) return 0, ruleError(ErrMissingCoinbaseHeight, str)
} }
// Detect the case when the block height is a small integer encoded with // Detect the case when the block height is a small integer encoded with
// as single byte. // a single byte.
opcode := int(sigScript[0]) opcode := int(sigScript[0])
if opcode == txscript.Op0 { if opcode == txscript.Op0 {
return 0, nil return 0, nil
@ -610,8 +581,8 @@ func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) {
// encode in the block height. // encode in the block height.
serializedLen := int(sigScript[0]) serializedLen := int(sigScript[0])
if len(sigScript[1:]) < serializedLen { if len(sigScript[1:]) < serializedLen {
str := "the coinbase signature script for blocks of " + str := "the coinbase signature script " +
"version %d or greater must start with the " + "must start with the " +
"serialized block height" "serialized block height"
str = fmt.Sprintf(str, serializedLen) str = fmt.Sprintf(str, serializedLen)
return 0, ruleError(ErrMissingCoinbaseHeight, str) return 0, ruleError(ErrMissingCoinbaseHeight, str)
@ -704,18 +675,6 @@ func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, selectedP
return ruleError(ErrForkTooOld, str) return ruleError(ErrForkTooOld, str)
} }
// Reject outdated block versions once a majority of the network
// has upgraded. These were originally voted on by BIP0034,
// BIP0065, and BIP0066.
params := dag.dagParams
if header.Version < 2 && blockHeight >= params.BIP0034Height ||
header.Version < 3 && blockHeight >= params.BIP0066Height {
str := "new blocks with version %d are no longer valid"
str = fmt.Sprintf(str, header.Version)
return ruleError(ErrBlockVersionTooOld, str)
}
return nil return nil
} }
@ -757,25 +716,20 @@ func (dag *BlockDAG) checkBlockContext(block *btcutil.Block, selectedParent *blo
} }
} }
// Ensure coinbase starts with serialized block heights for // Ensure coinbase starts with serialized block heights
// blocks whose version is the serializedHeightVersion or newer
// once a majority of the network has upgraded. This is part of
// BIP0034.
if ShouldHaveSerializedBlockHeight(header) &&
blockHeight >= dag.dagParams.BIP0034Height {
coinbaseTx := block.Transactions()[0] coinbaseTx := block.Transactions()[0]
err := checkSerializedHeight(coinbaseTx, blockHeight) err := checkSerializedHeight(coinbaseTx, blockHeight)
if err != nil { if err != nil {
return err return err
}
} }
} }
return nil return nil
} }
// checkBIP0030 ensures blocks do not contain duplicate transactions which // ensureNoDuplicateTx ensures blocks do not contain duplicate transactions which
// 'overwrite' older transactions that are not fully spent. This prevents an // 'overwrite' older transactions that are not fully spent. This prevents an
// attack where a coinbase and all of its dependent transactions could be // attack where a coinbase and all of its dependent transactions could be
// duplicated to effectively revert the overwritten transactions to a single // duplicated to effectively revert the overwritten transactions to a single
@ -786,7 +740,7 @@ func (dag *BlockDAG) checkBlockContext(block *btcutil.Block, selectedParent *blo
// http://r6.ca/blog/20120206T005236Z.html. // http://r6.ca/blog/20120206T005236Z.html.
// //
// This function MUST be called with the chain state lock held (for reads). // This function MUST be called with the chain state lock held (for reads).
func (dag *BlockDAG) checkBIP0030(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { func (dag *BlockDAG) ensureNoDuplicateTx(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error {
// Fetch utxos for all of the transaction ouputs in this block. // Fetch utxos for all of the transaction ouputs in this block.
// Typically, there will not be any utxos for any of the outputs. // Typically, there will not be any utxos for any of the outputs.
fetchSet := make(map[wire.OutPoint]struct{}) fetchSet := make(map[wire.OutPoint]struct{})
@ -965,27 +919,9 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
"of expected %v", view.Tips(), parentHashes)) "of expected %v", view.Tips(), parentHashes))
} }
// BIP0030 added a rule to prevent blocks which contain duplicate err := dag.ensureNoDuplicateTx(node, block, view)
// transactions that 'overwrite' older transactions which are not fully if err != nil {
// spent. See the documentation for checkBIP0030 for more details. return err
//
// There are two blocks in the chain which violate this rule, so the
// check must be skipped for those blocks. The isBIP0030Node function
// is used to determine if this block is one of the two blocks that must
// be skipped.
//
// In addition, as of BIP0034, duplicate coinbases are no longer
// possible due to its requirement for including the block height in the
// coinbase and thus it is no longer possible to create transactions
// that 'overwrite' older ones. Therefore, only enforce the rule if
// BIP0034 is not yet active. This is a useful optimization because the
// BIP0030 check is expensive since it involves a ton of cache misses in
// the utxoset.
if !isBIP0030Node(node) && (node.height < dag.dagParams.BIP0034Height) {
err := dag.checkBIP0030(node, block, view)
if err != nil {
return err
}
} }
// Load all of the utxos referenced by the inputs for all transactions // Load all of the utxos referenced by the inputs for all transactions
@ -993,7 +929,7 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
// //
// These utxo entries are needed for verification of things such as // These utxo entries are needed for verification of things such as
// transaction inputs, counting pay-to-script-hashes, and scripts. // transaction inputs, counting pay-to-script-hashes, and scripts.
err := view.fetchInputUtxos(dag.db, block) err = view.fetchInputUtxos(dag.db, block)
if err != nil { if err != nil {
return err return err
} }
@ -1115,13 +1051,6 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
scriptFlags |= txscript.ScriptBip16 scriptFlags |= txscript.ScriptBip16
} }
// Enforce DER signatures for block versions 3+ once the historical
// activation threshold has been reached. This is part of BIP0066.
blockHeader := &block.MsgBlock().Header
if blockHeader.Version >= 3 && node.height >= dag.dagParams.BIP0066Height {
scriptFlags |= txscript.ScriptVerifyDERSignatures
}
// We obtain the MTP of the *previous* block in order to // We obtain the MTP of the *previous* block in order to
// determine if transactions in the current block are final. // determine if transactions in the current block are final.
medianTime := node.selectedParent.CalcPastMedianTime() medianTime := node.selectedParent.CalcPastMedianTime()

View File

@ -11,9 +11,6 @@ import (
) )
const ( const (
// vbLegacyBlockVersion is the highest legacy block version before the
// version bits scheme became active.
vbLegacyBlockVersion = 4
// vbTopBits defines the bits to set in the version to signal that the // vbTopBits defines the bits to set in the version to signal that the
// version bits scheme is being used. // version bits scheme is being used.
@ -282,8 +279,7 @@ func (dag *BlockDAG) warnUnknownVersions(node *blockNode) error {
if err != nil { if err != nil {
return err return err
} }
if expectedVersion > vbLegacyBlockVersion && if (node.version & ^expectedVersion) != 0 {
(node.version & ^expectedVersion) != 0 {
numUpgraded++ numUpgraded++
} }

View File

@ -269,7 +269,7 @@ func TestDAGSvrCmds(t *testing.T) {
{ {
name: "getblocktemplate optional - template request with tweaks", name: "getblocktemplate optional - template request with tweaks",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {
return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}`) return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":1}`)
}, },
staticCmd: func() interface{} { staticCmd: func() interface{} {
template := btcjson.TemplateRequest{ template := btcjson.TemplateRequest{
@ -277,25 +277,25 @@ func TestDAGSvrCmds(t *testing.T) {
Capabilities: []string{"longpoll", "coinbasetxn"}, Capabilities: []string{"longpoll", "coinbasetxn"},
SigOpLimit: 500, SigOpLimit: 500,
SizeLimit: 100000000, SizeLimit: 100000000,
MaxVersion: 2, MaxVersion: 1,
} }
return btcjson.NewGetBlockTemplateCmd(&template) return btcjson.NewGetBlockTemplateCmd(&template)
}, },
marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}],"id":1}`, marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":1}],"id":1}`,
unmarshalled: &btcjson.GetBlockTemplateCmd{ unmarshalled: &btcjson.GetBlockTemplateCmd{
Request: &btcjson.TemplateRequest{ Request: &btcjson.TemplateRequest{
Mode: "template", Mode: "template",
Capabilities: []string{"longpoll", "coinbasetxn"}, Capabilities: []string{"longpoll", "coinbasetxn"},
SigOpLimit: int64(500), SigOpLimit: int64(500),
SizeLimit: int64(100000000), SizeLimit: int64(100000000),
MaxVersion: 2, MaxVersion: 1,
}, },
}, },
}, },
{ {
name: "getblocktemplate optional - template request with tweaks 2", name: "getblocktemplate optional - template request with tweaks 2",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {
return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}`) return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":1}`)
}, },
staticCmd: func() interface{} { staticCmd: func() interface{} {
template := btcjson.TemplateRequest{ template := btcjson.TemplateRequest{
@ -303,18 +303,18 @@ func TestDAGSvrCmds(t *testing.T) {
Capabilities: []string{"longpoll", "coinbasetxn"}, Capabilities: []string{"longpoll", "coinbasetxn"},
SigOpLimit: true, SigOpLimit: true,
SizeLimit: 100000000, SizeLimit: 100000000,
MaxVersion: 2, MaxVersion: 1,
} }
return btcjson.NewGetBlockTemplateCmd(&template) return btcjson.NewGetBlockTemplateCmd(&template)
}, },
marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}],"id":1}`, marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":1}],"id":1}`,
unmarshalled: &btcjson.GetBlockTemplateCmd{ unmarshalled: &btcjson.GetBlockTemplateCmd{
Request: &btcjson.TemplateRequest{ Request: &btcjson.TemplateRequest{
Mode: "template", Mode: "template",
Capabilities: []string{"longpoll", "coinbasetxn"}, Capabilities: []string{"longpoll", "coinbasetxn"},
SigOpLimit: true, SigOpLimit: true,
SizeLimit: int64(100000000), SizeLimit: int64(100000000),
MaxVersion: 2, MaxVersion: 1,
}, },
}, },
}, },

View File

@ -183,11 +183,6 @@ type Params struct {
// block in compact form. // block in compact form.
PowLimitBits uint32 PowLimitBits uint32
// These fields define the block heights at which the specified softfork
// BIP became active.
BIP0034Height int32
BIP0066Height int32
// CoinbaseMaturity is the number of blocks required before newly mined // CoinbaseMaturity is the number of blocks required before newly mined
// coins (coinbase transactions) can be spent. // coins (coinbase transactions) can be spent.
CoinbaseMaturity uint16 CoinbaseMaturity uint16
@ -285,8 +280,6 @@ var MainNetParams = Params{
GenesisHash: &genesisHash, GenesisHash: &genesisHash,
PowLimit: mainPowLimit, PowLimit: mainPowLimit,
PowLimitBits: 0x1d00ffff, PowLimitBits: 0x1d00ffff,
BIP0034Height: 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8
BIP0066Height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
@ -367,8 +360,6 @@ var RegressionNetParams = Params{
PowLimit: regressionPowLimit, PowLimit: regressionPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
BIP0034Height: 100000000, // Not active - Permit ver 1 blocks
BIP0066Height: 1251, // Used by regression tests
SubsidyReductionInterval: 150, SubsidyReductionInterval: 150,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
TargetTimePerBlock: time.Minute * 10, // 10 minutes TargetTimePerBlock: time.Minute * 10, // 10 minutes
@ -433,8 +424,6 @@ var TestNet3Params = Params{
GenesisHash: &testNet3GenesisHash, GenesisHash: &testNet3GenesisHash,
PowLimit: testNet3PowLimit, PowLimit: testNet3PowLimit,
PowLimitBits: 0x1d00ffff, PowLimitBits: 0x1d00ffff,
BIP0034Height: 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
BIP0066Height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days
@ -511,8 +500,6 @@ var SimNetParams = Params{
GenesisHash: &simNetGenesisHash, GenesisHash: &simNetGenesisHash,
PowLimit: simNetPowLimit, PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff, PowLimitBits: 0x207fffff,
BIP0034Height: 0, // Always active on simnet
BIP0066Height: 0, // Always active on simnet
CoinbaseMaturity: 100, CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000, SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimespan: time.Hour * 24 * 14, // 14 days

View File

@ -33,7 +33,7 @@ const (
// BlockVersion is the default block version used when generating // BlockVersion is the default block version used when generating
// blocks. // blocks.
BlockVersion = 4 BlockVersion = 1
) )
var ( var (

View File

@ -588,19 +588,16 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) {
// block height from the scriptSig of the coinbase transaction. // block height from the scriptSig of the coinbase transaction.
// Extraction is only attempted if the block's version is // Extraction is only attempted if the block's version is
// high enough (ver 2+). // high enough (ver 2+).
header := &bmsg.block.MsgBlock().Header coinbaseTx := bmsg.block.Transactions()[0]
if blockdag.ShouldHaveSerializedBlockHeight(header) { cbHeight, err := blockdag.ExtractCoinbaseHeight(coinbaseTx)
coinbaseTx := bmsg.block.Transactions()[0] if err != nil {
cbHeight, err := blockdag.ExtractCoinbaseHeight(coinbaseTx) log.Warnf("Unable to extract height from "+
if err != nil { "coinbase tx: %v", err)
log.Warnf("Unable to extract height from "+ } else {
"coinbase tx: %v", err) log.Debugf("Extracted height of %v from "+
} else { "orphan block", cbHeight)
log.Debugf("Extracted height of %v from "+ heightUpdate = cbHeight
"orphan block", cbHeight) blkHashUpdate = blockHash
heightUpdate = cbHeight
blkHashUpdate = blockHash
}
} }
orphanRoot := sm.dag.GetOrphanRoot(blockHash) orphanRoot := sm.dag.GetOrphanRoot(blockHash)

View File

@ -1182,31 +1182,6 @@ func handleGetBlockDAGInfo(s *Server, cmd interface{}, closeChan <-chan struct{}
Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription),
} }
// Next, populate the response with information describing the current
// status of soft-forks deployed via the super-majority block
// signalling mechanism.
height := dagState.SelectedTip.Height
chainInfo.SoftForks = []*btcjson.SoftForkDescription{
{
ID: "bip34",
Version: 2,
Reject: struct {
Status bool `json:"status"`
}{
Status: height >= params.BIP0034Height,
},
},
{
ID: "bip66",
Version: 3,
Reject: struct {
Status bool `json:"status"`
}{
Status: height >= params.BIP0066Height,
},
},
}
// Finally, query the BIP0009 version bits state for all currently // Finally, query the BIP0009 version bits state for all currently
// defined BIP0009 soft-fork deployments. // defined BIP0009 soft-fork deployments.
for deployment, deploymentDetails := range params.Deployments { for deployment, deploymentDetails := range params.Deployments {

View File

@ -688,16 +688,6 @@
"2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
], ],
["Increase test coverage for DERSIG"],
["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Overly long signature is correctly encoded"],
["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Missing S is correctly encoded"],
["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "S with invalid S length is correctly encoded"],
["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer R is correctly encoded"],
["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer S is correctly encoded"],
["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"],
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
["TRUE 2147483648", "CHECKSEQUENCEVERIFY", "", "OK", "CSV passes if stack top bit 1 << 31 is set"], ["TRUE 2147483648", "CHECKSEQUENCEVERIFY", "", "OK", "CSV passes if stack top bit 1 << 31 is set"],
["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], ["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
@ -1077,7 +1067,6 @@
["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], ["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"],
["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"], ["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"],
["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"], ["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"],
["", "'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"],
["", ["",
"0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", "0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
@ -1233,14 +1222,14 @@
], ],
["Increase DERSIG test coverage"], ["Increase DERSIG test coverage"],
["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"], ["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"],
["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"], ["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"],
["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"], ["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"],
["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"], ["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"],
["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"], ["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"],
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"],
["CHECKSEQUENCEVERIFY tests"], ["CHECKSEQUENCEVERIFY tests"],
["", "CHECKSEQUENCEVERIFY", "", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], ["", "CHECKSEQUENCEVERIFY", "", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
@ -1251,12 +1240,12 @@
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
["NULLFAIL should cover all signatures and signatures only"], ["NULLFAIL should cover all signatures and signatures only"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "", "OK", "BIP66 and NULLFAIL-compliant"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
["0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], ["0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
["0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], ["0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
["The End"] ["The End"]
] ]

View File

@ -35,10 +35,6 @@ const (
// This flag should never be used without the ScriptBip16 flag. // This flag should never be used without the ScriptBip16 flag.
ScriptVerifyCleanStack ScriptVerifyCleanStack
// ScriptVerifyDERSignatures defines that signatures are required
// to compily with the DER format.
ScriptVerifyDERSignatures
// ScriptVerifyLowS defines that signtures are required to comply with // ScriptVerifyLowS defines that signtures are required to comply with
// the DER format and whose S value is <= order / 2. This is rule 5 // the DER format and whose S value is <= order / 2. This is rule 5
// of BIP0062. // of BIP0062.
@ -420,12 +416,6 @@ func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error {
// checkSignatureEncoding returns whether or not the passed signature adheres to // checkSignatureEncoding returns whether or not the passed signature adheres to
// the strict encoding requirements if enabled. // the strict encoding requirements if enabled.
func (vm *Engine) checkSignatureEncoding(sig []byte) error { func (vm *Engine) checkSignatureEncoding(sig []byte) error {
if !vm.hasFlag(ScriptVerifyDERSignatures) &&
!vm.hasFlag(ScriptVerifyLowS) &&
!vm.hasFlag(ScriptVerifyStrictEncoding) {
return nil
}
// The format of a DER encoded signature is as follows: // The format of a DER encoded signature is as follows:
// //

View File

@ -162,7 +162,7 @@ func ExampleSignTxOutput() {
// Prove that the transaction has been validly signed by executing the // Prove that the transaction has been validly signed by executing the
// script pair. // script pair.
flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures | flags := txscript.ScriptBip16 |
txscript.ScriptDiscourageUpgradableNops txscript.ScriptDiscourageUpgradableNops
vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, flags, nil) vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, flags, nil)
if err != nil { if err != nil {

View File

@ -2023,14 +2023,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
return nil return nil
} }
var signature *btcec.Signature signature, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
if vm.hasFlag(ScriptVerifyStrictEncoding) ||
vm.hasFlag(ScriptVerifyDERSignatures) {
signature, err = btcec.ParseDERSignature(sigBytes, btcec.S256())
} else {
signature, err = btcec.ParseSignature(sigBytes, btcec.S256())
}
if err != nil { if err != nil {
vm.dstack.PushBool(false) vm.dstack.PushBool(false)
return nil return nil
@ -2200,15 +2193,9 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
// Parse the signature. // Parse the signature.
var err error var err error
if vm.hasFlag(ScriptVerifyStrictEncoding) || parsedSig, err = btcec.ParseDERSignature(signature,
vm.hasFlag(ScriptVerifyDERSignatures) { btcec.S256())
parsedSig, err = btcec.ParseDERSignature(signature,
btcec.S256())
} else {
parsedSig, err = btcec.ParseSignature(signature,
btcec.S256())
}
sigInfo.parsed = true sigInfo.parsed = true
if err != nil { if err != nil {
continue continue

View File

@ -135,8 +135,6 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
// Nothing. // Nothing.
case "CLEANSTACK": case "CLEANSTACK":
flags |= ScriptVerifyCleanStack flags |= ScriptVerifyCleanStack
case "DERSIG":
flags |= ScriptVerifyDERSignatures
case "DISCOURAGE_UPGRADABLE_NOPS": case "DISCOURAGE_UPGRADABLE_NOPS":
flags |= ScriptDiscourageUpgradableNops flags |= ScriptDiscourageUpgradableNops
case "LOW_S": case "LOW_S":

View File

@ -56,7 +56,7 @@ func mkGetScript(scripts map[string][]byte) ScriptDB {
func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error { func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error {
tx.TxIn[idx].SignatureScript = sigScript tx.TxIn[idx].SignatureScript = sigScript
vm, err := NewEngine(pkScript, tx, idx, vm, err := NewEngine(pkScript, tx, idx,
ScriptBip16|ScriptVerifyDERSignatures, nil) ScriptBip16, nil)
if err != nil { if err != nil {
return fmt.Errorf("failed to make script engine for %s: %v", return fmt.Errorf("failed to make script engine for %s: %v",
msg, err) msg, err)
@ -1658,7 +1658,7 @@ nexttest:
} }
// Validate tx input scripts // Validate tx input scripts
scriptFlags := ScriptBip16 | ScriptVerifyDERSignatures scriptFlags := ScriptBip16
for j := range tx.TxIn { for j := range tx.TxIn {
vm, err := NewEngine(sigScriptTests[i]. vm, err := NewEngine(sigScriptTests[i].
inputs[j].txout.PkScript, tx, j, scriptFlags, nil) inputs[j].txout.PkScript, tx, j, scriptFlags, nil)

View File

@ -27,7 +27,6 @@ const (
// TODO: This definition does not belong here. It belongs in a policy // TODO: This definition does not belong here. It belongs in a policy
// package. // package.
StandardVerifyFlags = ScriptBip16 | StandardVerifyFlags = ScriptBip16 |
ScriptVerifyDERSignatures |
ScriptVerifyStrictEncoding | ScriptVerifyStrictEncoding |
ScriptVerifyMinimalData | ScriptVerifyMinimalData |
ScriptDiscourageUpgradableNops | ScriptDiscourageUpgradableNops |