stake

package module
v4.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2023 License: ISC Imports: 18 Imported by: 18

Documentation

Overview

Package stake contains code for all of dcrd's stake transaction chain handling and other portions related to the Proof-of-Stake (PoS) system.

At the heart of the PoS system are tickets, votes and revocations. These 3 pieces work together to determine if previous blocks are valid and their txs should be confirmed.

Important Parts included in stake package:

- Processing SSTx (tickets), SSGen (votes), SSRtx (revocations) - TicketDB - Stake Reward calculation - Stake transaction identification (IsSStx, IsSSGen, IsSSRtx)

Index

Constants

View Source
const (
	// ErrSStxTooManyInputs indicates that a given SStx contains too many
	// inputs.
	ErrSStxTooManyInputs = ErrorKind("ErrSStxTooManyInputs")

	// ErrSStxTooManyOutputs indicates that a given SStx contains too many
	// outputs.
	ErrSStxTooManyOutputs = ErrorKind("ErrSStxTooManyOutputs")

	// ErrSStxNoOutputs indicates that a given SStx has no outputs.
	ErrSStxNoOutputs = ErrorKind("ErrSStxNoOutputs")

	// ErrSStxInvalidInput indicates that an invalid output has been used as
	// an input for a SStx; only non-SStx tagged outputs may be used to
	// purchase stake tickets.
	// TODO: Add this into validate
	// Ensure that all inputs are not tagged SStx outputs of some sort,
	// along with checks to make sure they exist and are available.
	ErrSStxInvalidInputs = ErrorKind("ErrSStxInvalidInputs")

	// ErrSStxInvalidOutput indicates that the output for an SStx tx is
	// invalid; in particular, either the output was not tagged SStx or the
	// OP_RETURNs were missing or contained invalid addresses.
	ErrSStxInvalidOutputs = ErrorKind("ErrSStxInvalidOutputs")

	// ErrSStxInOutProportions indicates the number of inputs in an SStx
	// was not equal to the number of output minus one.
	ErrSStxInOutProportions = ErrorKind("ErrSStxInOutProportions")

	// ErrSStxBadCommitAmount indicates that a ticket tried to commit 0 or
	// a negative value as the commitment amount.
	ErrSStxBadCommitAmount = ErrorKind("ErrSStxBadCommitAmount")

	// ErrSStxBadChangeAmts indicates that the change amount for some SStx
	// was invalid, for instance spending more than its inputs.
	ErrSStxBadChangeAmts = ErrorKind("ErrSStxBadChangeAmts")

	// ErrSStxVerifyCalcAmts indicates that passed calculated amounts failed
	// to conform to the amounts found in the ticket.
	ErrSStxVerifyCalcAmts = ErrorKind("ErrSStxVerifyCalcAmts")

	// ErrSSGenWrongNumInputs indicates that a given SSGen tx contains an
	// invalid number of inputs.
	ErrSSGenWrongNumInputs = ErrorKind("ErrSSGenWrongNumInputs")

	// ErrSSGenTooManyOutputs indicates that a given SSGen tx contains too
	// many outputs.
	ErrSSGenTooManyOutputs = ErrorKind("ErrSSGenTooManyOutputs")

	// ErrSSGenNoOutputs indicates that a given SSGen has no outputs.
	ErrSSGenNoOutputs = ErrorKind("ErrSSGenNoOutputs")

	// ErrSSGenWrongIndex indicates that a given SSGen sstx input was not
	// using the correct index.
	ErrSSGenWrongIndex = ErrorKind("ErrSSGenWrongIndex")

	// ErrSSGenWrongTxTree indicates that a given SSGen tx input was not found in
	// the stake tx tree.
	ErrSSGenWrongTxTree = ErrorKind("ErrSSGenWrongTxTree")

	// ErrSSGenNoStakebase indicates that the SSGen tx did not contain a
	// valid StakeBase in the zeroeth position of inputs.
	ErrSSGenNoStakebase = ErrorKind("ErrSSGenNoStakebase")

	// ErrSSGenNoReference indicates that there is no reference OP_RETURN
	// included as the first output.
	ErrSSGenNoReference = ErrorKind("ErrSSGenNoReference")

	// ErrSSGenNoReference indicates that the OP_RETURN included as the
	// first output was corrupted in some way.
	ErrSSGenBadReference = ErrorKind("ErrSSGenBadReference")

	// ErrSSGenNoVotePush indicates that there is no vote bits OP_RETURN
	// included as the second output.
	ErrSSGenNoVotePush = ErrorKind("ErrSSGenNoVotePush")

	// ErrSSGenBadVotePush indicates that the OP_RETURN included as the
	// second output was corrupted in some way.
	ErrSSGenBadVotePush = ErrorKind("ErrSSGenBadVotePush")

	// ErrSSGenInvalidDiscriminatorLength indicates that the discriminator
	// length is too short.
	ErrSSGenInvalidDiscriminatorLength = ErrorKind("ErrSSGenInvalidDiscriminatorLength")

	// ErrSSGenInvalidNullScript indicates that the passed script is not a
	// valid nullscript.
	ErrSSGenInvalidNullScript = ErrorKind("ErrSSGenInvalidNullScript")

	// ErrSSGenInvalidTVLength indicates that this is an invalid Treasury
	// Vote length.
	ErrSSGenInvalidTVLength = ErrorKind("ErrSSGenInvalidTVLength")

	// ErrSSGenInvalidTreasuryVote indicates that this is an invalid
	// treasury vote.
	ErrSSGenInvalidTreasuryVote = ErrorKind("ErrSSGenInvalidTreasuryVote")

	// ErrSSGenDuplicateTreasuryVote indicates that there is a duplicate
	// treasury vote.
	ErrSSGenDuplicateTreasuryVote = ErrorKind("ErrSSGenDuplicateTreasuryVote")

	// ErrSSGenInvalidTxVersion indicates that this transaction has the
	// wrong version.
	ErrSSGenInvalidTxVersion = ErrorKind("ErrSSGenInvalidTxVersion")

	// ErrSSGenUnknownDiscriminator indicates that the supplied
	// discriminator is unsupported.
	ErrSSGenUnknownDiscriminator = ErrorKind("ErrSSGenUnknownDiscriminator")

	// ErrSSGenBadGenOuts indicates that something was wrong with the stake
	// generation outputs that were present after the first two OP_RETURN
	// pushes in an SSGen tx.
	ErrSSGenBadGenOuts = ErrorKind("ErrSSGenBadGenOuts")

	// ErrSSRtxWrongNumInputs indicates that a given SSRtx contains an
	// invalid number of inputs.
	ErrSSRtxWrongNumInputs = ErrorKind("ErrSSRtxWrongNumInputs")

	// ErrSSRtxTooManyOutputs indicates that a given SSRtx contains too many
	// outputs.
	ErrSSRtxTooManyOutputs = ErrorKind("ErrSSRtxTooManyOutputs")

	// ErrSSRtxNoOutputs indicates that a given SSRtx has no outputs.
	ErrSSRtxNoOutputs = ErrorKind("ErrSSRtxNoOutputs")

	// ErrSSRtxWrongTxTree indicates that a given SSRtx input was not found in
	// the stake tx tree.
	ErrSSRtxWrongTxTree = ErrorKind("ErrSSRtxWrongTxTree")

	// ErrSSRtxBadOuts indicates that there was a non-SSRtx tagged output
	// present in an SSRtx.
	ErrSSRtxBadOuts = ErrorKind("ErrSSRtxBadOuts")

	// ErrSSRtxInvalidFee indicates that a given SSRtx contains an invalid fee.
	ErrSSRtxInvalidFee = ErrorKind("ErrSSRtxInvalidFee")

	// ErrSSRtxInputHasSigScript indicates that a given SSRtx input has a
	// non-empty signature script.
	ErrSSRtxInputHasSigScript = ErrorKind("ErrSSRtxInputHasSigScript")

	// ErrSSRtxInvalidTxVersion indicates that a given SSRtx has an invalid
	// transaction version.
	ErrSSRtxInvalidTxVersion = ErrorKind("ErrSSRtxInvalidTxVersion")

	// ErrVerSStxAmts indicates there was an error verifying the calculated
	// SStx out amounts and the actual SStx out amounts.
	ErrVerSStxAmts = ErrorKind("ErrVerSStxAmts")

	// ErrVerifyInput indicates that there was an error in verification
	// function input.
	ErrVerifyInput = ErrorKind("ErrVerifyInput")

	// ErrVerifyOutType indicates that there was a non-equivalence in the
	// output type.
	ErrVerifyOutType = ErrorKind("ErrVerifyOutType")

	// ErrVerifyTooMuchFees indicates that a transaction's output gave
	// too much in fees after taking into accounts the limits imposed
	// by the SStx output's version field.
	ErrVerifyTooMuchFees = ErrorKind("ErrVerifyTooMuchFees")

	// ErrVerifySpendTooMuch indicates that a transaction's output spent more
	// than it was allowed to spend based on the calculated subsidy or return
	// for a vote or revocation.
	ErrVerifySpendTooMuch = ErrorKind("ErrVerifySpendTooMuch")

	// ErrVerifyOutputAmt indicates that for a vote/revocation spend output,
	// the rule was given that it must exactly match the calculated maximum,
	// however the amount in the output did not (e.g. it gave fees).
	ErrVerifyOutputAmt = ErrorKind("ErrVerifyOutputAmt")

	// ErrVerifyOutPkhs indicates that the recipient of the P2PKH or P2SH
	// script was different from that indicated in the SStx input.
	ErrVerifyOutPkhs = ErrorKind("ErrVerifyOutPkhs")

	// ErrDatabaseCorrupt indicates a database inconsistency.
	ErrDatabaseCorrupt = ErrorKind("ErrDatabaseCorrupt")

	// ErrMissingDatabaseTx indicates that a node disconnection failed to
	// pass a database transaction when attempted to remove a very old
	// node.
	ErrMissingDatabaseTx = ErrorKind("ErrMissingDatabaseTx")

	// ErrMemoryCorruption indicates that memory has somehow become corrupt,
	// for example invalid block header serialization from an in memory
	// struct.
	ErrMemoryCorruption = ErrorKind("ErrMemoryCorruption")

	// ErrFindTicketIdxs indicates a failure to find the selected ticket
	// indexes from the block header.
	ErrFindTicketIdxs = ErrorKind("ErrFindTicketIdxs")

	// ErrMissingTicket indicates that a ticket was missing in one of the
	// ticket treaps when it was attempted to be fetched.
	ErrMissingTicket = ErrorKind("ErrMissingTicket")

	// ErrDuplicateTicket indicates that a duplicate ticket was attempted
	// to be inserted into a ticket treap or the database.
	ErrDuplicateTicket = ErrorKind("ErrDuplicateTicket")

	// ErrUnknownTicketSpent indicates that an unknown ticket was spent by
	// the block.
	ErrUnknownTicketSpent = ErrorKind("ErrUnknownTicketSpent")

	// ErrTAddInvalidTxVersion indicates that this transaction has the
	// wrong version.
	ErrTAddInvalidTxVersion = ErrorKind("ErrTAddInvalidTxVersion")

	// ErrTAddInvalidCount indicates that this transaction contains an
	// invalid TADD script count.
	ErrTAddInvalidCount = ErrorKind("ErrTAddInvalidCount")

	// ErrTAddInvalidVersion indicates that this transaction has an invalid
	// version in an output script.
	ErrTAddInvalidVersion = ErrorKind("ErrTAddInvalidVersion")

	// ErrTAddInvalidScriptLength indicates that this transaction has a zero
	// length output script.
	ErrTAddInvalidScriptLength = ErrorKind("ErrTAddInvalidScriptLength")

	// ErrTAddInvalidLength indicates that output 0 is not exactly 1 byte.
	ErrTAddInvalidLength = ErrorKind("ErrTAddInvalidLength")

	// ErrTAddInvalidOpcode indicates that this transaction does not have a
	// TADD opcode.
	ErrTAddInvalidOpcode = ErrorKind("ErrTAddInvalidOpcode")

	// ErrTAddInvalidChange indicates that this transaction contains an
	// invalid change script.
	ErrTAddInvalidChange = ErrorKind("ErrTAddInvalidChange")

	// ErrTSpendInvalidTxVersion indicates that this transaction has
	// the wrong version.
	ErrTSpendInvalidTxVersion = ErrorKind("ErrTSpendInvalidTxVersion")

	// ErrTSpendInvalidLength indicates that this transaction has an
	// invalid number of inputs and/or outputs.
	ErrTSpendInvalidLength = ErrorKind("ErrTSpendInvalidLength")

	// ErrTSpendInvalidVersion indicates that this transaction has an
	// invalid version in an output script.
	ErrTSpendInvalidVersion = ErrorKind("ErrTSpendInvalidVersion")

	// ErrTSpendInvalidScriptLength indicates that the TSPEND transaction
	// has outputs that have a zero length script.
	ErrTSpendInvalidScriptLength = ErrorKind("ErrTSpendInvalidScriptLength")

	// ErrTSpendInvalidPubkey indicates that this transaction contains an
	// invalid public key.
	ErrTSpendInvalidPubkey = ErrorKind("ErrTSpendInvalidPubkey")

	// ErrTSpendInvalidScript indicates that this transaction does not
	// match the required TSPEND transaction signature.
	ErrTSpendInvalidScript = ErrorKind("ErrTSpendInvalidScript")

	// ErrTSpendInvalidTGen indicates that the TSPEND transaction has
	// outputs that are not tagged with OP_TGEN.
	ErrTSpendInvalidTGen = ErrorKind("ErrTSpendInvalidTGen")

	// ErrTSpendInvalidTransaction indicates that a TSPEND transaction
	// output 0 does not have an a valid null data script.
	ErrTSpendInvalidTransaction = ErrorKind("ErrTSpendInvalidTransaction")

	// ErrTSpendInvalidSpendScript indicates that this transaction contains
	// an invalid P2SH or P2PKH script.
	ErrTSpendInvalidSpendScript = ErrorKind("ErrTSpendInvalidSpendScript")

	// ErrTreasuryBaseInvalidTxVersion indicates that this transaction has
	// the wrong version.
	ErrTreasuryBaseInvalidTxVersion = ErrorKind("ErrTreasuryBaseInvalidTxVersion")

	// ErrTreasuryBaseInvalidCount indicates that this transaction contains
	// an invalid treasury base script count.
	ErrTreasuryBaseInvalidCount = ErrorKind("ErrTreasuryBaseInvalidCount")

	// ErrTreasuryBaseInvalidLength indicates that this transaction contains
	// an invalid treasury base input script length.
	ErrTreasuryBaseInvalidLength = ErrorKind("ErrTreasuryBaseInvalidLength")

	// ErrTreasuryBaseInvalidVersion indicates that this transaction has an
	// invalid version in an output script.
	ErrTreasuryBaseInvalidVersion = ErrorKind("ErrTreasuryBaseInvalidVersion")

	// ErrTreasuryBaseInvalidOpcode0 indicates that this transaction does
	// not have a TADD opcode in TxOut[0].
	ErrTreasuryBaseInvalidOpcode0 = ErrorKind("ErrTreasuryBaseInvalidOpcode0")

	// ErrTreasuryBaseInvalidOpcode1 indicates that this transaction does
	// not have an OP_RETURN opcode in TxOut[1].
	ErrTreasuryBaseInvalidOpcode1 = ErrorKind("ErrTreasuryBaseInvalidOpcode1")

	// ErrTreasuryBaseInvalid indicates that this transaction contains
	// invalid treasurybase TxIn constants.
	ErrTreasuryBaseInvalid = ErrorKind("ErrTreasuryBaseInvalid")
)

These constants are used to identify a specific RuleError.

View Source
const (

	// TxVersionAutoRevocations is the revocation transaction version that enables
	// automatic ticket revocations.
	TxVersionAutoRevocations uint16 = 2

	// MaxInputsPerSStx is the maximum number of inputs allowed in an SStx.
	MaxInputsPerSStx = 64

	// MaxOutputsPerSStx is the maximum number of outputs allowed in an SStx;
	// you need +1 for the tagged SStx output.
	MaxOutputsPerSStx = MaxInputsPerSStx*2 + 1

	// NumInputsPerSSGen is the exact number of inputs for an SSGen
	// (stakebase) tx.  Inputs are a tagged SStx output and a stakebase (null)
	// input.
	NumInputsPerSSGen = 2 // SStx and stakebase

	// MaxOutputsPerSSGen is the maximum number of outputs in an SSGen tx,
	// which are all outputs to the addresses specified in the OP_RETURNs of
	// the original SStx referenced as input plus reference and vote
	// OP_RETURN outputs in the zeroeth and first position.
	//
	// NOTE: If the treasury agenda is active, an OP_RETURN TV (treasury vote)
	// output is additionally included in the last position when voting on a
	// treasury spend.  The MaxOutputsPerSSGen value does NOT account for this
	// output, and should technically be increased by 1, but since the treasury
	// agenda is already active this cannot be updated without a consensus vote.
	MaxOutputsPerSSGen = MaxInputsPerSStx + 2

	// NumInputsPerSSRtx is the exact number of inputs for an SSRtx (stake
	// revocation tx); the only input should be the SStx output.
	NumInputsPerSSRtx = 1

	// MaxOutputsPerSSRtx is the maximum number of outputs in an SSRtx, which
	// are all outputs to the addresses specified in the OP_RETURNs of the
	// original SStx referenced.
	MaxOutputsPerSSRtx = MaxInputsPerSStx

	// SStxPKHMinOutSize is the minimum size of an OP_RETURN commitment output
	// for an SStx tx.
	// 20 bytes P2SH/P2PKH + 8 byte amount + 4 byte fee range limits
	SStxPKHMinOutSize = 32

	// SStxPKHMaxOutSize is the maximum size of an OP_RETURN commitment output
	// for an SStx tx.
	SStxPKHMaxOutSize = 77

	// SSGenBlockReferenceOutSize is the size of a block reference OP_RETURN
	// output for an SSGen tx.
	SSGenBlockReferenceOutSize = 38

	// SSGenVoteBitsOutputMinSize is the minimum size for a VoteBits push
	// in an SSGen.
	SSGenVoteBitsOutputMinSize = 4

	// SSGenVoteBitsOutputMaxSize is the maximum size for a VoteBits push
	// in an SSGen.
	SSGenVoteBitsOutputMaxSize = 77

	// MaxSingleBytePushLength is the largest maximum push for an
	// SStx commitment or VoteBits push.
	MaxSingleBytePushLength = 75

	// SSGenVoteBitsExtendedMaxSize is the maximum size for a VoteBitsExtended
	// push in an SSGen.
	//
	// The final vote transaction includes a single data push for all vote
	// bits concatenated.  The non-extended vote bits occupy the first 2
	// bytes, thus the max number of extended vote bits is the maximum
	// allow length for a single byte data push minus the 2 bytes required
	// by the non-extended vote bits.
	SSGenVoteBitsExtendedMaxSize = MaxSingleBytePushLength - 2

	// SStxVoteReturnFractionMask extracts the return fraction from a
	// commitment output version.
	// If after applying this mask &0x003f is given, the entire amount of
	// the output is allowed to be spent as fees if the flag to allow fees
	// is set.
	SStxVoteReturnFractionMask = 0x003f

	// SStxRevReturnFractionMask extracts the return fraction from a
	// commitment output version.
	// If after applying this mask &0x3f00 is given, the entire amount of
	// the output is allowed to be spent as fees if the flag to allow fees
	// is set.
	SStxRevReturnFractionMask = 0x3f00

	// SStxVoteFractionFlag is a bitflag mask specifying whether or not to
	// apply a fractional limit to the amount used for fees in a vote.
	// 00000000 00000000 = No fees allowed
	// 00000000 01000000 = Apply fees rule
	SStxVoteFractionFlag = 0x0040

	// SStxRevFractionFlag is a bitflag mask specifying whether or not to
	// apply a fractional limit to the amount used for fees in a vote.
	// 00000000 00000000 = No fees allowed
	// 01000000 00000000 = Apply fees rule
	SStxRevFractionFlag = 0x4000

	// VoteConsensusVersionAbsent is the value of the consensus version
	// for a short read of the voteBits.
	VoteConsensusVersionAbsent = 0

	// MaxDataCarrierSize is the maximum number of bytes allowed in pushed
	// data in the various stake transactions.
	MaxDataCarrierSize = 256
)
View Source
const (
	// TSpendScriptLen is the exact length of a TSpend script.
	// <OP_DATA_64> <signature> <OP_DATA_33> <public key> <OP_TSPEND>
	// 1 + 64 + 1 + 33 + 1 = 100
	TSpendScriptLen = 100
)

Variables

This section is empty.

Functions

func AddrFromSStxPkScrCommitment

func AddrFromSStxPkScrCommitment(pkScript []byte, params stdaddr.AddressParams) (stdaddr.StakeAddress, error)

AddrFromSStxPkScrCommitment extracts a P2SH or P2PKH address from a ticket commitment pkScript.

func AmountFromSStxPkScrCommitment

func AmountFromSStxPkScrCommitment(pkScript []byte) (dcrutil.Amount, error)

AmountFromSStxPkScrCommitment extracts a commitment amount from a ticket commitment pkScript.

func CalcHash256PRNGIV

func CalcHash256PRNGIV(seed []byte) chainhash.Hash

CalcHash256PRNGIV calculates and returns the initialization vector for a given seed. This can be used in conjunction with the NewHash256PRNGFromIV function to arrive at the same values that are produced when calling NewHash256PRNG with the seed.

func CalculateRevocationRewards

func CalculateRevocationRewards(contribAmounts []int64, ticketPurchaseAmount int64,
	prevHeaderBytes []byte, isAutoRevocationsEnabled bool) []int64

CalculateRevocationRewards calculates the required amounts to return for a revocation given the original contribution amounts for the ticket and the price the ticket was purchased for.

Since multiple inputs can be used to purchase a ticket, each one contributes a portion of the overall ticket purchase, including the transaction fee. Thus, when claiming the ticket, each output must receive the same proportion of the total amount returned.

After the original contribution amounts are evenly distributed to each output, there may be a remainder left over of 1 to numOutputs - 1 atoms. If the automatic ticket revocations agenda is not active, this remainder ends up as part of the transaction fee. If the agenda is active, each atom in the remainder is added to an output index that is selected in a uniformly random manner, where Hash256PRNG seeded with the previous header bytes is used for the deterministic pseudorandom selection.

func CalculateRewards

func CalculateRewards(contribAmounts []int64, ticketPurchaseAmount,
	voteSubsidy int64) []int64

CalculateRewards calculates the required amounts to return for a vote given the original contribution amounts for the ticket, the price the ticket was purchased for, and the vote subsidy to include.

Since multiple inputs can be used to purchase a ticket, each one contributes a portion of the overall ticket purchase, including the transaction fee. Thus, when claiming the ticket, each output must receive the same proportion of the total amount returned.

After the original contribution amounts are evenly distributed to each output, there may be a remainder left over of 1 to numOutputs - 1 atoms. This remainder ends up as part of the transaction fee.

Note: If calculating rewards for a revocation, CalculateRevocationRewards should be used instead.

func CheckSSGen

func CheckSSGen(tx *wire.MsgTx, isTreasuryEnabled bool) error

CheckSSGen wraps CheckSSGenVotes (which is the old CheckSSGen plus it returns TSpend votes if there are any) to maintain consistency and backwards compatibility.

func CheckSSRtx

func CheckSSRtx(tx *wire.MsgTx, isAutoRevocationsEnabled bool) error

CheckSSRtx returns an error if a transaction is not a stake submission revocation transaction. It does some simple validation steps to make sure the number of inputs, number of outputs, and the input/output scripts are valid.

SSRtx transactions are specified as below.

Inputs:

[index 0] SStx-tagged output

Outputs:

[index 0] SSRtx-tagged output to the first payment commitment address from
  SStx-tagged output's tx (output index 1)
[index 1] SSRtx-tagged output to the second payment commitment address from
  SStx-tagged output's tx (output index 3)
...
[index MaxOutputsPerSSRtx - 1] SSRtx-tagged output to the last payment
  commitment address from SStx-tagged output's tx index output (output
  index MaxInputsPerSStx - 1)

func CheckSStx

func CheckSStx(tx *wire.MsgTx) error

CheckSStx returns an error if a transaction is not a stake submission transaction. It does some simple validation steps to make sure the number of inputs, number of outputs, and the input/output scripts are valid.

SStx transactions are specified as below. Inputs: untagged output 1 [index 0] untagged output 2 [index 1] ... untagged output MaxInputsPerSStx [index MaxInputsPerSStx-1]

Outputs: OP_SSTX tagged output [index 0] OP_RETURN push of input 1's address for reward receiving [index 1] OP_SSTXCHANGE tagged output for input 1 [index 2] OP_RETURN push of input 2's address for reward receiving [index 3] OP_SSTXCHANGE tagged output for input 2 [index 4] ... OP_RETURN push of input MaxInputsPerSStx's address for reward receiving

[index (MaxInputsPerSStx*2)-2]

OP_SSTXCHANGE tagged output [index (MaxInputsPerSStx*2)-1]

The output OP_RETURN pushes should be of size 20 bytes (standard address).

func CheckTAdd

func CheckTAdd(mtx *wire.MsgTx) error

CheckTAdd exports checkTAdd for testing purposes.

func CheckTSpend

func CheckTSpend(mtx *wire.MsgTx) ([]byte, []byte, error)

CheckTSpend verifies if a MsgTx is a valid TSPEND. This function DOES NOT check the signature or if the public key is a well known PI key. This is a convenience function to obtain the signature and public key without iterating over the same MsgTx over and over again. The return values are signature, public key and an error.

func CheckTreasuryBase

func CheckTreasuryBase(mtx *wire.MsgTx) error

CheckTreasuryBase verifies that the provided MsgTx is a treasury base. This is exported for testing purposes.

func CreateRevocationFromTicket

func CreateRevocationFromTicket(ticketHash *chainhash.Hash,
	ticketMinOuts []*MinimalOutput, revocationTxFee dcrutil.Amount,
	revocationTxVersion uint16, params *chaincfg.Params,
	prevHeaderBytes []byte, isAutoRevocationsEnabled bool) (*wire.MsgTx, error)

CreateRevocationFromTicket creates a revocation transaction for the provided ticket. The provided fee is applied to the first output of the created revocation unless it does not adhere to the fee limit imposed by the ticket, in which case an error is returned.

func IsNullDataScript

func IsNullDataScript(scriptVersion uint16, script []byte) bool

IsNullDataScript returns whether or not the passed script is a null data script.

NOTE: This function is only valid for version 0 scripts. It will always return false for other script versions.

func IsRevocationScript

func IsRevocationScript(version uint16, script []byte) bool

IsRevocationScript checks if the provided script is a ticket revocation script.

func IsSSGen

func IsSSGen(tx *wire.MsgTx, isTreasuryEnabled bool) bool

IsSSGen returns whether or not a transaction is a stake submission generation transaction. These are also known as votes.

func IsSSRtx

func IsSSRtx(tx *wire.MsgTx, isAutoRevocationsEnabled bool) bool

IsSSRtx returns whether or not a transaction is a stake submission revocation transaction. These are also known as revocations.

func IsSStx

func IsSStx(tx *wire.MsgTx) bool

IsSStx returns whether or not a transaction is a stake submission transaction. These are also known as tickets.

func IsStakeBase

func IsStakeBase(tx *wire.MsgTx) bool

IsStakeBase returns whether or not a tx could be considered as having a topically valid stake base present.

func IsStakeChangeScript

func IsStakeChangeScript(version uint16, script []byte) bool

IsStakeChangeScript checks if the provided script is a stake change script.

func IsStakeCommitmentTxOut

func IsStakeCommitmentTxOut(index int) bool

IsStakeCommitmentTxOut indicates whether the transaction output identified by the given index is a stake commitment output of a stake submission (aka ticket) transaction. Stake commitment outputs are the odd-numbered outputs.

This function is only safe to be called on a transaction that has passed IsSStx.

func IsTAdd

func IsTAdd(tx *wire.MsgTx) bool

IsTAdd returns true if the provided transaction is a proper TADD.

func IsTSpend

func IsTSpend(tx *wire.MsgTx) bool

IsTSpend returns true if the provided transaction is a proper TSPEND.

func IsTicketPurchaseScript

func IsTicketPurchaseScript(version uint16, script []byte) bool

IsTicketPurchaseScript checks if the provided script is a ticket purchase script.

func IsTreasuryBase

func IsTreasuryBase(tx *wire.MsgTx) bool

IsTreasuryBase returns true if the provided transaction is a treasury base transaction.

func IsTreasuryGenScript

func IsTreasuryGenScript(version uint16, script []byte) bool

IsTreasuryGenScript checks if the provided script is a treasury generation script.

func IsTreasuryVote

func IsTreasuryVote(vote TreasuryVoteT) bool

IsTreasuryVote returns true if the provided vote is valid.

func IsVoteScript

func IsVoteScript(version uint16, script []byte) bool

IsVoteScript checks if the provided script is a vote script.

func ResetDatabase

func ResetDatabase(dbTx database.Tx, params StakeParams, genesisHash *chainhash.Hash) error

ResetDatabase resets the ticket database back to the genesis block.

func SSGenBlockVotedOn

func SSGenBlockVotedOn(tx *wire.MsgTx) (chainhash.Hash, uint32)

SSGenBlockVotedOn takes an SSGen tx and returns the block voted on in the first OP_RETURN by hash and height.

This function is only safe to be called on a transaction that has passed IsSSGen.

func SSGenVersion

func SSGenVersion(tx *wire.MsgTx) uint32

SSGenVersion takes an SSGen tx as input and returns the network consensus version from the VoteBits output. If there is a short read, the network consensus version is considered 0 or "unset".

This function is only safe to be called on a transaction that has passed IsSSGen.

func SSGenVoteBits

func SSGenVoteBits(tx *wire.MsgTx) uint16

SSGenVoteBits takes an SSGen tx as input and scans through its outputs, returning the VoteBits of the index 1 output.

This function is only safe to be called on a transaction that has passed IsSSGen.

func SStxNullOutputAmounts

func SStxNullOutputAmounts(amounts []int64,
	changeAmounts []int64,
	amountTicket int64) (int64, []int64, error)

SStxNullOutputAmounts takes an array of input amounts, change amounts, and a ticket purchase amount, calculates the adjusted proportion from the purchase amount, stores it in an array, then returns the array. That is, for any given SStx, this function calculates the proportional outputs that any single user should receive. Returns: (1) Fees (2) Output Amounts (3) Error

func SStxStakeOutputInfo

func SStxStakeOutputInfo(outs []*MinimalOutput) ([]bool, [][]byte, []int64,
	[]int64, [][]bool, [][]uint16)

SStxStakeOutputInfo takes an SStx as input and scans through its outputs, returning the pubkeyhashs and amounts for any null data pushes (future commitments to stake generation rewards).

func TxSStxStakeOutputInfo

func TxSStxStakeOutputInfo(tx *wire.MsgTx) ([]bool, [][]byte, []int64, []int64,
	[][]bool, [][]uint16)

TxSStxStakeOutputInfo takes an SStx as input and scans through its outputs, returning the pubkeyhashs and amounts for any null data pushes (future commitments to stake generation rewards).

func UseLogger

func UseLogger(logger slog.Logger)

UseLogger uses a specified Logger to output package logging info.

func WriteConnectedBestNode

func WriteConnectedBestNode(dbTx database.Tx, node *Node, hash chainhash.Hash) error

WriteConnectedBestNode writes the newly connected best node to the database under an atomic database transaction, performing all the necessary writes to the database buckets for live, missed, and revoked tickets.

func WriteDisconnectedBestNode

func WriteDisconnectedBestNode(dbTx database.Tx, node *Node, hash chainhash.Hash, childUndoData UndoTicketDataSlice) error

WriteDisconnectedBestNode writes the newly connected best node to the database under an atomic database transaction, performing all the necessary writes to reverse the contents of the database buckets for live, missed, and revoked tickets. It does so by using the parent's block undo data to restore the original state in the database. It also drops new ticket and reversion data for any nodes that have a height higher than this one after.

Types

type ErrorKind

type ErrorKind string

ErrorKind identifies a kind of error. It has full support for errors.Is and errors.As, so the caller can directly check against an error kind when determining the reason for an error.

func (ErrorKind) Error

func (e ErrorKind) Error() string

Error satisfies the error interface and prints human-readable errors.

type Hash256PRNG

type Hash256PRNG struct {
	// contains filtered or unexported fields
}

Hash256PRNG is a deterministic pseudorandom number generator that uses a 256-bit secure hashing function to generate random uint32s starting from an initial seed.

func NewHash256PRNG

func NewHash256PRNG(seed []byte) *Hash256PRNG

NewHash256PRNG returns a deterministic pseudorandom number generator that uses a 256-bit secure hashing function to generate random uint32s given a seed.

func NewHash256PRNGFromIV

func NewHash256PRNGFromIV(iv chainhash.Hash) *Hash256PRNG

NewHash256PRNGFromIV returns a deterministic pseudorandom number generator that uses a 256-bit secure hashing function to generate random uint32s given an initialization vector. The CalcHash256PRNGIV can be used to calculate an initialization vector for a given seed such that the generator will produce the same values as if NewHash256PRNG were called with the same seed. This allows callers to cache and reuse the initialization vector for a given seed to avoid recomputation.

func (*Hash256PRNG) Hash256Rand

func (hp *Hash256PRNG) Hash256Rand() uint32

Hash256Rand returns a uint32 random number using the pseudorandom number generator and updates the state.

func (*Hash256PRNG) StateHash

func (hp *Hash256PRNG) StateHash() chainhash.Hash

StateHash returns a hash referencing the current state the deterministic PRNG.

func (*Hash256PRNG) UniformRandom

func (hp *Hash256PRNG) UniformRandom(upperBound uint32) uint32

UniformRandom returns a random in the range [0 ... upperBound) while avoiding modulo bias, thus giving a normal distribution within the specified range.

Ported from https://github.com/conformal/clens/blob/master/src/arc4random_uniform.c

type MinimalOutput

type MinimalOutput struct {
	PkScript []byte
	Value    int64
	Version  uint16
}

MinimalOutput is a struct encoding a minimally sized output for use in parsing stake related information.

func ConvertToMinimalOutputs

func ConvertToMinimalOutputs(tx *wire.MsgTx) []*MinimalOutput

ConvertToMinimalOutputs converts a transaction to its minimal outputs derivative.

type Node

type Node struct {
	// contains filtered or unexported fields
}

Node is in-memory stake data for a node. It contains a list of database updates to be written in the case that the block is inserted in the main chain database. Because of its use of immutable treap data structures, it allows for a fast, efficient in-memory representation of the ticket database for each node. It handles connection of and disconnection of new blocks simply.

Like the immutable treap structures, stake nodes themselves are considered to be immutable. The connection or disconnection of past or future nodes returns a pointer to a new stake node, which must be saved and used appropriately.

func InitDatabaseState

func InitDatabaseState(dbTx database.Tx, params StakeParams, genesisHash *chainhash.Hash) (*Node, error)

InitDatabaseState initializes the chain with the best state being the genesis block.

func LoadBestNode

func LoadBestNode(dbTx database.Tx, height uint32, blockHash chainhash.Hash, header wire.BlockHeader, params StakeParams) (*Node, error)

LoadBestNode is used when the blockchain is initialized, to get the initial stake node from the database bucket. The blockchain must pass the height and the blockHash to confirm that the ticket database is on the same location in the blockchain as the blockchain itself. This function also checks to ensure that the database has not failed the upgrade process and reports the current version. Upgrades are also handled by this function, when they become applicable.

func (*Node) ConnectNode

func (sn *Node) ConnectNode(lotteryIV chainhash.Hash, ticketsVoted, revokedTickets, newTickets []chainhash.Hash) (*Node, error)

ConnectNode connects a stake node to the node and returns a pointer to the stake node of the child.

func (*Node) DisconnectNode

func (sn *Node) DisconnectNode(parentLotteryIV chainhash.Hash, parentUtds UndoTicketDataSlice, parentTickets []chainhash.Hash, dbTx database.Tx) (*Node, error)

DisconnectNode disconnects a stake node from the node and returns a pointer to the stake node of the parent.

func (*Node) ExistsExpiredTicket

func (sn *Node) ExistsExpiredTicket(ticket chainhash.Hash) bool

ExistsExpiredTicket returns whether or not a ticket was ever expired from the perspective of this stake node.

func (*Node) ExistsLiveTicket

func (sn *Node) ExistsLiveTicket(ticket chainhash.Hash) bool

ExistsLiveTicket returns whether or not a ticket exists in the live ticket treap for this stake node.

func (*Node) ExistsMissedTicket

func (sn *Node) ExistsMissedTicket(ticket chainhash.Hash) bool

ExistsMissedTicket returns whether or not a ticket exists in the missed ticket treap for this stake node.

func (*Node) ExistsRevokedTicket

func (sn *Node) ExistsRevokedTicket(ticket chainhash.Hash) bool

ExistsRevokedTicket returns whether or not a ticket exists in the revoked ticket treap for this stake node.

func (*Node) ExpiredByBlock

func (sn *Node) ExpiredByBlock() []chainhash.Hash

ExpiredByBlock returns the tickets that expired in this block. This is a subset of the missed tickets returned by MissedByBlock. The output only includes the initial expiration of the ticket, not when an expired ticket is revoked. This is unlike MissedByBlock that includes the revocation as well.

func (*Node) ExpiringNextBlock

func (sn *Node) ExpiringNextBlock() []chainhash.Hash

ExpiringNextBlock returns the tickets that will expire in the next block.

func (*Node) FinalState

func (sn *Node) FinalState() [6]byte

FinalState returns the final state lottery checksum of the node.

func (*Node) Height

func (sn *Node) Height() uint32

Height returns the height of the node.

func (*Node) LiveTickets

func (sn *Node) LiveTickets() []chainhash.Hash

LiveTickets returns the list of live tickets for this stake node.

func (*Node) MissedByBlock

func (sn *Node) MissedByBlock() []chainhash.Hash

MissedByBlock returns the tickets that were missed in this block. This includes expired tickets and winning tickets that were not spent by a vote. Also note that when a miss is later revoked, that ticket hash will also appear in the output of this function for the block with the revocation.

func (*Node) MissedTickets

func (sn *Node) MissedTickets() []chainhash.Hash

MissedTickets returns the list of missed tickets for this stake node.

func (*Node) NewTickets

func (sn *Node) NewTickets() []chainhash.Hash

NewTickets returns the stored UndoTicketDataSlice used to remove this node and restore it to the parent state.

func (*Node) PoolSize

func (sn *Node) PoolSize() int

PoolSize returns the size of the live ticket pool.

func (*Node) RevokedTickets

func (sn *Node) RevokedTickets() []*chainhash.Hash

RevokedTickets returns the list of revoked tickets for this stake node.

func (*Node) SpentByBlock

func (sn *Node) SpentByBlock() []chainhash.Hash

SpentByBlock returns the tickets that were spent in this block.

func (*Node) UndoData

func (sn *Node) UndoData() UndoTicketDataSlice

UndoData returns the stored UndoTicketDataSlice used to remove this node and restore it to the parent state.

func (*Node) Winners

func (sn *Node) Winners() []chainhash.Hash

Winners returns the current list of winners for this stake node, which can vote on this node.

type RuleError

type RuleError struct {
	Description string
	Err         error
}

RuleError identifies a rule violation related to stake transactions. It has full support for errors.Is and errors.As, so the caller can ascertain the specific reason for the error by checking the underlying error.

func (RuleError) Error

func (e RuleError) Error() string

Error satisfies the error interface and prints human-readable errors.

func (RuleError) Unwrap

func (e RuleError) Unwrap() error

Unwrap returns the underlying wrapped rule error.

type SpentTicketsInBlock

type SpentTicketsInBlock struct {
	VotedTickets   []chainhash.Hash
	RevokedTickets []chainhash.Hash
	Votes          []VoteVersionTuple
}

SpentTicketsInBlock stores the hashes of the spent (both voted and revoked) tickets of a given block, along with the vote information.

func FindSpentTicketsInBlock

func FindSpentTicketsInBlock(block *wire.MsgBlock) *SpentTicketsInBlock

FindSpentTicketsInBlock returns information about tickets spent in a given block. This includes voted and revoked tickets, and the vote bits of each spent ticket. This is faster than calling the individual functions to determine ticket state if all information regarding spent tickets is needed.

Note that the returned hashes are of the originally purchased *tickets* and **NOT** of the vote/revoke transaction.

The tickets are determined **only** from the STransactions of the provided block and no validation is performed.

This function is only safe to be called with a block that has previously had all header commitments validated.

type StakeParams

type StakeParams interface {
	// VotesPerBlock returns the maximum number of votes a block must contain to
	// receive full subsidy.
	VotesPerBlock() uint16

	// StakeValidationBeginHeight returns the height at which votes become
	// required to extend a block.  This height is the first that will be voted
	// on, but will not include any votes itself.
	StakeValidationBeginHeight() int64

	// StakeEnableHeight returns the height at which the first ticket could
	// possibly mature.
	StakeEnableHeight() int64

	// TicketExpiryBlocks returns the number of blocks after maturity that
	// tickets expire. This will be >= (StakeEnableHeight() +
	// StakeValidationBeginHeight()).
	TicketExpiryBlocks() uint32
}

StakeParams defines an interface that is used to provides the parameters required working with stake nodes. These values are typically well-defined and unique per network.

type TreasuryVoteT

type TreasuryVoteT byte

TreasuryVoteT is the type that designates a treasury vote. There are two valid bits that may be set, although not simultaneously. 0x01 and 0x02. Any other (or lack therefore) bits are considered invalid.

const (
	// TreasuryVoteInvalid identifies an invalid vote for a treasury spend
	// transaction.
	TreasuryVoteInvalid TreasuryVoteT = 0x00

	// TreasuryVoteYes identifies a vote in favor of a specific treasury spend
	// transaction.
	TreasuryVoteYes TreasuryVoteT = 0x01

	// TreasuryVoteNo identifies a vote against a specific treasury spend
	// transaction.
	TreasuryVoteNo TreasuryVoteT = 0x02
)

func CheckTreasuryVote

func CheckTreasuryVote(vote TreasuryVoteT) (TreasuryVoteT, error)

CheckTreasuryVote ensures that the provided treasury vote is valid. If the vote is valid the proper value is returned.

type TreasuryVoteTuple

type TreasuryVoteTuple struct {
	Hash chainhash.Hash
	Vote TreasuryVoteT
}

TreasuryVoteTuple is a tuple that groups a TSpend hash and its associated vote bits.

func CheckSSGenVotes

func CheckSSGenVotes(tx *wire.MsgTx, isTreasuryEnabled bool) ([]TreasuryVoteTuple, error)

CheckSSGenVotes returns an error if a transaction is not a stake submission generation transaction. It does some simple validation steps to make sure the number of inputs, number of outputs, and the input/output scripts are valid. In addition it returns treasury votes to avoid subsequent expensive calls.

This does NOT check to see if the subsidy is valid or whether or not the value of input[0] + subsidy = value of the outputs.

SSGen transactions are specified as below.

Inputs:

[index 0] Stakebase null input
[index 1] SStx-tagged output

Outputs:

[index 0] OP_RETURN push of 40 bytes containing:
  i. 32-byte block header of block being voted on.
  ii. 8-byte int of this block's height.
[index 1] OP_RETURN push of 2 bytes containing votebits
[index 2] SSGen-tagged output to the first payment commitment address from
  SStx-tagged output's tx (output index 1)
[index 3] SSGen-tagged output to the second payment commitment address from
  SStx-tagged output's tx (output index 3)
...
[index maxOuts - 2] SSGen-tagged output to the last payment
  commitment address from SStx-tagged output's tx index output (output
  index MaxInputsPerSStx - 1)
[index maxOuts - 1] OP_RETURN push of 2 bytes containing opcode
  designating what the remaining data that is pushed is.  In the case of
  'TV' (Treasury Vote) it checks for a <hash><vote> tuple. For example:
  OP_RETURN OP_DATA_X 'T','V' <N hashvote_tuple>
  NOTE: This output is only appended when the treasury agenda is active
  and a treasury spend is being voted on.

func GetSSGenTreasuryVotes

func GetSSGenTreasuryVotes(PkScript []byte) ([]TreasuryVoteTuple, error)

GetSSGenTreasuryVotes pulls out treasury votes for TSpend transactions. This function is a convenience function to discourage rolling new versions that pull out votes and may be therefore different from consensus. This function verifies that the passed in script is of the following form: OP_RETURN DATA_PUSH []byte{'T', 'V'} N-votes and returns a slice of hashes which represent the TSpend transactions they are supposed to vote on.

type TxType

type TxType int

TxType indicates the type of tx (regular or stake type).

const (
	TxTypeRegular TxType = iota
	TxTypeSStx
	TxTypeSSGen
	TxTypeSSRtx
	TxTypeTAdd
	TxTypeTSpend
	TxTypeTreasuryBase
)

Possible TxTypes.

func DetermineTxType

func DetermineTxType(tx *wire.MsgTx, isTreasuryEnabled,
	isAutoRevocationsEnabled bool) TxType

DetermineTxType determines the type of stake transaction a transaction is; if none, it returns that it is an assumed regular tx.

type UndoTicketDataSlice

type UndoTicketDataSlice []ticketdb.UndoTicketData

UndoTicketDataSlice is a pass through for ticketdb's UndoTicketData, which is stored in memory in the node.

type VoteBits

type VoteBits struct {
	Bits         uint16
	ExtendedBits []byte
}

VoteBits is a field representing the mandatory 2-byte field of voteBits along with the optional 73-byte extended field for votes.

type VoteVersionTuple

type VoteVersionTuple struct {
	Version uint32
	Bits    uint16
}

VoteVersionTuple contains the extracted vote bits and version from votes (SSGen).

Directories

Path Synopsis
internal
dbnamespace
Package dbnamespace contains constants that define the database namespaces for the purpose of the blockchain, so that external callers may easily access this data.
Package dbnamespace contains constants that define the database namespaces for the purpose of the blockchain, so that external callers may easily access this data.
tickettreap
Package tickettreap implements a treap data structure that is used to hold live tickets ordered by their key along with some associated data using a combination of binary search tree and heap semantics.
Package tickettreap implements a treap data structure that is used to hold live tickets ordered by their key along with some associated data using a combination of binary search tree and heap semantics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL