Merge 42da3cd0a0d3218beade91864ebcf5fa951de283 into 387fade0442539efbaf2464dd362ea4985748b36

This commit is contained in:
Ori Newman 2023-12-01 10:09:45 +02:00 committed by GitHub
commit c6917dcb0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 82 additions and 23 deletions

View File

@ -84,4 +84,6 @@ const (
defaultDeflationaryPhaseDaaScore = 15778800 - 259200 defaultDeflationaryPhaseDaaScore = 15778800 - 259200
defaultMergeDepth = 3600 defaultMergeDepth = 3600
defaultDustConst = 1e12 // TODO: Determine the right value
) )

View File

@ -188,6 +188,8 @@ type Params struct {
MaxBlockLevel int MaxBlockLevel int
MergeDepth uint64 MergeDepth uint64
DustConst uint64
} }
// NormalizeRPCServerAddress returns addr with the current network default // NormalizeRPCServerAddress returns addr with the current network default
@ -288,6 +290,7 @@ var MainnetParams = Params{
// This means that any block that has a level lower or equal to genesis will be level 0. // This means that any block that has a level lower or equal to genesis will be level 0.
MaxBlockLevel: 225, MaxBlockLevel: 225,
MergeDepth: defaultMergeDepth, MergeDepth: defaultMergeDepth,
DustConst: defaultDustConst,
} }
// TestnetParams defines the network parameters for the test Kaspa network. // TestnetParams defines the network parameters for the test Kaspa network.
@ -354,6 +357,7 @@ var TestnetParams = Params{
MaxBlockLevel: 250, MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth, MergeDepth: defaultMergeDepth,
DustConst: defaultDustConst,
} }
// SimnetParams defines the network parameters for the simulation test Kaspa // SimnetParams defines the network parameters for the simulation test Kaspa
@ -420,6 +424,7 @@ var SimnetParams = Params{
MaxBlockLevel: 250, MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth, MergeDepth: defaultMergeDepth,
DustConst: defaultDustConst,
} }
// DevnetParams defines the network parameters for the development Kaspa network. // DevnetParams defines the network parameters for the development Kaspa network.
@ -482,6 +487,7 @@ var DevnetParams = Params{
MaxBlockLevel: 250, MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth, MergeDepth: defaultMergeDepth,
DustConst: defaultDustConst,
} }
// ErrDuplicateNet describes an error where the parameters for a Kaspa // ErrDuplicateNet describes an error where the parameters for a Kaspa

View File

@ -5,6 +5,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle" "github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper" "github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/consensusreference" "github.com/kaspanet/kaspad/domain/consensusreference"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
"github.com/kaspanet/kaspad/util/mstime" "github.com/kaspanet/kaspad/util/mstime"
"math" "math"
"sort" "sort"
@ -22,6 +23,7 @@ type candidateTx struct {
*consensusexternalapi.DomainTransaction *consensusexternalapi.DomainTransaction
txValue float64 txValue float64
gasLimit uint64 gasLimit uint64
mass uint64
p float64 p float64
start float64 start float64
@ -41,11 +43,11 @@ type blockTemplateBuilder struct {
// New creates a new blockTemplateBuilder // New creates a new blockTemplateBuilder
func New(consensusReference consensusreference.ConsensusReference, mempool miningmanagerapi.Mempool, func New(consensusReference consensusreference.ConsensusReference, mempool miningmanagerapi.Mempool,
blockMaxMass uint64, coinbasePayloadScriptPublicKeyMaxLength uint8) miningmanagerapi.BlockTemplateBuilder { blockMaxMass uint64, coinbasePayloadScriptPublicKeyMaxLength uint8, dustConst uint64) miningmanagerapi.BlockTemplateBuilder {
return &blockTemplateBuilder{ return &blockTemplateBuilder{
consensusReference: consensusReference, consensusReference: consensusReference,
mempool: mempool, mempool: mempool,
policy: policy{BlockMaxMass: blockMaxMass}, policy: policy{BlockMaxMass: blockMaxMass, DustConst: dustConst},
coinbasePayloadScriptPublicKeyMaxLength: coinbasePayloadScriptPublicKeyMaxLength, coinbasePayloadScriptPublicKeyMaxLength: coinbasePayloadScriptPublicKeyMaxLength,
} }
@ -121,15 +123,18 @@ func (btb *blockTemplateBuilder) BuildBlockTemplate(
mempoolTransactions := btb.mempool.BlockCandidateTransactions() mempoolTransactions := btb.mempool.BlockCandidateTransactions()
candidateTxs := make([]*candidateTx, 0, len(mempoolTransactions)) candidateTxs := make([]*candidateTx, 0, len(mempoolTransactions))
for _, tx := range mempoolTransactions { for _, tx := range mempoolTransactions {
// Calculate the tx value if tx.Mass() == 0 {
panic(errors.Errorf("BuildBlockTemplate expects transactions with populated mass: %s has 0 mass", tx.TransactionID()))
}
gasLimit := uint64(0) gasLimit := uint64(0)
if !subnetworks.IsBuiltInOrNative(tx.SubnetworkID) { if !subnetworks.IsBuiltInOrNative(tx.Transaction().SubnetworkID) {
panic("We currently don't support non native subnetworks") panic("We currently don't support non native subnetworks")
} }
candidateTxs = append(candidateTxs, &candidateTx{ candidateTxs = append(candidateTxs, &candidateTx{
DomainTransaction: tx, DomainTransaction: tx.Transaction(),
txValue: btb.calcTxValue(tx), txValue: btb.calcTxValue(tx),
gasLimit: gasLimit, gasLimit: gasLimit,
mass: tx.Mass(),
}) })
} }
@ -208,15 +213,15 @@ func (btb *blockTemplateBuilder) ModifyBlockTemplate(newCoinbaseData *consensuse
// calcTxValue calculates a value to be used in transaction selection. // calcTxValue calculates a value to be used in transaction selection.
// The higher the number the more likely it is that the transaction will be // The higher the number the more likely it is that the transaction will be
// included in the block. // included in the block.
func (btb *blockTemplateBuilder) calcTxValue(tx *consensusexternalapi.DomainTransaction) float64 { func (btb *blockTemplateBuilder) calcTxValue(tx *model.MempoolTransaction) float64 {
massLimit := btb.policy.BlockMaxMass massLimit := btb.policy.BlockMaxMass
mass := tx.Mass mass := tx.Mass()
fee := tx.Fee fee := tx.Transaction().Fee
if subnetworks.IsBuiltInOrNative(tx.SubnetworkID) { if subnetworks.IsBuiltInOrNative(tx.Transaction().SubnetworkID) {
return float64(fee) / (float64(mass) / float64(massLimit)) return float64(fee) / (float64(mass) / float64(massLimit))
} }
// TODO: Replace with real gas once implemented // TODO: Replace with real gas once implemented
gasLimit := uint64(math.MaxUint64) gasLimit := uint64(math.MaxUint64)
return float64(fee) / (float64(mass)/float64(massLimit) + float64(tx.Gas)/float64(gasLimit)) return float64(fee) / (float64(mass)/float64(massLimit) + float64(tx.Transaction().Gas)/float64(gasLimit))
} }

View File

@ -11,4 +11,6 @@ type policy struct {
// BlockMaxMass is the maximum block mass to be used when generating a // BlockMaxMass is the maximum block mass to be used when generating a
// block template. // block template.
BlockMaxMass uint64 BlockMaxMass uint64
DustConst uint64
} }

View File

@ -101,8 +101,8 @@ func (btb *blockTemplateBuilder) selectTransactions(candidateTxs []*candidateTx)
// Enforce maximum transaction mass per block. Also check // Enforce maximum transaction mass per block. Also check
// for overflow. // for overflow.
if txsForBlockTemplate.totalMass+selectedTx.Mass < txsForBlockTemplate.totalMass || if txsForBlockTemplate.totalMass+selectedTx.mass < txsForBlockTemplate.totalMass ||
txsForBlockTemplate.totalMass+selectedTx.Mass > btb.policy.BlockMaxMass { txsForBlockTemplate.totalMass+selectedTx.mass > btb.policy.BlockMaxMass {
log.Tracef("Tx %s would exceed the max block mass. "+ log.Tracef("Tx %s would exceed the max block mass. "+
"As such, stopping.", consensushashing.TransactionID(tx)) "As such, stopping.", consensushashing.TransactionID(tx))
break break
@ -143,11 +143,11 @@ func (btb *blockTemplateBuilder) selectTransactions(candidateTxs []*candidateTx)
// save the masses, fees, and signature operation counts to the // save the masses, fees, and signature operation counts to the
// result. // result.
selectedTxs = append(selectedTxs, selectedTx) selectedTxs = append(selectedTxs, selectedTx)
txsForBlockTemplate.totalMass += selectedTx.Mass txsForBlockTemplate.totalMass += selectedTx.mass
txsForBlockTemplate.totalFees += selectedTx.Fee txsForBlockTemplate.totalFees += selectedTx.Fee
log.Tracef("Adding tx %s (feePerMegaGram %d)", log.Tracef("Adding tx %s (feePerMegaGram %d)",
consensushashing.TransactionID(tx), selectedTx.Fee*1e6/selectedTx.Mass) consensushashing.TransactionID(tx), selectedTx.Fee*1e6/selectedTx.mass)
markCandidateTxForDeletion(selectedTx) markCandidateTxForDeletion(selectedTx)
} }
@ -157,7 +157,7 @@ func (btb *blockTemplateBuilder) selectTransactions(candidateTxs []*candidateTx)
}) })
for _, selectedTx := range selectedTxs { for _, selectedTx := range selectedTxs {
txsForBlockTemplate.selectedTxs = append(txsForBlockTemplate.selectedTxs, selectedTx.DomainTransaction) txsForBlockTemplate.selectedTxs = append(txsForBlockTemplate.selectedTxs, selectedTx.DomainTransaction)
txsForBlockTemplate.txMasses = append(txsForBlockTemplate.txMasses, selectedTx.Mass) txsForBlockTemplate.txMasses = append(txsForBlockTemplate.txMasses, selectedTx.mass)
txsForBlockTemplate.txFees = append(txsForBlockTemplate.txFees, selectedTx.Fee) txsForBlockTemplate.txFees = append(txsForBlockTemplate.txFees, selectedTx.Fee)
} }
return txsForBlockTemplate return txsForBlockTemplate

View File

@ -21,7 +21,7 @@ func (f *factory) NewMiningManager(consensusReference consensusreference.Consens
mempoolConfig *mempoolpkg.Config) MiningManager { mempoolConfig *mempoolpkg.Config) MiningManager {
mempool := mempoolpkg.New(mempoolConfig, consensusReference) mempool := mempoolpkg.New(mempoolConfig, consensusReference)
blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, params.MaxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength) blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, params.MaxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength, params.DustConst)
return &miningManager{ return &miningManager{
consensusReference: consensusReference, consensusReference: consensusReference,

View File

@ -33,6 +33,7 @@ const (
// as consensus. // as consensus.
defaultMinimumStandardTransactionVersion = constants.MaxTransactionVersion defaultMinimumStandardTransactionVersion = constants.MaxTransactionVersion
defaultMaximumStandardTransactionVersion = constants.MaxTransactionVersion defaultMaximumStandardTransactionVersion = constants.MaxTransactionVersion
defaultDustConst = 1e12 // TODO: Determine real value
) )
// Config represents a mempool configuration // Config represents a mempool configuration
@ -50,6 +51,7 @@ type Config struct {
MinimumRelayTransactionFee util.Amount MinimumRelayTransactionFee util.Amount
MinimumStandardTransactionVersion uint16 MinimumStandardTransactionVersion uint16
MaximumStandardTransactionVersion uint16 MaximumStandardTransactionVersion uint16
DustConst uint64
} }
// DefaultConfig returns the default mempool configuration // DefaultConfig returns the default mempool configuration
@ -70,5 +72,6 @@ func DefaultConfig(dagParams *dagconfig.Params) *Config {
MinimumRelayTransactionFee: defaultMinimumRelayTransactionFee, MinimumRelayTransactionFee: defaultMinimumRelayTransactionFee,
MinimumStandardTransactionVersion: defaultMinimumStandardTransactionVersion, MinimumStandardTransactionVersion: defaultMinimumStandardTransactionVersion,
MaximumStandardTransactionVersion: defaultMaximumStandardTransactionVersion, MaximumStandardTransactionVersion: defaultMaximumStandardTransactionVersion,
DustConst: defaultDustConst,
} }
} }

View File

@ -1,6 +1,7 @@
package mempool package mempool
import ( import (
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
"sync" "sync"
"github.com/kaspanet/kaspad/domain/consensusreference" "github.com/kaspanet/kaspad/domain/consensusreference"
@ -137,7 +138,7 @@ func (mp *mempool) HandleNewBlockTransactions(transactions []*externalapi.Domain
return mp.handleNewBlockTransactions(transactions) return mp.handleNewBlockTransactions(transactions)
} }
func (mp *mempool) BlockCandidateTransactions() []*externalapi.DomainTransaction { func (mp *mempool) BlockCandidateTransactions() []*model.MempoolTransaction {
mp.mtx.RLock() mp.mtx.RLock()
defer mp.mtx.RUnlock() defer mp.mtx.RUnlock()

View File

@ -11,6 +11,7 @@ type MempoolTransaction struct {
parentTransactionsInPool IDToTransactionMap parentTransactionsInPool IDToTransactionMap
isHighPriority bool isHighPriority bool
addedAtDAAScore uint64 addedAtDAAScore uint64
mass uint64
} }
// NewMempoolTransaction constructs a new MempoolTransaction // NewMempoolTransaction constructs a new MempoolTransaction
@ -19,12 +20,14 @@ func NewMempoolTransaction(
parentTransactionsInPool IDToTransactionMap, parentTransactionsInPool IDToTransactionMap,
isHighPriority bool, isHighPriority bool,
addedAtDAAScore uint64, addedAtDAAScore uint64,
mass uint64,
) *MempoolTransaction { ) *MempoolTransaction {
return &MempoolTransaction{ return &MempoolTransaction{
transaction: transaction, transaction: transaction,
parentTransactionsInPool: parentTransactionsInPool, parentTransactionsInPool: parentTransactionsInPool,
isHighPriority: isHighPriority, isHighPriority: isHighPriority,
addedAtDAAScore: addedAtDAAScore, addedAtDAAScore: addedAtDAAScore,
mass: mass,
} }
} }
@ -57,3 +60,17 @@ func (mt *MempoolTransaction) IsHighPriority() bool {
func (mt *MempoolTransaction) AddedAtDAAScore() uint64 { func (mt *MempoolTransaction) AddedAtDAAScore() uint64 {
return mt.addedAtDAAScore return mt.addedAtDAAScore
} }
func (mt *MempoolTransaction) Mass() uint64 {
return mt.mass
}
func (mt *MempoolTransaction) Clone() *MempoolTransaction {
return &MempoolTransaction{
transaction: mt.transaction.Clone(),
parentTransactionsInPool: mt.parentTransactionsInPool,
isHighPriority: mt.isHighPriority,
addedAtDAAScore: mt.addedAtDAAScore,
mass: mt.mass,
}
}

View File

@ -218,6 +218,7 @@ func (op *orphansPool) unorphanTransaction(transaction *model.OrphanTransaction)
op.mempool.transactionsPool.getParentTransactionsInPool(transaction.Transaction()), op.mempool.transactionsPool.getParentTransactionsInPool(transaction.Transaction()),
false, false,
virtualDAAScore, virtualDAAScore,
0,
) )
err = op.mempool.transactionsPool.addMempoolTransaction(mempoolTransaction) err = op.mempool.transactionsPool.addMempoolTransaction(mempoolTransaction)
if err != nil { if err != nil {

View File

@ -41,7 +41,7 @@ func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransa
} }
mempoolTransaction := model.NewMempoolTransaction( mempoolTransaction := model.NewMempoolTransaction(
transaction, parentTransactionsInPool, isHighPriority, virtualDAAScore) transaction, parentTransactionsInPool, isHighPriority, virtualDAAScore, tp.calcMass(transaction))
err = tp.addMempoolTransaction(mempoolTransaction) err = tp.addMempoolTransaction(mempoolTransaction)
if err != nil { if err != nil {
@ -51,6 +51,27 @@ func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransa
return mempoolTransaction, nil return mempoolTransaction, nil
} }
func (tp *transactionsPool) calcMass(tx *externalapi.DomainTransaction) uint64 {
// TODO: Insert link for relevant KIP
if tx.Mass == 0 {
panic(errors.Errorf("tx %s is expected to have a populated mass", consensushashing.TransactionID(tx)))
}
addedMass := uint64(0)
sumOutsValue := uint64(0)
for _, output := range tx.Outputs {
addedMass += tp.mempool.config.DustConst / output.Value
sumOutsValue += output.Value
}
reducedMass := uint64(len(tx.Inputs)*len(tx.Inputs)) * tp.mempool.config.DustConst / sumOutsValue
if addedMass < reducedMass {
return tx.Mass
}
return tx.Mass + addedMass - reducedMass
}
func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error { func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error {
tp.allTransactions[*transaction.TransactionID()] = transaction tp.allTransactions[*transaction.TransactionID()] = transaction
@ -131,12 +152,12 @@ func (tp *transactionsPool) expireOldTransactions() error {
return nil return nil
} }
func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransaction { func (tp *transactionsPool) allReadyTransactions() []*model.MempoolTransaction {
result := []*externalapi.DomainTransaction{} result := []*model.MempoolTransaction{}
for _, mempoolTransaction := range tp.allTransactions { for _, mempoolTransaction := range tp.allTransactions {
if len(mempoolTransaction.ParentTransactionsInPool()) == 0 { if len(mempoolTransaction.ParentTransactionsInPool()) == 0 {
result = append(result, mempoolTransaction.Transaction().Clone()) //this pointer leaves the mempool, and gets its utxo set to nil, hence we clone. result = append(result, mempoolTransaction.Clone()) //this pointer leaves the mempool, and gets its utxo set to nil, hence we clone.
} }
} }

View File

@ -2,13 +2,14 @@ package model
import ( import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
) )
// Mempool maintains a set of known transactions that // Mempool maintains a set of known transactions that
// are intended to be mined into new blocks // are intended to be mined into new blocks
type Mempool interface { type Mempool interface {
HandleNewBlockTransactions(txs []*externalapi.DomainTransaction) ([]*externalapi.DomainTransaction, error) HandleNewBlockTransactions(txs []*externalapi.DomainTransaction) ([]*externalapi.DomainTransaction, error)
BlockCandidateTransactions() []*externalapi.DomainTransaction BlockCandidateTransactions() []*model.MempoolTransaction
ValidateAndInsertTransaction(transaction *externalapi.DomainTransaction, isHighPriority bool, allowOrphan bool) ( ValidateAndInsertTransaction(transaction *externalapi.DomainTransaction, isHighPriority bool, allowOrphan bool) (
acceptedTransactions []*externalapi.DomainTransaction, err error) acceptedTransactions []*externalapi.DomainTransaction, err error)
RemoveTransactions(txs []*externalapi.DomainTransaction, removeRedeemers bool) error RemoveTransactions(txs []*externalapi.DomainTransaction, removeRedeemers bool) error

View File

@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs
const ( const (
appMajor uint = 0 appMajor uint = 0
appMinor uint = 12 appMinor uint = 12
appPatch uint = 13 appPatch uint = 15
) )
// appBuild is defined as a variable so it can be overridden during the build // appBuild is defined as a variable so it can be overridden during the build