This implements an agenda for voting to repurpose the stake root field
of the block header to house a commitment root that includes an initial
commitment to a version 2 block filter as defined in DCP0005 along with
consensus tests.
In particular, once the vote has passed and is active, the stake root
field of the block header will contain the merkle root of a merkle tree
that consists of the hash of the version 2 GCS block filter as the sole
leaf.
In order to accomplish validation efficiently and such that it provides
a well-defined path for adding future commitments, this introduces a new
unexported struct in blockchain to house header commitment data, named
headerCommitmentData, and modifies the relevant funcs to accept an
instance of it.
Next, it introduces a new function named CalcCommitmentRootV1 which
takes the filter hash to commit to and returns the resulting commitment
root. It is certainly the case that this function is not strictly
necessary yet since the version 1 header commitment only consists of a
single item, and hence the root will be the same as the hash provided.
However, this approach is used in order to provide a clear path for
future commitment versions, help make it clear exactly what each version
commits to, and to provide for more consistent code the supports
multiple versions.
Finally, since the version 2 block filters require all previous output
scripts referenced as inputs by the block, and some of those scripts may
no longer be availabled in the pruned utxo set in the case the current
tip block of the main chain does not have enough votes, this introduces
a new blockchain method named FetchUtxoViewParentTemplate to load utxo
details from the point of view of just having connected the given block
template to the parent of the tip of the main chain. It also ensures
the provided template connects to the parent as expected.
It is also worth noting that this makes use of the already introduced
header commitments agenda and associated changes to generate new version
blocks and therefore must be merged at the same time as the commits
which introduce those changes along with the other consensus changes
that the agenda entails.
The following is an overview of the changes:
- Generate block templates with the stake root value set to either the
existing stake root or the new commitment root in accordance with the
state of the vote
- Add new ErrCalcCommitmentRoot mining error code
- Introduce a new function named calcBlockCommitmentRootV1 which
handles creating the version 2 block filter and calculating the
resulting commitment root for block templates
- Remove the no longer used mining calcTxTreeMerkleRoot function
- Modify block validation to enforce the commitment root field in
accordance with the state of the vote
- Add new ErrBadCommitmentRoot rule error code to uniquely identify
the new consensus violation
- Introduce new unexported struct to house header commitment data and
modify relevant funcs to accept an instance of it
- Introduce a new function named CalcCommitmentRootV1 for calculating
the commitment root
- Add tests to ensure the commitment root is calculated properly
- Add a new blockchain method named FetchUtxoViewParentTemplate
98 lines
3.3 KiB
Go
98 lines
3.3 KiB
Go
// Copyright (c) 2015-2016 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// MiningErrorCode identifies a kind of error.
|
|
type MiningErrorCode int
|
|
|
|
// These constants are used to identify a specific RuleError.
|
|
const (
|
|
// ErrNotEnoughVoters indicates that there were not enough voters to
|
|
// build a block on top of HEAD.
|
|
ErrNotEnoughVoters MiningErrorCode = iota
|
|
|
|
// ErrFailedToGetGeneration specifies that the current generation for
|
|
// a block could not be obtained from blockchain.
|
|
ErrFailedToGetGeneration
|
|
|
|
// ErrGetStakeDifficulty indicates that the current top block of the
|
|
// blockchain could not be obtained.
|
|
ErrGetTopBlock
|
|
|
|
// ErrGettingDifficulty indicates that there was an error getting the
|
|
// PoW difficulty.
|
|
ErrGettingDifficulty
|
|
|
|
// ErrTransactionAppend indicates there was a problem adding a msgtx
|
|
// to a msgblock.
|
|
ErrTransactionAppend
|
|
|
|
// ErrCheckConnectBlock indicates that a newly created block template
|
|
// failed blockchain.CheckConnectBlock.
|
|
ErrCheckConnectBlock
|
|
|
|
// ErrFraudProofIndex indicates that there was an error finding the index
|
|
// for a fraud proof.
|
|
ErrFraudProofIndex
|
|
|
|
// ErrFetchTxStore indicates a transaction store failed to fetch.
|
|
ErrFetchTxStore
|
|
|
|
// ErrCalcCommitmentRoot indicates that creating the header commitments and
|
|
// calculating the associated commitment root for a newly created block
|
|
// template failed.
|
|
ErrCalcCommitmentRoot
|
|
)
|
|
|
|
// Map of MiningErrorCode values back to their constant names for pretty printing.
|
|
var miningErrorCodeStrings = map[MiningErrorCode]string{
|
|
ErrNotEnoughVoters: "ErrNotEnoughVoters",
|
|
ErrFailedToGetGeneration: "ErrFailedToGetGeneration",
|
|
ErrGetTopBlock: "ErrGetTopBlock",
|
|
ErrGettingDifficulty: "ErrGettingDifficulty",
|
|
ErrTransactionAppend: "ErrTransactionAppend",
|
|
ErrCheckConnectBlock: "ErrCheckConnectBlock",
|
|
ErrFraudProofIndex: "ErrFraudProofIndex",
|
|
ErrFetchTxStore: "ErrFetchTxStore",
|
|
ErrCalcCommitmentRoot: "ErrCalcCommitmentRoot",
|
|
}
|
|
|
|
// String returns the MiningErrorCode as a human-readable name.
|
|
func (e MiningErrorCode) String() string {
|
|
if s := miningErrorCodeStrings[e]; s != "" {
|
|
return s
|
|
}
|
|
return fmt.Sprintf("Unknown MiningErrorCode (%d)", int(e))
|
|
}
|
|
|
|
// MiningRuleError identifies a rule violation. It is used to indicate that
|
|
// processing of a block or transaction failed due to one of the many validation
|
|
// rules. The caller can use type assertions to determine if a failure was
|
|
// specifically due to a rule violation and access the MiningErrorCode field to
|
|
// ascertain the specific reason for the rule violation.
|
|
type MiningRuleError struct {
|
|
ErrorCode MiningErrorCode // Describes the kind of error
|
|
Description string // Human readable description of the issue
|
|
}
|
|
|
|
// Error satisfies the error interface and prints human-readable errors.
|
|
func (e MiningRuleError) Error() string {
|
|
return e.Description
|
|
}
|
|
|
|
// GetCode satisfies the error interface and prints human-readable errors.
|
|
func (e MiningRuleError) GetCode() MiningErrorCode {
|
|
return e.ErrorCode
|
|
}
|
|
|
|
// miningRuleError creates an RuleError given a set of arguments.
|
|
func miningRuleError(c MiningErrorCode, desc string) MiningRuleError {
|
|
return MiningRuleError{ErrorCode: c, Description: desc}
|
|
}
|