Skip to content

Commit

Permalink
first df local test ok
Browse files Browse the repository at this point in the history
  • Loading branch information
okilisan committed Sep 23, 2024
1 parent 7cca4f4 commit 959bd27
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 9 deletions.
3 changes: 2 additions & 1 deletion domain/consensus/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
daaBlocksStore,
blockStore,
pruningStore,
blockHeaderStore)
blockHeaderStore,
&config.Params)
headerTipsManager := headersselectedtipmanager.New(dbManager, dagTopologyManager, dagTraversalManager,
ghostdagManager, headersSelectedTipStore, headersSelectedChainStore)
genesisHash := config.GenesisHash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ type CoinbaseManager interface {
coinbaseData *externalapi.DomainCoinbaseData) (expectedTransaction *externalapi.DomainTransaction, hasRedReward bool, err error)
CalcBlockSubsidy(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (uint64, error)
ExtractCoinbaseDataBlueScoreAndSubsidy(coinbaseTx *externalapi.DomainTransaction) (blueScore uint64, coinbaseData *externalapi.DomainCoinbaseData, subsidy uint64, err error)
CheckDevFee(reward uint64, output *externalapi.DomainTransactionOutput) bool
}
61 changes: 61 additions & 0 deletions domain/consensus/processes/blockvalidator/block_body_in_context.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package blockvalidator

import (
"encoding/json"

"github.com/karlsen-network/karlsend/v2/domain/consensus/model"
"github.com/karlsen-network/karlsend/v2/domain/consensus/model/externalapi"
"github.com/karlsen-network/karlsend/v2/domain/consensus/ruleerrors"
Expand Down Expand Up @@ -38,6 +40,12 @@ func (v *blockValidator) ValidateBodyInContext(stagingArea *model.StagingArea, b
if err != nil {
return err
}

//TODO: control block version >= 3
err = v.CheckDevFee(stagingArea, blockHash)
if err != nil {
return err
}
}
return nil
}
Expand Down Expand Up @@ -199,3 +207,56 @@ func (v *blockValidator) checkCoinbaseSubsidy(

return nil
}

func (v *blockValidator) CheckDevFee(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) error {
pruningPoint, err := v.pruningStore.PruningPoint(v.databaseContext, stagingArea)
if err != nil {
return err
}
parents, err := v.dagTopologyManagers[0].Parents(stagingArea, blockHash)
if err != nil {
return err
}
for _, parent := range parents {
isInFutureOfPruningPoint, err := v.dagTopologyManagers[0].IsAncestorOf(stagingArea, pruningPoint, parent)
if err != nil {
return err
}
// The pruning proof ( https://github.com/kaspanet/docs/blob/main/Reference/prunality/Prunality.pdf ) concludes
// that it's impossible for a block to be merged if it was created in the anticone of the pruning point that was
// present at the time of the block creation. So if such situation happens we can be sure that it happens during
// IBD and that this block has at least pruningDepth-finalityInterval confirmations.
if !isInFutureOfPruningPoint {
return nil
}
}
block, err := v.blockStore.Block(v.databaseContext, stagingArea, blockHash)
if err != nil {
return err
}
// Check for nodeFee in block outputs
if len(block.Transactions) < 1 {
return nil
}
if len(block.Transactions[0].Outputs) < 1 {
return nil
}
reward, _ := v.coinbaseManager.CalcBlockSubsidy(stagingArea, blockHash)
hasDevFee := false
for _, transaction := range block.Transactions {
for _, output := range transaction.Outputs {
if v.coinbaseManager.CheckDevFee(reward, output) {
hasDevFee = true
break
}
}
if hasDevFee {
break
}
}
if !hasDevFee {
jsonBytes, _ := json.MarshalIndent(block, "", " ")
return errors.Wrapf(ruleerrors.ErrDevFeeNotIncluded, "transactions do not include dev fee transaction. \n%s", string(jsonBytes))
}
return nil
}
106 changes: 102 additions & 4 deletions domain/consensus/processes/coinbasemanager/coinbasemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"github.com/karlsen-network/karlsend/v2/domain/consensus/utils/hashset"
"github.com/karlsen-network/karlsend/v2/domain/consensus/utils/subnetworks"
"github.com/karlsen-network/karlsend/v2/domain/consensus/utils/transactionhelper"
"github.com/karlsen-network/karlsend/v2/domain/consensus/utils/txscript"
"github.com/karlsen-network/karlsend/v2/domain/dagconfig"
"github.com/karlsen-network/karlsend/v2/infrastructure/db/database"
"github.com/karlsen-network/karlsend/v2/util"
"github.com/pkg/errors"
)

Expand All @@ -29,6 +32,7 @@ type coinbaseManager struct {
blockStore model.BlockStore
pruningStore model.PruningStore
blockHeaderStore model.BlockHeaderStore
params *dagconfig.Params
}

func (c *coinbaseManager) ExpectedCoinbaseTransaction(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
Expand Down Expand Up @@ -60,24 +64,30 @@ func (c *coinbaseManager) ExpectedCoinbaseTransaction(stagingArea *model.Staging
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues()))
acceptanceDataMap := acceptanceDataFromArrayToMap(acceptanceData)
for _, blue := range ghostdagData.MergeSetBlues() {
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(stagingArea, blue, acceptanceDataMap[*blue], daaAddedBlocksSet)
//txOut, hasReward, err := c.coinbaseOutputForBlueBlock(stagingArea, blue, acceptanceDataMap[*blue], daaAddedBlocksSet)
txOut, devTx, hasReward, err := c.coinbaseOutputForBlueBlockWithDevFee(stagingArea, blue, acceptanceDataMap[*blue], daaAddedBlocksSet)
if err != nil {
return nil, false, err
}

if hasReward {
txOuts = append(txOuts, txOut)
txOuts = append(txOuts, devTx)
}
}

txOut, hasRedReward, err := c.coinbaseOutputForRewardFromRedBlocks(
//txOut, hasRedReward, err := c.coinbaseOutputForRewardFromRedBlocks(
// stagingArea, ghostdagData, acceptanceData, daaAddedBlocksSet, coinbaseData)
txOut, devTx, hasRedReward, err := c.coinbaseOutputForRewardFromRedBlocksWithDevFee(
stagingArea, ghostdagData, acceptanceData, daaAddedBlocksSet, coinbaseData)

if err != nil {
return nil, false, err
}

if hasRedReward {
txOuts = append(txOuts, txOut)
txOuts = append(txOuts, devTx)
}

subsidy, err := c.CalcBlockSubsidy(stagingArea, blockHash)
Expand Down Expand Up @@ -114,6 +124,7 @@ func (c *coinbaseManager) daaAddedBlocksSet(stagingArea *model.StagingArea, bloc

// 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(stagingArea *model.StagingArea,
blueBlock *externalapi.DomainHash, blockAcceptanceData *externalapi.BlockAcceptanceData,
mergingBlockDAAAddedBlocksSet hashset.HashSet) (*externalapi.DomainTransactionOutput, bool, error) {
Expand All @@ -123,7 +134,7 @@ func (c *coinbaseManager) coinbaseOutputForBlueBlock(stagingArea *model.StagingA
return nil, false, err
}
if blockReward == 0 {
if blockReward <= 0 {
return nil, false, nil
}
Expand All @@ -140,7 +151,46 @@ func (c *coinbaseManager) coinbaseOutputForBlueBlock(stagingArea *model.StagingA
return txOut, true, nil
}
*/

func (c *coinbaseManager) coinbaseOutputForBlueBlockWithDevFee(stagingArea *model.StagingArea,
blueBlock *externalapi.DomainHash, blockAcceptanceData *externalapi.BlockAcceptanceData,
mergingBlockDAAAddedBlocksSet hashset.HashSet) (*externalapi.DomainTransactionOutput, *externalapi.DomainTransactionOutput, bool, error) {
blockReward, err := c.calcMergedBlockReward(stagingArea, blueBlock, blockAcceptanceData, mergingBlockDAAAddedBlocksSet)
if err != nil {
return nil, nil, false, err
}
devFeeDecodedAddress, err := util.DecodeAddress(c.params.DevFeeAddress, c.params.Prefix)
if err != nil {
return nil, nil, false, err
}
devFeeScriptPublicKey, err := txscript.PayToAddrScript(devFeeDecodedAddress)
if err != nil {
return nil, nil, false, err
}
//devFeeQuantity := uint64(float64(constants.DevFee) / 100 * float64(blockReward))
devFeeQuantity := uint64(float64(c.params.DevFee) / 100 * float64(blockReward))
blockReward -= devFeeQuantity
if blockReward <= 0 {
return nil, nil, false, nil
}
// the ScriptPublicKey for the coinbase is parsed from the coinbase payload
_, coinbaseData, _, err := c.ExtractCoinbaseDataBlueScoreAndSubsidy(blockAcceptanceData.TransactionAcceptanceData[0].Transaction)
if err != nil {
return nil, nil, false, err
}
txOut := &externalapi.DomainTransactionOutput{
Value: blockReward,
ScriptPublicKey: coinbaseData.ScriptPublicKey,
}
devTx := &externalapi.DomainTransactionOutput{
Value: devFeeQuantity,
ScriptPublicKey: devFeeScriptPublicKey,
}
return txOut, devTx, true, nil
}

/*
func (c *coinbaseManager) coinbaseOutputForRewardFromRedBlocks(stagingArea *model.StagingArea,
ghostdagData *externalapi.BlockGHOSTDAGData, acceptanceData externalapi.AcceptanceData, daaAddedBlocksSet hashset.HashSet,
coinbaseData *externalapi.DomainCoinbaseData) (*externalapi.DomainTransactionOutput, bool, error) {
Expand All @@ -165,6 +215,43 @@ func (c *coinbaseManager) coinbaseOutputForRewardFromRedBlocks(stagingArea *mode
ScriptPublicKey: coinbaseData.ScriptPublicKey,
}, true, nil
}
*/

func (c *coinbaseManager) coinbaseOutputForRewardFromRedBlocksWithDevFee(stagingArea *model.StagingArea,
ghostdagData *externalapi.BlockGHOSTDAGData, acceptanceData externalapi.AcceptanceData, daaAddedBlocksSet hashset.HashSet,
coinbaseData *externalapi.DomainCoinbaseData) (*externalapi.DomainTransactionOutput, *externalapi.DomainTransactionOutput, bool, error) {
acceptanceDataMap := acceptanceDataFromArrayToMap(acceptanceData)
totalReward := uint64(0)
for _, red := range ghostdagData.MergeSetReds() {
reward, err := c.calcMergedBlockReward(stagingArea, red, acceptanceDataMap[*red], daaAddedBlocksSet)
if err != nil {
return nil, nil, false, err
}
totalReward += reward
}
devFeeDecodedAddress, err := util.DecodeAddress(c.params.DevFeeAddress, c.params.Prefix)
if err != nil {
return nil, nil, false, err
}
devFeeScriptPublicKey, err := txscript.PayToAddrScript(devFeeDecodedAddress)
if err != nil {
return nil, nil, false, err
}
devFeeQuantity := uint64(float64(c.params.DevFee) / 100 * float64(totalReward))
totalReward -= devFeeQuantity
if totalReward <= 0 {
return nil, nil, false, nil
}
txOut := &externalapi.DomainTransactionOutput{
Value: totalReward,
ScriptPublicKey: coinbaseData.ScriptPublicKey,
}
devTx := &externalapi.DomainTransactionOutput{
Value: devFeeQuantity,
ScriptPublicKey: devFeeScriptPublicKey,
}
return txOut, devTx, true, nil
}

func acceptanceDataFromArrayToMap(acceptanceData externalapi.AcceptanceData) map[externalapi.DomainHash]*externalapi.BlockAcceptanceData {
acceptanceDataMap := make(map[externalapi.DomainHash]*externalapi.BlockAcceptanceData, len(acceptanceData))
Expand All @@ -174,6 +261,15 @@ func acceptanceDataFromArrayToMap(acceptanceData externalapi.AcceptanceData) map
return acceptanceDataMap
}

func (c *coinbaseManager) CheckDevFee(reward uint64, output *externalapi.DomainTransactionOutput) bool {
_, address, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, c.params)
if err != nil {
return false
}
devFeeAmount := uint64(float64(c.params.DevFee) / 100 * float64(reward))
return (address.EncodeAddress() == c.params.DevFeeAddress) && (output.Value >= devFeeAmount)
}

// 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
Expand Down Expand Up @@ -305,7 +401,8 @@ func New(
daaBlocksStore model.DAABlocksStore,
blockStore model.BlockStore,
pruningStore model.PruningStore,
blockHeaderStore model.BlockHeaderStore) model.CoinbaseManager {
blockHeaderStore model.BlockHeaderStore,
params *dagconfig.Params) model.CoinbaseManager {

return &coinbaseManager{
databaseContext: databaseContext,
Expand All @@ -324,5 +421,6 @@ func New(
blockStore: blockStore,
pruningStore: pruningStore,
blockHeaderStore: blockHeaderStore,
params: params,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func TestCalcDeflationaryPeriodBlockSubsidy(t *testing.T) {
nil,
nil,
nil,
nil)
nil,
&dagconfig.MainnetParams)
coinbaseManagerInstance := coinbaseManagerInterface.(*coinbaseManager)

tests := []struct {
Expand Down Expand Up @@ -109,7 +110,8 @@ func TestBuildSubsidyTable(t *testing.T) {
nil,
nil,
nil,
nil)
nil,
&dagconfig.MainnetParams)
coinbaseManagerInstance := coinbaseManagerInterface.(*coinbaseManager)

var subsidyTable []uint64
Expand Down
4 changes: 4 additions & 0 deletions domain/consensus/ruleerrors/rule_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (

// These constants are used to identify a specific RuleError.
var (
// ErrDevFeeNotIncluded indicates that the transactions do not
// include dev fee.
ErrDevFeeNotIncluded = newRuleError("ErrDevFeeNotIncluded")

// ErrDuplicateBlock indicates a block with the same hash already
// exists.
ErrDuplicateBlock = newRuleError("ErrDuplicateBlock")
Expand Down
14 changes: 12 additions & 2 deletions domain/dagconfig/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ type Params struct {
// MaxBlockLevel is the maximum possible block level.
MaxBlockLevel int

MergeDepth uint64
HFDAAScore uint64
MergeDepth uint64
HFDAAScore uint64
DevFee uint64
DevFeeAddress string
}

// NormalizeRPCServerAddress returns addr with the current network default
Expand Down Expand Up @@ -284,6 +286,8 @@ var MainnetParams = Params{
MaxBlockLevel: 225,
MergeDepth: defaultMergeDepth,
HFDAAScore: 26962009, // HF DAAscore to switch to khashv2 (Fri Sep 13 01:37:00 PM UTC 2024)
DevFee: 5,
DevFeeAddress: "karlsen:qzrq7v5jhsc5znvtfdg6vxg7dz5x8dqe4wrh90jkdnwehp6vr8uj7csdss2l7",
}

// TestnetParams defines the network parameters for the test Karlsen network.
Expand Down Expand Up @@ -350,6 +354,8 @@ var TestnetParams = Params{
MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth,
HFDAAScore: 43200, // HF DAAscore to switch to khashv2 (12 hours after testnet launch)
DevFee: 5,
DevFeeAddress: "karlsentest:qrfdtcz926ykjk3vgrxz2cnsynefed7f8dvasm3ckzad2llpm6z8ypwjpwyex",
}

// SimnetParams defines the network parameters for the simulation test Karlsen
Expand Down Expand Up @@ -418,6 +424,8 @@ var SimnetParams = Params{
MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth,
HFDAAScore: 3600,
DevFee: 5,
DevFeeAddress: "karlsendev:qp928nxy34knk3lp4tkdd6qgqlkasa68rdw9fk9rdqrgycwt7cnyw9xsnduwh",
}

// DevnetParams defines the network parameters for the development Karlsen network.
Expand Down Expand Up @@ -482,6 +490,8 @@ var DevnetParams = Params{
MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth,
HFDAAScore: 3600,
DevFee: 10,
DevFeeAddress: "karlsendev:qp928nxy34knk3lp4tkdd6qgqlkasa68rdw9fk9rdqrgycwt7cnyw9xsnduwh",
}

// ErrDuplicateNet describes an error where the parameters for a Karlsen
Expand Down

0 comments on commit 959bd27

Please sign in to comment.