mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-29 18:26:41 +00:00

* [NOD-1500] Added Domain type and Constructor * [NOD-1500] Replaced dag+txpool with domain in flowContext * [NOD-1500] Replaced dag+txpool with domain in flowContext * [NOD-1500] Converters: domain objects from/to appmessage * [NOD-1500] Convert hashes to DomainHashes in appmessages * [NOD-1500] Remove references to daghash in dagconfig * [NOD-1500] Fixed all appmessage usages of hashes * [NOD-1500] Update all RPC to use domain * [NOD-1500] Big chunk of protocol flows re-wired to domain * [NOD-1500] Finished re-wiring all protocol flows to new Domain * [NOD-1500] Fix some mempool and kaspaminer compilation errors * [NOD-1500] Deleted util/{block,tx,daghash} and dbaccess * [NOD-1500] util.CoinbaseTransactionIndex -> transactionhelper.CoinbaseTransactionIndex * [NOD-1500] Fix txsigner * [NOD-1500] Removed all references to util/subnetworkid * [NOD-1500] Update RpcGetBlock related messages * [NOD-1500] Many more compilation fixes * [NOD-1500] Return full list of missing blocks for orphan resolution * [NOD-1500] Fixed handshake * [NOD-1500] Fixed flowcontext compilation * [NOD-1500] Update users of StartIBDIfRequired to handle error * [NOD-1500] Removed some more fields from RPC * [NOD-1500] Fix the getBlockTemplate flow * [NOD-1500] Fix HandleGetCurrentNetwork * [NOD-1500] Remove redundant code * [NOD-1500] Remove obsolete notifications * [NOD-1500] Split MiningManager and Consensus to separate fields in Domain * [NOD-1500] Update two wrong references to location of txscript * [NOD-1500] Added comments * [NOD-1500] Fix some tests * [NOD-1500] Removed serialization logic from appmessage * [NOD-1500] Rename database/serialization/messages.proto to dbobjects.proto * [NOD-1500] Delete integration tests * [NOD-1500] Remove txsort * [NOD-1500] Fix tiny bug * [NOD-1500] Remove rogue dependancy on bchd * [NOD-1500] Some stylistic fixes
137 lines
4.2 KiB
Go
137 lines
4.2 KiB
Go
package coinbasemanager
|
|
|
|
import (
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/coinbase"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
|
)
|
|
|
|
type coinbaseManager struct {
|
|
subsidyReductionInterval uint64
|
|
|
|
databaseContext model.DBReader
|
|
ghostdagDataStore model.GHOSTDAGDataStore
|
|
acceptanceDataStore model.AcceptanceDataStore
|
|
}
|
|
|
|
func (c coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.DomainHash,
|
|
coinbaseData *externalapi.DomainCoinbaseData) (*externalapi.DomainTransaction, error) {
|
|
|
|
ghostdagData, err := c.ghostdagDataStore.Get(c.databaseContext, blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
acceptanceData, err := c.acceptanceDataStore.Get(c.databaseContext, blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues))
|
|
for i, blue := range ghostdagData.MergeSetBlues {
|
|
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if hasReward {
|
|
txOuts = append(txOuts, txOut)
|
|
}
|
|
}
|
|
|
|
payload, err := coinbase.SerializeCoinbasePayload(ghostdagData.BlueScore, coinbaseData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
payloadHash := hashes.HashData(payload)
|
|
|
|
return &externalapi.DomainTransaction{
|
|
Version: constants.TransactionVersion,
|
|
Inputs: []*externalapi.DomainTransactionInput{},
|
|
Outputs: txOuts,
|
|
LockTime: 0,
|
|
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
|
Gas: 0,
|
|
PayloadHash: *payloadHash,
|
|
Payload: payload,
|
|
}, nil
|
|
}
|
|
|
|
// coinbaseOutputForBlueBlock calculates the output that should go into the coinbase transaction of blueBlock
|
|
// If blueBlock gets no fee - returns nil for txOut
|
|
func (c coinbaseManager) coinbaseOutputForBlueBlock(blueBlock *externalapi.DomainHash,
|
|
blockAcceptanceData *model.BlockAcceptanceData) (*externalapi.DomainTransactionOutput, bool, error) {
|
|
|
|
totalFees := uint64(0)
|
|
for _, txAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
|
|
if txAcceptanceData.IsAccepted {
|
|
totalFees += txAcceptanceData.Fee
|
|
}
|
|
}
|
|
|
|
subsidy, err := c.calcBlockSubsidy(blueBlock)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
totalReward := subsidy + totalFees
|
|
|
|
if totalReward == 0 {
|
|
return nil, false, nil
|
|
}
|
|
|
|
// the ScriptPubKey for the coinbase is parsed from the coinbase payload
|
|
_, coinbaseData, err := coinbase.ExtractCoinbaseDataAndBlueScore(blockAcceptanceData.TransactionAcceptanceData[0].Transaction)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
txOut := &externalapi.DomainTransactionOutput{
|
|
Value: totalReward,
|
|
ScriptPublicKey: coinbaseData.ScriptPublicKey,
|
|
}
|
|
|
|
return txOut, true, nil
|
|
}
|
|
|
|
// calcBlockSubsidy returns the subsidy amount a block at the provided blue score
|
|
// 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
|
|
// has the expected value.
|
|
//
|
|
// The subsidy is halved every SubsidyReductionInterval blocks. Mathematically
|
|
// this is: baseSubsidy / 2^(blueScore/SubsidyReductionInterval)
|
|
//
|
|
// At the target block generation rate for the main network, this is
|
|
// approximately every 4 years.
|
|
func (c coinbaseManager) calcBlockSubsidy(blockHash *externalapi.DomainHash) (uint64, error) {
|
|
if c.subsidyReductionInterval == 0 {
|
|
return constants.BaseSubsidy, nil
|
|
}
|
|
|
|
ghostdagData, err := c.ghostdagDataStore.Get(c.databaseContext, blockHash)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Equivalent to: baseSubsidy / 2^(blueScore/subsidyHalvingInterval)
|
|
return constants.BaseSubsidy >> uint(ghostdagData.BlueScore/c.subsidyReductionInterval), nil
|
|
}
|
|
|
|
// New instantiates a new CoinbaseManager
|
|
func New(
|
|
databaseContext model.DBReader,
|
|
ghostdagDataStore model.GHOSTDAGDataStore,
|
|
acceptanceDataStore model.AcceptanceDataStore) model.CoinbaseManager {
|
|
|
|
return &coinbaseManager{
|
|
databaseContext: databaseContext,
|
|
ghostdagDataStore: ghostdagDataStore,
|
|
acceptanceDataStore: acceptanceDataStore,
|
|
}
|
|
}
|