This implements a new module named blockchain/standalone which aims to provide several of the standalone functions currently available in blockchain and ultimately replace them in the next major version. The primary goal of offering these functions via a separate module is to reduce the required dependencies to a minimum as compared to the blockchain module. It will be ideal for applications such as lightweight clients that need to ensure basic security properties hold and calculate appropriate vote subsidies and block explorers. For example, some things an SPV wallet needs to prove are that the block headers all connect together, that they satisfy the proof of work requirements, and that a given transaction tree is valid for a given header. The new module currently only provides functions related to proof of work, however, future commits will provide functions for merkle root calculation, subsidy calculation, and coinbase transaction identification. It is being done in stages to help ease review since it is consensus critical code. Finally, it also includes comprehensive tests, full package documentation, and basic usage examples.
67 lines
2.1 KiB
Go
67 lines
2.1 KiB
Go
// Copyright (c) 2019 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package standalone
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// ErrorCode identifies a kind of error.
|
|
type ErrorCode int
|
|
|
|
// These constants are used to identify a specific RuleError.
|
|
const (
|
|
// ErrUnexpectedDifficulty indicates specified bits do not align with
|
|
// the expected value either because it doesn't match the calculated
|
|
// value based on difficulty rules or it is out of the valid range.
|
|
ErrUnexpectedDifficulty ErrorCode = iota
|
|
|
|
// ErrHighHash indicates the block does not hash to a value which is
|
|
// lower than the required target difficultly.
|
|
ErrHighHash
|
|
|
|
// numErrorCodes is the maximum error code number used in tests.
|
|
numErrorCodes
|
|
)
|
|
|
|
// Map of ErrorCode values back to their constant names for pretty printing.
|
|
var errorCodeStrings = map[ErrorCode]string{
|
|
ErrUnexpectedDifficulty: "ErrUnexpectedDifficulty",
|
|
ErrHighHash: "ErrHighHash",
|
|
}
|
|
|
|
// String returns the ErrorCode as a human-readable name.
|
|
func (e ErrorCode) String() string {
|
|
if s := errorCodeStrings[e]; s != "" {
|
|
return s
|
|
}
|
|
return fmt.Sprintf("Unknown ErrorCode (%d)", int(e))
|
|
}
|
|
|
|
// RuleError identifies a rule violation. The caller can use type assertions to
|
|
// determine if a failure was specifically due to a rule violation and access
|
|
// the ErrorCode field to ascertain the specific reason for the rule violation.
|
|
type RuleError struct {
|
|
ErrorCode ErrorCode // 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 RuleError) Error() string {
|
|
return e.Description
|
|
}
|
|
|
|
// ruleError creates an RuleError given a set of arguments.
|
|
func ruleError(c ErrorCode, desc string) RuleError {
|
|
return RuleError{ErrorCode: c, Description: desc}
|
|
}
|
|
|
|
// IsErrorCode returns whether or not the provided error is a rule error with
|
|
// the provided error code.
|
|
func IsErrorCode(err error, c ErrorCode) bool {
|
|
e, ok := err.(RuleError)
|
|
return ok && e.ErrorCode == c
|
|
}
|