mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-08-23 02:53:14 +00:00

* Replace the old blockSubsidy parameters with the new ones. * Return subsidyGenesisReward if blockHash is the genesis hash. * Traverse a block's past for the subsidy calculation. * Partially implement SubsidyStore. * Refer to SubsidyStore from CoinbaseManager. * Wrap calcBlockSubsidy in getBlockSubsidy, which first checks the database. * Fix finalityStore not calling GenerateShardingID. * Implement calculateAveragePastSubsidy. * Implement calculateMergeSetSubsidySum. * Implement calculateSubsidyRandomVariable. * Implement calcBlockSubsidy. * Add a TODO about floats. * Update the calcBlockSubsidy TODO. * Use binary.LittleEndian in calculateSubsidyRandomVariable. * Fix bad range in calculateSubsidyRandomVariable. * Replace float64 with big.Rat everywhere except for subsidyRandomVariable. * Fix a nil dereference. * Use a random walk to approximate the normal distribution. * In order to avoid unsupported fractional results from powInt64, flip the numerator and the denominator manually. * Set standardDeviation to 0.25, MaxSompi to 10_000_000_000 * SompiPerKaspa and defaultSubsidyGenesisReward to 1_000. * Set the standard deviation to 0.2. * Use a binomial distribution instead of trying to estimate the normal distribution. * Change some values around. * Clamp the block subsidy. * Remove the fake duplicate constants in the util package. * Reduce MaxSompi to only 100m Kaspa to avoid hitting the uint64 ceiling. * Lower MaxSompi further to avoid new and exciting ways for the uint64 ceiling to be hit. * Remove debug logs. * Fix a couple of failing tests. * Fix TestBlockWindow. * Fix limitTransactionCount sometimes crashing on index-out-of-bounds. * In TrustedDataDataDAABlock, replace BlockHeader with DomainBlock * In calculateAveragePastSubsidy, use blockWindow instead of doing a BFS manually. * Remove the reference to DAGTopologyManager in coinbaseManager. * Add subsidy to the coinbase payload. * Get rid of the subsidy store and extract subsidies out of coinbase transactions. * Keep a blockWindow amount of blocks under the virtual for IBD purposes. * Manually remove the virtual genesis from the merge set. * Fix simnet genesis. * Fix TestPruning. * Fix TestCheckBlockIsNotPruned. * Fix TestBlockWindow. * Fix TestCalculateSignatureHashSchnorr. * Fix TestCalculateSignatureHashECDSA. * Fix serializing the wrong value into the coinbase payload. * Rename coinbaseOutputForBlueBlock to coinbaseOutputAndSubsidyForBlueBlock. * Add a TODO about optimizing trusted data DAA window blocks. * Expand on a comment in TestCheckBlockIsNotPruned. * In calcBlockSubsidy, divide the big.Int numerator by the big.Int denominator instead of converting to float64. * Clarify a comment. * Rename SubsidyMinGenesisReward to MinSubsidy. * Properly handle trusted data blocks in calculateMergeSetSubsidySum. * Use the first two bytes of the selected parent's hash for randomness instead of math/rand. * Restore maxSompi to what it used to be. * Fix TestPruning. * Fix TestAmountCreation. * Fix TestBlockWindow. * Fix TestAmountUnitConversions. * Increase the timeout in many-tips to 30 minutes. * Check coinbase subsidy for every block * Re-rename functions * Use shift instead of powInt64 to determine subsidyRandom Co-authored-by: Ori Newman <orinewman1@gmail.com>
71 lines
3.7 KiB
Go
71 lines
3.7 KiB
Go
package coinbasemanager
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const uint64Len = 8
|
|
const uint16Len = 2
|
|
const lengthOfSubsidy = uint64Len
|
|
const lengthOfScriptPubKeyLength = 1
|
|
const lengthOfVersionScriptPubKey = uint16Len
|
|
|
|
// serializeCoinbasePayload builds the coinbase payload based on the provided scriptPubKey and extra data.
|
|
func (c *coinbaseManager) serializeCoinbasePayload(blueScore uint64,
|
|
coinbaseData *externalapi.DomainCoinbaseData, subsidy uint64) ([]byte, error) {
|
|
|
|
scriptLengthOfScriptPubKey := len(coinbaseData.ScriptPublicKey.Script)
|
|
if scriptLengthOfScriptPubKey > int(c.coinbasePayloadScriptPublicKeyMaxLength) {
|
|
return nil, errors.Wrapf(ruleerrors.ErrBadCoinbasePayloadLen, "coinbase's payload script public key is "+
|
|
"longer than the max allowed length of %d", c.coinbasePayloadScriptPublicKeyMaxLength)
|
|
}
|
|
|
|
payload := make([]byte, uint64Len+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength+scriptLengthOfScriptPubKey+len(coinbaseData.ExtraData)+lengthOfSubsidy)
|
|
binary.LittleEndian.PutUint64(payload[:uint64Len], blueScore)
|
|
binary.LittleEndian.PutUint64(payload[uint64Len:], subsidy)
|
|
|
|
payload[uint64Len+lengthOfSubsidy] = uint8(coinbaseData.ScriptPublicKey.Version)
|
|
payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey] = uint8(len(coinbaseData.ScriptPublicKey.Script))
|
|
copy(payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength:], coinbaseData.ScriptPublicKey.Script)
|
|
copy(payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength+scriptLengthOfScriptPubKey:], coinbaseData.ExtraData)
|
|
|
|
return payload, nil
|
|
}
|
|
|
|
// ExtractCoinbaseDataBlueScoreAndSubsidy deserializes the coinbase payload to its component (scriptPubKey, extra data, and subsidy).
|
|
func (c *coinbaseManager) ExtractCoinbaseDataBlueScoreAndSubsidy(coinbaseTx *externalapi.DomainTransaction) (
|
|
blueScore uint64, coinbaseData *externalapi.DomainCoinbaseData, subsidy uint64, err error) {
|
|
|
|
minLength := uint64Len + lengthOfSubsidy + lengthOfVersionScriptPubKey + lengthOfScriptPubKeyLength
|
|
if len(coinbaseTx.Payload) < minLength {
|
|
return 0, nil, 0, errors.Wrapf(ruleerrors.ErrBadCoinbasePayloadLen,
|
|
"coinbase payload is less than the minimum length of %d", minLength)
|
|
}
|
|
|
|
blueScore = binary.LittleEndian.Uint64(coinbaseTx.Payload[:uint64Len])
|
|
subsidy = binary.LittleEndian.Uint64(coinbaseTx.Payload[uint64Len:])
|
|
|
|
scriptPubKeyVersion := uint16(coinbaseTx.Payload[uint64Len+lengthOfSubsidy])
|
|
scriptPubKeyScriptLength := coinbaseTx.Payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey]
|
|
|
|
if scriptPubKeyScriptLength > c.coinbasePayloadScriptPublicKeyMaxLength {
|
|
return 0, nil, 0, errors.Wrapf(ruleerrors.ErrBadCoinbasePayloadLen, "coinbase's payload script public key is "+
|
|
"longer than the max allowed length of %d", c.coinbasePayloadScriptPublicKeyMaxLength)
|
|
}
|
|
|
|
if len(coinbaseTx.Payload) < minLength+int(scriptPubKeyScriptLength) {
|
|
return 0, nil, 0, errors.Wrapf(ruleerrors.ErrBadCoinbasePayloadLen,
|
|
"coinbase payload doesn't have enough bytes to contain a script public key of %d bytes", scriptPubKeyScriptLength)
|
|
}
|
|
scriptPubKeyScript := coinbaseTx.Payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength : uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength+scriptPubKeyScriptLength]
|
|
|
|
return blueScore, &externalapi.DomainCoinbaseData{
|
|
ScriptPublicKey: &externalapi.ScriptPublicKey{Script: scriptPubKeyScript, Version: scriptPubKeyVersion},
|
|
ExtraData: coinbaseTx.Payload[uint64Len+lengthOfSubsidy+lengthOfVersionScriptPubKey+lengthOfScriptPubKeyLength+scriptPubKeyScriptLength:],
|
|
}, subsidy, nil
|
|
}
|