Remove HF1 activation code (#2042)

* Remove HF1 activation code

* Remove test with an overflow

* Fix "max sompi amount is never dust"

* Remove estimatedHeaderUpperBound logic
This commit is contained in:
Ori Newman 2022-05-05 20:35:17 +03:00 committed by GitHub
parent 52fbeedf20
commit 7390651072
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 84 additions and 324 deletions

View File

@ -23,7 +23,7 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
// errChan is used by the flow goroutines to return to runFlows when an error occurs.
// They are both initialized here and passed to register flows.
isStopping := uint32(0)
errChan := make(chan error)
errChan := make(chan error, 1)
receiveVersionRoute, sendVersionRoute, receiveReadyRoute := registerHandshakeRoutes(router)

View File

@ -2,10 +2,7 @@ package libkaspawallet_test
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/pkg/errors"
"strings"
"testing"
@ -321,7 +318,6 @@ func TestMaxSompi(t *testing.T) {
cfg := *consensusConfig
cfg.BlockCoinbaseMaturity = 0
cfg.PreDeflationaryPhaseBaseSubsidy = 20e6 * constants.SompiPerKaspa
cfg.HF1DAAScore = cfg.GenesisBlock.Header.DAAScore() + 10
tc, teardown, err := consensus.NewFactory().NewTestConsensus(&cfg, "TestMaxSompi")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
@ -457,8 +453,8 @@ func TestMaxSompi(t *testing.T) {
TransactionID: *consensushashing.TransactionID(txWithLargeInputAmount),
Index: 0,
}
if virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO1) {
t.Fatalf("Transaction was accepted in the DAG")
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO1) {
t.Fatalf("Transaction wasn't accepted in the DAG")
}
selectedUTXOsForTxWithLargeInputAndOutputAmount := []*libkaspawallet.UTXO{
@ -499,34 +495,13 @@ func TestMaxSompi(t *testing.T) {
t.Fatalf("ExtractTransaction: %+v", err)
}
_, _, err = tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{txWithLargeInputAndOutputAmount})
if !errors.Is(err, ruleerrors.ErrBadTxOutValue) {
t.Fatalf("AddBlock: %+v", err)
}
tip := block1Hash
for {
tip, _, err = tc.AddBlock([]*externalapi.DomainHash{tip}, nil, nil)
// We're creating a new longer chain so we can double spend txWithLargeInputAmount
newChainRoot, _, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
selectedTip, err := tc.GetVirtualSelectedParent()
if err != nil {
t.Fatalf("GetVirtualDAAScore: %+v", err)
}
daaScore, err := tc.DAABlocksStore().DAAScore(tc.DatabaseContext(), model.NewStagingArea(), selectedTip)
if err != nil {
t.Fatalf("DAAScore: %+v", err)
}
if daaScore >= cfg.HF1DAAScore {
break
}
}
tip, virtualChangeSet, err = tc.AddBlock([]*externalapi.DomainHash{tip}, nil, []*externalapi.DomainTransaction{txWithLargeInputAndOutputAmount})
_, virtualChangeSet, err = tc.AddBlock([]*externalapi.DomainHash{newChainRoot}, nil, []*externalapi.DomainTransaction{txWithLargeInputAndOutputAmount})
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@ -539,14 +514,5 @@ func TestMaxSompi(t *testing.T) {
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO2) {
t.Fatalf("txWithLargeInputAndOutputAmount weren't accepted in the DAG")
}
_, virtualChangeSet, err = tc.AddBlock([]*externalapi.DomainHash{tip}, nil, []*externalapi.DomainTransaction{txWithLargeInputAmount})
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO1) {
t.Fatalf("txWithLargeInputAmount wasn't accepted in the DAG")
}
})
}

View File

@ -217,8 +217,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
pastMedianTimeManager,
ghostdagDataStore,
daaBlocksStore,
txMassCalculator,
config.HF1DAAScore)
txMassCalculator)
difficultyManager := f.difficultyConstructor(
dbManager,
ghostdagManager,
@ -266,7 +265,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
finalityManager,
genesisHash,
config.MergeDepth,
config.HF1DAAScore,
ghostdagDataStore,
mergeDepthRootStore,
daaBlocksStore,
@ -344,7 +342,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
config.MaxBlockParents,
config.TimestampDeviationTolerance,
config.TargetTimePerBlock,
config.HF1DAAScore,
config.MaxBlockLevel,
dbManager,
@ -393,7 +390,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockBuilder := blockbuilder.New(
dbManager,
genesisHash,
config.HF1DAAScore,
difficultyManager,
pastMedianTimeManager,

View File

@ -185,7 +185,6 @@ func TestBoundedMergeDepth(t *testing.T) {
consensusConfig.K = 5
consensusConfig.MergeDepth = 7
consensusConfig.FinalityDuration = 20 * consensusConfig.TargetTimePerBlock
consensusConfig.HF1DAAScore = consensusConfig.GenesisBlock.Header.DAAScore() + 200
if uint64(consensusConfig.K) >= consensusConfig.FinalityDepth() {
t.Fatal("K must be smaller than finality duration for this test to run")
@ -483,56 +482,6 @@ func TestBoundedMergeDepth(t *testing.T) {
}
}
test(consensusConfig.FinalityDepth(), consensusConfig.GenesisHash, true, true)
virtualDAAScore, err := consensusReal.GetVirtualDAAScore()
if err != nil {
t.Fatalf("GetVirtualDAAScore: %+v", err)
}
if virtualDAAScore > consensusConfig.HF1DAAScore {
t.Fatalf("Hard fork is already activated")
}
tipBeforeHFActivated, err := consensusReal.GetVirtualSelectedParent()
if err != nil {
t.Fatalf("GetVirtualSelectedParent: %+v", err)
}
tip := tipBeforeHFActivated
for {
tip, _, err = consensusReal.AddBlock([]*externalapi.DomainHash{tip}, nil, nil)
if err != nil {
t.Fatalf("Failed adding block: %+v", err)
}
daaScore, err := consensusReal.DAABlocksStore().DAAScore(consensusReal.DatabaseContext(), model.NewStagingArea(), tip)
if err != nil {
t.Fatalf("Failed adding block: %+v", err)
}
// We check what happens when on the transition between rules: if we merge a chain that
// started before the HF was activated, but the HF was already activated for the merging
// block, the HF rules should apply.
// The checked block in `test` is going to have a DAA score of `tip.DAAScore + depth + 5`,
// so this is why we started to test from this depth.
if daaScore == consensusConfig.HF1DAAScore-consensusConfig.MergeDepth-5 {
test(consensusConfig.MergeDepth, tip, true, true)
}
if daaScore > consensusConfig.HF1DAAScore {
virtualSelectedParent, err := consensusReal.GetVirtualSelectedParent()
if err != nil {
t.Fatalf("GetVirtualSelectedParent: %+v", err)
}
if virtualSelectedParent.Equal(tip) {
break
}
}
}
test(consensusConfig.MergeDepth, tip, true, true)
test(consensusConfig.FinalityDepth(), tipBeforeHFActivated, false, true)
test(consensusConfig.MergeDepth, tipBeforeHFActivated, false, false)
test(consensusConfig.MergeDepth, consensusConfig.GenesisHash, true, true)
})
}

View File

@ -20,7 +20,6 @@ import (
type blockBuilder struct {
databaseContext model.DBManager
genesisHash *externalapi.DomainHash
hf1DAAScore uint64
difficultyManager model.DifficultyManager
pastMedianTimeManager model.PastMedianTimeManager
@ -43,7 +42,6 @@ type blockBuilder struct {
func New(
databaseContext model.DBManager,
genesisHash *externalapi.DomainHash,
hf1DAAScore uint64,
difficultyManager model.DifficultyManager,
pastMedianTimeManager model.PastMedianTimeManager,
@ -65,7 +63,6 @@ func New(
return &blockBuilder{
databaseContext: databaseContext,
genesisHash: genesisHash,
hf1DAAScore: hf1DAAScore,
difficultyManager: difficultyManager,
pastMedianTimeManager: pastMedianTimeManager,
@ -227,13 +224,8 @@ func (bb *blockBuilder) buildHeader(stagingArea *model.StagingArea, transactions
return nil, err
}
version := constants.BlockVersionBeforeHF1
if daaScore >= bb.hf1DAAScore {
version = constants.BlockVersionAfterHF1
}
return blockheader.NewImmutableBlockHeader(
version,
constants.BlockVersion,
parents,
hashMerkleRoot,
acceptedIDMerkleRoot,

View File

@ -94,14 +94,9 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingAre
})
}
version := constants.BlockVersionBeforeHF1
if daaScore >= bb.hf1DAAScore {
version = constants.BlockVersionAfterHF1
}
bb.nonceCounter++
return blockheader.NewImmutableBlockHeader(
version,
constants.BlockVersion,
parents,
hashMerkleRoot,
&externalapi.DomainHash{},

View File

@ -220,10 +220,6 @@ func (v *blockValidator) validateGasLimit(block *externalapi.DomainBlock) error
func (v *blockValidator) checkBlockMass(block *externalapi.DomainBlock) error {
mass := uint64(0)
if block.Header.DAAScore() < v.hf1DAAScore {
mass += v.headerEstimatedSerializedSize(block.Header)
}
for _, transaction := range block.Transactions {
v.transactionValidator.PopulateMass(transaction)

View File

@ -1307,7 +1307,7 @@ func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consens
return &externalapi.DomainBlock{
Header: blockheader.NewImmutableBlockHeader(
constants.BlockVersionBeforeHF1,
constants.BlockVersion,
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{consensusConfig.GenesisHash}},
merkle.CalculateHashMerkleRoot([]*externalapi.DomainTransaction{tx}),
&externalapi.DomainHash{},

View File

@ -108,11 +108,7 @@ func TestCheckParentsIncest(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
version := constants.BlockVersionBeforeHF1
if consensusConfig.HF1DAAScore == 0 {
version = constants.BlockVersionAfterHF1
}
version := constants.BlockVersion
directParentsRelationBlock := &externalapi.DomainBlock{
Header: blockheader.NewImmutableBlockHeader(
version,

View File

@ -56,16 +56,9 @@ func (v *blockValidator) checkParentsLimit(header externalapi.BlockHeader) error
}
func (v *blockValidator) checkBlockVersion(header externalapi.BlockHeader) error {
if header.DAAScore() >= v.hf1DAAScore {
if header.Version() != constants.BlockVersionAfterHF1 {
if header.Version() != constants.BlockVersion {
return errors.Wrapf(
ruleerrors.ErrWrongBlockVersion, "After HF1 the block version should be %d", constants.BlockVersionAfterHF1)
}
} else {
if header.Version() != constants.BlockVersionBeforeHF1 {
return errors.Wrapf(
ruleerrors.ErrWrongBlockVersion, "Beofre HF1 the block version should be %d", constants.BlockVersionBeforeHF1)
}
ruleerrors.ErrWrongBlockVersion, "The block version should be %d", constants.BlockVersion)
}
return nil
}

View File

@ -62,11 +62,7 @@ func CheckBlockVersion(t *testing.T, tc testapi.TestConsensus, consensusConfig *
t.Fatalf("BuildBlockWithParents: %+v", err)
}
expectedVersion := constants.BlockVersionBeforeHF1
if consensusConfig.HF1DAAScore == 0 {
expectedVersion = constants.BlockVersionAfterHF1
}
expectedVersion := constants.BlockVersion
block.Header = blockheader.NewImmutableBlockHeader(
expectedVersion+1,
block.Header.Parents(),

View File

@ -24,7 +24,6 @@ type blockValidator struct {
maxBlockParents externalapi.KType
timestampDeviationTolerance int
targetTimePerBlock time.Duration
hf1DAAScore uint64
maxBlockLevel int
databaseContext model.DBReader
@ -64,7 +63,6 @@ func New(powMax *big.Int,
maxBlockParents externalapi.KType,
timestampDeviationTolerance int,
targetTimePerBlock time.Duration,
hf1DAAScore uint64,
maxBlockLevel int,
databaseContext model.DBReader,
@ -104,7 +102,6 @@ func New(powMax *big.Int,
maxBlockMass: maxBlockMass,
mergeSetSizeLimit: mergeSetSizeLimit,
maxBlockParents: maxBlockParents,
hf1DAAScore: hf1DAAScore,
maxBlockLevel: maxBlockLevel,
timestampDeviationTolerance: timestampDeviationTolerance,

View File

@ -1,28 +0,0 @@
package blockvalidator
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// headerEstimatedSerializedSize is the estimated size of a block header in some
// serialization. This has to be deterministic, but not necessarily accurate, since
// it's only used to check block size limit violation.
func (v *blockValidator) headerEstimatedSerializedSize(header externalapi.BlockHeader) uint64 {
size := uint64(0)
size += 2 // Version (uint16)
size += 8 // number of block levels (uint64)
for _, blockLevelParents := range header.Parents() {
size += 8 // number of parents in the block level (uint64)
size += uint64(externalapi.DomainHashSize * len(blockLevelParents)) // parents
}
size += externalapi.DomainHashSize // HashMerkleRoot
size += externalapi.DomainHashSize // AcceptedIDMerkleRoot
size += externalapi.DomainHashSize // UTXOCommitment
size += 8 // TimeInMilliseconds (int64)
size += 4 // Bits (uint32)
size += 8 // Nonce (uint64)
return size
}

View File

@ -111,7 +111,7 @@ func TestGHOSTDAG(t *testing.T) {
blockID := StringToDomainHash(testBlockData.ID)
dagTopology.parentsMap[*blockID] = StringToDomainHashSlice(testBlockData.Parents)
blockHeadersStore.dagMap[*blockID] = blockheader.NewImmutableBlockHeader(
constants.BlockVersionBeforeHF1,
constants.BlockVersion,
[]externalapi.BlockLevelParents{StringToDomainHashSlice(testBlockData.Parents)},
nil,
nil,

View File

@ -16,7 +16,6 @@ type mergeDepthManager struct {
genesisHash *externalapi.DomainHash
mergeDepth uint64
hf1DAAScore uint64
ghostdagDataStore model.GHOSTDAGDataStore
mergeDepthRootStore model.MergeDepthRootStore
@ -34,7 +33,6 @@ func New(
genesisHash *externalapi.DomainHash,
mergeDepth uint64,
hf1DAAScore uint64,
ghostdagDataStore model.GHOSTDAGDataStore,
mergeDepthRootStore model.MergeDepthRootStore,
@ -49,7 +47,6 @@ func New(
finalityManager: finalityManager,
genesisHash: genesisHash,
mergeDepth: mergeDepth,
hf1DAAScore: hf1DAAScore,
ghostdagDataStore: ghostdagDataStore,
mergeDepthRootStore: mergeDepthRootStore,
daaBlocksStore: daaBlocksStore,
@ -71,19 +68,24 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(stagingArea *model.StagingA
return nil
}
// For validation, we must follow the HF1 DAA score in order to determine the correct depth to verify
mergeDepthRootByHF1, err := mdm.mergeDepthRootByHF1DAAScoreForValidationOnly(stagingArea, blockHash, isBlockWithTrustedData)
mergeDepthRoot, err := mdm.MergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
nonBoundedMergeDepthViolatingBlues, err := mdm.NonBoundedMergeDepthViolatingBlues(stagingArea, blockHash, mergeDepthRootByHF1)
// We call FinalityPoint in order to save it to storage.
_, err = mdm.finalityManager.FinalityPoint(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
nonBoundedMergeDepthViolatingBlues, err := mdm.NonBoundedMergeDepthViolatingBlues(stagingArea, blockHash, mergeDepthRoot)
if err != nil {
return err
}
for _, red := range ghostdagData.MergeSetReds() {
doesRedHaveMergeRootInPast, err := mdm.dagTopologyManager.IsAncestorOf(stagingArea, mergeDepthRootByHF1, red)
doesRedHaveMergeRootInPast, err := mdm.dagTopologyManager.IsAncestorOf(stagingArea, mergeDepthRoot, red)
if err != nil {
return err
}
@ -133,34 +135,6 @@ func (mdm *mergeDepthManager) NonBoundedMergeDepthViolatingBlues(
return nonBoundedMergeDepthViolatingBlues, nil
}
func (mdm *mergeDepthManager) mergeDepthRootByHF1DAAScoreForValidationOnly(
stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) (*externalapi.DomainHash, error) {
daaScore, err := mdm.daaBlocksStore.DAAScore(mdm.databaseContext, stagingArea, blockHash)
if err != nil {
return nil, err
}
// We call both, merge depth root and finality, in order to trigger storage persistency for both,
// although only one of them is used below
mergeDepthRoot, err := mdm.MergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return nil, err
}
// As noted above, this line should not be removed following the HF, unless we validate that storage of
// finality point is not needed any more
finalityPoint, err := mdm.finalityManager.FinalityPoint(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return nil, err
}
if daaScore >= mdm.hf1DAAScore {
return mergeDepthRoot, nil
}
// We fall back to the merge depth root before the HF, which was the finality point
return finalityPoint, nil
}
func (mdm *mergeDepthManager) VirtualMergeDepthRoot(stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
log.Tracef("VirtualMergeDepthRoot start")
defer log.Tracef("VirtualMergeDepthRoot end")

View File

@ -37,7 +37,7 @@ func TestPruning(t *testing.T) {
},
"dag-for-test-pruning.json": {
dagconfig.MainnetParams.Name: "503",
dagconfig.TestnetParams.Name: "502",
dagconfig.TestnetParams.Name: "503",
dagconfig.DevnetParams.Name: "503",
dagconfig.SimnetParams.Name: "503",
},

View File

@ -58,14 +58,6 @@ func (v *transactionValidator) ValidateTransactionInContextIgnoringUTXO(stagingA
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "unfinalized transaction %v", tx)
}
// TODO: Remove checkTransactionAmountRanges from here once HF was activated. It's only temporary
// because in the HF transition period checkTransactionAmountRanges is not context free.
isHF1Activated := povBlockDAAScore >= v.hf1DAAScore
err = v.checkTransactionAmountRanges(tx, isHF1Activated)
if err != nil {
return err
}
return nil
}
@ -81,13 +73,7 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateFee(stagin
return err
}
daaScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, stagingArea, povBlockHash)
if err != nil {
return err
}
isHF1Activated := daaScore >= v.hf1DAAScore
totalSompiIn, err := v.checkTransactionInputAmounts(tx, isHF1Activated)
totalSompiIn, err := v.checkTransactionInputAmounts(tx)
if err != nil {
return err
}
@ -149,7 +135,7 @@ func (v *transactionValidator) checkTransactionCoinbaseMaturity(stagingArea *mod
return nil
}
func (v *transactionValidator) checkTransactionInputAmounts(tx *externalapi.DomainTransaction, isHF1Activated bool) (totalSompiIn uint64, err error) {
func (v *transactionValidator) checkTransactionInputAmounts(tx *externalapi.DomainTransaction) (totalSompiIn uint64, err error) {
totalSompiIn = 0
var missingOutpoints []*externalapi.DomainOutpoint
@ -166,7 +152,7 @@ func (v *transactionValidator) checkTransactionInputAmounts(tx *externalapi.Doma
// a transaction are in a unit value known as a sompi. One
// kaspa is a quantity of sompi as defined by the
// SompiPerKaspa constant.
totalSompiIn, err = v.checkEntryAmounts(utxoEntry, totalSompiIn, isHF1Activated)
totalSompiIn, err = v.checkEntryAmounts(utxoEntry, totalSompiIn)
if err != nil {
return 0, err
}
@ -179,24 +165,19 @@ func (v *transactionValidator) checkTransactionInputAmounts(tx *externalapi.Doma
return totalSompiIn, nil
}
func (v *transactionValidator) checkEntryAmounts(entry externalapi.UTXOEntry, totalSompiInBefore uint64, isHF1Activated bool) (totalSompiInAfter uint64, err error) {
func (v *transactionValidator) checkEntryAmounts(entry externalapi.UTXOEntry, totalSompiInBefore uint64) (totalSompiInAfter uint64, err error) {
// The total of all outputs must not be more than the max
// allowed per transaction. Also, we could potentially overflow
// the accumulator so check for overflow.
maxSompi := constants.MaxSompiBeforeHF1
if isHF1Activated {
maxSompi = constants.MaxSompiAfterHF1
}
originTxSompi := entry.Amount()
totalSompiInAfter = totalSompiInBefore + originTxSompi
if totalSompiInAfter < totalSompiInBefore ||
totalSompiInAfter > maxSompi {
totalSompiInAfter > constants.MaxSompi {
return 0, errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
"inputs is %d which is higher than max "+
"allowed value of %d", totalSompiInBefore,
maxSompi)
constants.MaxSompi)
}
return totalSompiInAfter, nil
}

View File

@ -11,12 +11,11 @@ import (
// ValidateTransactionInIsolation validates the parts of the transaction that can be validated context-free
func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction, povDAAScore uint64) error {
isHF1Activated := povDAAScore >= v.hf1DAAScore
err := v.checkTransactionInputCount(tx)
if err != nil {
return err
}
err = v.checkTransactionAmountRanges(tx, isHF1Activated)
err = v.checkTransactionAmountRanges(tx)
if err != nil {
return err
}
@ -63,18 +62,13 @@ func (v *transactionValidator) checkTransactionInputCount(tx *externalapi.Domain
return nil
}
func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.DomainTransaction, isHF1Activated bool) error {
func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.DomainTransaction) error {
// Ensure the transaction amounts are in range. Each transaction
// output must not be negative or more than the max allowed per
// transaction. Also, the total of all outputs must abide by the same
// restrictions. All amounts in a transaction are in a unit value known
// as a sompi. One kaspa is a quantity of sompi as defined by the
// sompiPerKaspa constant.
maxSompi := constants.MaxSompiBeforeHF1
if isHF1Activated {
maxSompi = constants.MaxSompiAfterHF1
}
var totalSompi uint64
for _, txOut := range tx.Outputs {
sompi := txOut.Value
@ -82,9 +76,9 @@ func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.Doma
return errors.Wrap(ruleerrors.ErrTxOutValueZero, "zero value outputs are forbidden")
}
if sompi > maxSompi {
if sompi > constants.MaxSompi {
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "transaction output value of %d is "+
"higher than max allowed value of %d", sompi, maxSompi)
"higher than max allowed value of %d", sompi, constants.MaxSompi)
}
// Binary arithmetic guarantees that any overflow is detected and reported.
@ -94,14 +88,14 @@ func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.Doma
if newTotalSompi < totalSompi {
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
"outputs exceeds max allowed value of %d",
maxSompi)
constants.MaxSompi)
}
totalSompi = newTotalSompi
if totalSompi > maxSompi {
if totalSompi > constants.MaxSompi {
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
"outputs is %d which is higher than max "+
"allowed value of %d", totalSompi,
maxSompi)
constants.MaxSompi)
}
}

View File

@ -22,7 +22,6 @@ type txSubnetworkData struct {
func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
cfg := *consensusConfig
cfg.HF1DAAScore = 20
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(&cfg, "TestValidateTransactionInIsolationAndPopulateMass")
@ -45,22 +44,22 @@ func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
{"good one", 1, 1, 1, subnetworks.SubnetworkIDNative, nil, nil, nil, 0},
{"no inputs", 0, 1, 1, subnetworks.SubnetworkIDNative, nil, nil, ruleerrors.ErrNoTxInputs, 0},
{"no outputs", 1, 0, 1, subnetworks.SubnetworkIDNative, nil, nil, nil, 0},
{"too much sompi in one output", 1, 1, constants.MaxSompiBeforeHF1 + 1,
{"too much sompi in one output", 1, 1, constants.MaxSompi + 1,
subnetworks.SubnetworkIDNative,
nil,
nil,
ruleerrors.ErrBadTxOutValue, 0},
{"too much sompi before- valid now", 1, 1, constants.MaxSompiBeforeHF1 + 1,
{"too much sompi before- valid now", 1, 1, 21e14 + 1,
subnetworks.SubnetworkIDNative,
nil,
nil,
nil, cfg.HF1DAAScore},
{"too much sompi in one output - after hf", 1, 1, constants.MaxSompiAfterHF1 + 1,
nil, 0},
{"too much sompi in one output - after hf", 1, 1, constants.MaxSompi + 1,
subnetworks.SubnetworkIDNative,
nil,
nil,
ruleerrors.ErrBadTxOutValue, cfg.HF1DAAScore},
{"too much sompi in one output", 1, 1, constants.MaxSompiAfterHF1 + 1,
ruleerrors.ErrBadTxOutValue, 0},
{"too much sompi in one output", 1, 1, constants.MaxSompi + 1,
subnetworks.SubnetworkIDNative,
nil,
nil,

View File

@ -21,7 +21,6 @@ type transactionValidator struct {
sigCache *txscript.SigCache
sigCacheECDSA *txscript.SigCacheECDSA
txMassCalculator *txmass.Calculator
hf1DAAScore uint64
}
// New instantiates a new TransactionValidator
@ -32,8 +31,7 @@ func New(blockCoinbaseMaturity uint64,
pastMedianTimeManager model.PastMedianTimeManager,
ghostdagDataStore model.GHOSTDAGDataStore,
daaBlocksStore model.DAABlocksStore,
txMassCalculator *txmass.Calculator,
hf1DAAScore uint64) model.TransactionValidator {
txMassCalculator *txmass.Calculator) model.TransactionValidator {
return &transactionValidator{
blockCoinbaseMaturity: blockCoinbaseMaturity,
@ -46,6 +44,5 @@ func New(blockCoinbaseMaturity uint64,
sigCache: txscript.NewSigCache(sigCacheSize),
sigCacheECDSA: txscript.NewSigCacheECDSA(sigCacheSize),
txMassCalculator: txMassCalculator,
hf1DAAScore: hf1DAAScore,
}
}

View File

@ -21,7 +21,6 @@ import (
func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.HF1DAAScore = consensusConfig.GenesisBlock.Header.DAAScore() + 1000
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
"TestValidateTransactionInContextAndPopulateFee")
@ -92,7 +91,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
constants.MaxSompiBeforeHF1+1,
21e14+1,
scriptPublicKey,
false,
0),
@ -104,7 +103,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
constants.MaxSompiAfterHF1+1,
constants.MaxSompi+1,
scriptPublicKey,
false,
0),
@ -163,7 +162,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
Gas: 0,
LockTime: 0}
txWithLargeAmountAfterHF := externalapi.DomainTransaction{
txWithInvalidAmount := externalapi.DomainTransaction{
Version: constants.MaxTransactionVersion,
Inputs: []*externalapi.DomainTransactionInput{&txInputWithLargeAmountAfterHF},
Outputs: []*externalapi.DomainTransactionOutput{&txOutput},
@ -207,9 +206,6 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
povBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x01})
tc.DAABlocksStore().StageDAAScore(stagingArea, povBlockHash, consensusConfig.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockDAAScore())
povAfterHFBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x02})
tc.DAABlocksStore().StageDAAScore(stagingArea, povAfterHFBlockHash, consensusConfig.HF1DAAScore)
// Just use some stub ghostdag data
tc.GHOSTDAGDataStore().Stage(stagingArea, povBlockHash, externalapi.NewBlockGHOSTDAGData(
0,
@ -242,24 +238,17 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
isValid: false,
expectedError: ruleerrors.ErrImmatureSpend,
},
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompiBeforeHF1)
name: "checkTransactionInputAmounts - invalid - before HF",
{ // The total inputs amount is bigger than the allowed maximum before the HF (21e14)
name: "checkTransactionInputAmounts - valid",
tx: &txWithLargeAmountBeforeHF,
povBlockHash: povBlockHash,
isValid: false,
expectedError: ruleerrors.ErrBadTxOutValue,
},
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompiBeforeHF1)
name: "checkTransactionInputAmounts - valid - after HF",
tx: &txWithLargeAmountBeforeHF,
povBlockHash: povAfterHFBlockHash,
isValid: true,
expectedError: nil,
},
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompiBeforeHF1)
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompi)
name: "checkTransactionInputAmounts - invalid - after HF",
tx: &txWithLargeAmountAfterHF,
povBlockHash: povAfterHFBlockHash,
tx: &txWithInvalidAmount,
povBlockHash: povBlockHash,
isValid: false,
expectedError: ruleerrors.ErrBadTxOutValue,
},

View File

@ -3,11 +3,8 @@ package constants
import "math"
const (
// BlockVersionBeforeHF1 represents the current version of blocks mined before HF1
BlockVersionBeforeHF1 uint16 = 0
// BlockVersionAfterHF1 represents the current version of blocks mined after HF1
BlockVersionAfterHF1 uint16 = 1
// BlockVersion represents the current block version
BlockVersion uint16 = 1
// MaxTransactionVersion is the current latest supported transaction version.
MaxTransactionVersion uint16 = 0
@ -18,11 +15,8 @@ const (
// SompiPerKaspa is the number of sompi in one kaspa (1 KAS).
SompiPerKaspa = 100_000_000
// MaxSompiBeforeHF1 is the maximum transaction amount allowed in sompi before the HF1 hard fork is activated.
MaxSompiBeforeHF1 = uint64(21_000_000 * SompiPerKaspa)
// MaxSompiAfterHF1 is the maximum transaction amount allowed in sompi after the HF1 hard fork is activated.
MaxSompiAfterHF1 = uint64(29_000_000_000 * SompiPerKaspa)
// MaxSompi is the maximum transaction amount allowed in sompi.
MaxSompi = uint64(29_000_000_000 * SompiPerKaspa)
// MaxTxInSequenceNum is the maximum sequence number the sequence field
// of a transaction input can be.

View File

@ -188,7 +188,6 @@ type Params struct {
MaxBlockLevel int
MergeDepth uint64
HF1DAAScore uint64
}
// NormalizeRPCServerAddress returns addr with the current network default
@ -288,7 +287,6 @@ var MainnetParams = Params{
// This means that any block that has a level lower or equal to genesis will be level 0.
MaxBlockLevel: 225,
MergeDepth: defaultMergeDepth,
HF1DAAScore: 14687583,
}
// TestnetParams defines the network parameters for the test Kaspa network.
@ -351,7 +349,6 @@ var TestnetParams = Params{
MaxBlockLevel: 250,
MergeDepth: defaultMergeDepth,
HF1DAAScore: 172800,
}
// SimnetParams defines the network parameters for the simulation test Kaspa

View File

@ -5,7 +5,6 @@ import (
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/domain/miningmanager/blocktemplatebuilder"
mempoolpkg "github.com/kaspanet/kaspad/domain/miningmanager/mempool"
"github.com/pkg/errors"
"sync"
"time"
)
@ -22,15 +21,7 @@ func (f *factory) NewMiningManager(consensusReference consensusreference.Consens
mempoolConfig *mempoolpkg.Config) MiningManager {
mempool := mempoolpkg.New(mempoolConfig, consensusReference)
// In the current pruning window (according to 06/04/2022) the header with the most mass weighted 5294 grams.
// We take a 10x factor for safety.
// TODO: Remove this behaviour once `ignoreHeaderMass` is set to true in all networks.
const estimatedHeaderUpperBound = 60000
if estimatedHeaderUpperBound > params.MaxBlockMass {
panic(errors.Errorf("Estimated header mass upper bound is higher than the max block mass allowed"))
}
maxBlockMass := params.MaxBlockMass - estimatedHeaderUpperBound
blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, maxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength)
blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, params.MaxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength)
return &miningManager{
consensusReference: consensusReference,

View File

@ -198,9 +198,8 @@ func (mp *mempool) minimumRequiredTransactionRelayFee(mass uint64) uint64 {
// Set the minimum fee to the maximum possible value if the calculated
// fee is not in the valid range for monetary amounts.
// TODO: Replace it with constants.MaxSompiAfterHF1 once HF is activated
if minimumFee > constants.MaxSompiBeforeHF1 {
minimumFee = constants.MaxSompiBeforeHF1
if minimumFee > constants.MaxSompi {
minimumFee = constants.MaxSompi
}
return minimumFee

View File

@ -50,12 +50,6 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
defaultMinimumRelayTransactionFee,
100000,
},
{
"max standard tx size with max sompi relay fee",
MaximumStandardTransactionMass,
util.Amount(constants.MaxSompiBeforeHF1),
constants.MaxSompiBeforeHF1,
},
{
"1500 bytes with 5000 relay fee",
1500,
@ -156,8 +150,8 @@ func TestIsTransactionOutputDust(t *testing.T) {
{
// Maximum allowed value is never dust.
"max sompi amount is never dust",
externalapi.DomainTransactionOutput{Value: constants.MaxSompiBeforeHF1, ScriptPublicKey: scriptPublicKey},
util.Amount(constants.MaxSompiBeforeHF1),
externalapi.DomainTransactionOutput{Value: constants.MaxSompi, ScriptPublicKey: scriptPublicKey},
util.Amount(1000),
false,
},
{

View File

@ -58,12 +58,12 @@ func (id *ID) SerializeToBytes() ([]byte, error) {
}
// FromBytes returns an ID deserialized from the given byte slice.
func FromBytes(serializedID []byte) *ID {
func FromBytes(serializedID []byte) (*ID, error) {
r := bytes.NewReader(serializedID)
newID := new(ID)
err := newID.Deserialize(r)
if err != nil {
panic(err)
return nil, err
}
return newID
return newID, nil
}

View File

@ -35,13 +35,22 @@ func (x *VersionMessage) toAppMessage() (appmessage.Message, error) {
return nil, err
}
if x.Id == nil {
return nil, errors.Wrapf(errorNil, "VersionMessage.Id is nil")
}
appMsgID, err := id.FromBytes(x.Id)
if err != nil {
return nil, err
}
return &appmessage.MsgVersion{
ProtocolVersion: x.ProtocolVersion,
Network: x.Network,
Services: appmessage.ServiceFlag(x.Services),
Timestamp: mstime.UnixMilliseconds(x.Timestamp),
Address: address,
ID: id.FromBytes(x.Id),
ID: appMsgID,
UserAgent: x.UserAgent,
DisableRelayTx: x.DisableRelayTx,
SubnetworkID: subnetworkID,

View File

@ -28,15 +28,9 @@ func TestAmountCreation(t *testing.T) {
},
{
name: "max producible",
amount: 21e6,
amount: 29e9,
valid: true,
expected: Amount(constants.MaxSompiBeforeHF1),
},
{
name: "exceeds max producible",
amount: 21e6 + 1e-8,
valid: true,
expected: Amount(constants.MaxSompiBeforeHF1) + 1,
expected: Amount(constants.MaxSompi),
},
{
name: "one hundred",
@ -109,10 +103,10 @@ func TestAmountUnitConversions(t *testing.T) {
}{
{
name: "MKAS",
amount: Amount(constants.MaxSompiBeforeHF1),
amount: Amount(constants.MaxSompi),
unit: AmountMegaKAS,
converted: 21,
s: "21 MKAS",
converted: 29000,
s: "29000 MKAS",
},
{
name: "kKAS",