mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-07-09 14:22:33 +00:00
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:
parent
52fbeedf20
commit
7390651072
@ -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.
|
// 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.
|
// They are both initialized here and passed to register flows.
|
||||||
isStopping := uint32(0)
|
isStopping := uint32(0)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
receiveVersionRoute, sendVersionRoute, receiveReadyRoute := registerHandshakeRoutes(router)
|
receiveVersionRoute, sendVersionRoute, receiveReadyRoute := registerHandshakeRoutes(router)
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@ package libkaspawallet_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -321,7 +318,6 @@ func TestMaxSompi(t *testing.T) {
|
|||||||
cfg := *consensusConfig
|
cfg := *consensusConfig
|
||||||
cfg.BlockCoinbaseMaturity = 0
|
cfg.BlockCoinbaseMaturity = 0
|
||||||
cfg.PreDeflationaryPhaseBaseSubsidy = 20e6 * constants.SompiPerKaspa
|
cfg.PreDeflationaryPhaseBaseSubsidy = 20e6 * constants.SompiPerKaspa
|
||||||
cfg.HF1DAAScore = cfg.GenesisBlock.Header.DAAScore() + 10
|
|
||||||
tc, teardown, err := consensus.NewFactory().NewTestConsensus(&cfg, "TestMaxSompi")
|
tc, teardown, err := consensus.NewFactory().NewTestConsensus(&cfg, "TestMaxSompi")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error setting up tc: %+v", err)
|
t.Fatalf("Error setting up tc: %+v", err)
|
||||||
@ -457,8 +453,8 @@ func TestMaxSompi(t *testing.T) {
|
|||||||
TransactionID: *consensushashing.TransactionID(txWithLargeInputAmount),
|
TransactionID: *consensushashing.TransactionID(txWithLargeInputAmount),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
if virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO1) {
|
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO1) {
|
||||||
t.Fatalf("Transaction was accepted in the DAG")
|
t.Fatalf("Transaction wasn't accepted in the DAG")
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedUTXOsForTxWithLargeInputAndOutputAmount := []*libkaspawallet.UTXO{
|
selectedUTXOsForTxWithLargeInputAndOutputAmount := []*libkaspawallet.UTXO{
|
||||||
@ -499,34 +495,13 @@ func TestMaxSompi(t *testing.T) {
|
|||||||
t.Fatalf("ExtractTransaction: %+v", err)
|
t.Fatalf("ExtractTransaction: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err = tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{txWithLargeInputAndOutputAmount})
|
// We're creating a new longer chain so we can double spend txWithLargeInputAmount
|
||||||
if !errors.Is(err, ruleerrors.ErrBadTxOutValue) {
|
newChainRoot, _, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, nil)
|
||||||
t.Fatalf("AddBlock: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tip := block1Hash
|
|
||||||
for {
|
|
||||||
tip, _, err = tc.AddBlock([]*externalapi.DomainHash{tip}, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("AddBlock: %+v", err)
|
t.Fatalf("AddBlock: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedTip, err := tc.GetVirtualSelectedParent()
|
_, virtualChangeSet, err = tc.AddBlock([]*externalapi.DomainHash{newChainRoot}, nil, []*externalapi.DomainTransaction{txWithLargeInputAndOutputAmount})
|
||||||
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})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("AddBlock: %+v", err)
|
t.Fatalf("AddBlock: %+v", err)
|
||||||
}
|
}
|
||||||
@ -539,14 +514,5 @@ func TestMaxSompi(t *testing.T) {
|
|||||||
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO2) {
|
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO2) {
|
||||||
t.Fatalf("txWithLargeInputAndOutputAmount weren't accepted in the DAG")
|
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")
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -217,8 +217,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
|
|||||||
pastMedianTimeManager,
|
pastMedianTimeManager,
|
||||||
ghostdagDataStore,
|
ghostdagDataStore,
|
||||||
daaBlocksStore,
|
daaBlocksStore,
|
||||||
txMassCalculator,
|
txMassCalculator)
|
||||||
config.HF1DAAScore)
|
|
||||||
difficultyManager := f.difficultyConstructor(
|
difficultyManager := f.difficultyConstructor(
|
||||||
dbManager,
|
dbManager,
|
||||||
ghostdagManager,
|
ghostdagManager,
|
||||||
@ -266,7 +265,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
|
|||||||
finalityManager,
|
finalityManager,
|
||||||
genesisHash,
|
genesisHash,
|
||||||
config.MergeDepth,
|
config.MergeDepth,
|
||||||
config.HF1DAAScore,
|
|
||||||
ghostdagDataStore,
|
ghostdagDataStore,
|
||||||
mergeDepthRootStore,
|
mergeDepthRootStore,
|
||||||
daaBlocksStore,
|
daaBlocksStore,
|
||||||
@ -344,7 +342,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
|
|||||||
config.MaxBlockParents,
|
config.MaxBlockParents,
|
||||||
config.TimestampDeviationTolerance,
|
config.TimestampDeviationTolerance,
|
||||||
config.TargetTimePerBlock,
|
config.TargetTimePerBlock,
|
||||||
config.HF1DAAScore,
|
|
||||||
config.MaxBlockLevel,
|
config.MaxBlockLevel,
|
||||||
|
|
||||||
dbManager,
|
dbManager,
|
||||||
@ -393,7 +390,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
|
|||||||
blockBuilder := blockbuilder.New(
|
blockBuilder := blockbuilder.New(
|
||||||
dbManager,
|
dbManager,
|
||||||
genesisHash,
|
genesisHash,
|
||||||
config.HF1DAAScore,
|
|
||||||
|
|
||||||
difficultyManager,
|
difficultyManager,
|
||||||
pastMedianTimeManager,
|
pastMedianTimeManager,
|
||||||
|
@ -185,7 +185,6 @@ func TestBoundedMergeDepth(t *testing.T) {
|
|||||||
consensusConfig.K = 5
|
consensusConfig.K = 5
|
||||||
consensusConfig.MergeDepth = 7
|
consensusConfig.MergeDepth = 7
|
||||||
consensusConfig.FinalityDuration = 20 * consensusConfig.TargetTimePerBlock
|
consensusConfig.FinalityDuration = 20 * consensusConfig.TargetTimePerBlock
|
||||||
consensusConfig.HF1DAAScore = consensusConfig.GenesisBlock.Header.DAAScore() + 200
|
|
||||||
|
|
||||||
if uint64(consensusConfig.K) >= consensusConfig.FinalityDepth() {
|
if uint64(consensusConfig.K) >= consensusConfig.FinalityDepth() {
|
||||||
t.Fatal("K must be smaller than finality duration for this test to run")
|
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)
|
test(consensusConfig.MergeDepth, 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)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
type blockBuilder struct {
|
type blockBuilder struct {
|
||||||
databaseContext model.DBManager
|
databaseContext model.DBManager
|
||||||
genesisHash *externalapi.DomainHash
|
genesisHash *externalapi.DomainHash
|
||||||
hf1DAAScore uint64
|
|
||||||
|
|
||||||
difficultyManager model.DifficultyManager
|
difficultyManager model.DifficultyManager
|
||||||
pastMedianTimeManager model.PastMedianTimeManager
|
pastMedianTimeManager model.PastMedianTimeManager
|
||||||
@ -43,7 +42,6 @@ type blockBuilder struct {
|
|||||||
func New(
|
func New(
|
||||||
databaseContext model.DBManager,
|
databaseContext model.DBManager,
|
||||||
genesisHash *externalapi.DomainHash,
|
genesisHash *externalapi.DomainHash,
|
||||||
hf1DAAScore uint64,
|
|
||||||
|
|
||||||
difficultyManager model.DifficultyManager,
|
difficultyManager model.DifficultyManager,
|
||||||
pastMedianTimeManager model.PastMedianTimeManager,
|
pastMedianTimeManager model.PastMedianTimeManager,
|
||||||
@ -65,7 +63,6 @@ func New(
|
|||||||
return &blockBuilder{
|
return &blockBuilder{
|
||||||
databaseContext: databaseContext,
|
databaseContext: databaseContext,
|
||||||
genesisHash: genesisHash,
|
genesisHash: genesisHash,
|
||||||
hf1DAAScore: hf1DAAScore,
|
|
||||||
|
|
||||||
difficultyManager: difficultyManager,
|
difficultyManager: difficultyManager,
|
||||||
pastMedianTimeManager: pastMedianTimeManager,
|
pastMedianTimeManager: pastMedianTimeManager,
|
||||||
@ -227,13 +224,8 @@ func (bb *blockBuilder) buildHeader(stagingArea *model.StagingArea, transactions
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
version := constants.BlockVersionBeforeHF1
|
|
||||||
if daaScore >= bb.hf1DAAScore {
|
|
||||||
version = constants.BlockVersionAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockheader.NewImmutableBlockHeader(
|
return blockheader.NewImmutableBlockHeader(
|
||||||
version,
|
constants.BlockVersion,
|
||||||
parents,
|
parents,
|
||||||
hashMerkleRoot,
|
hashMerkleRoot,
|
||||||
acceptedIDMerkleRoot,
|
acceptedIDMerkleRoot,
|
||||||
|
@ -94,14 +94,9 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingAre
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
version := constants.BlockVersionBeforeHF1
|
|
||||||
if daaScore >= bb.hf1DAAScore {
|
|
||||||
version = constants.BlockVersionAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
bb.nonceCounter++
|
bb.nonceCounter++
|
||||||
return blockheader.NewImmutableBlockHeader(
|
return blockheader.NewImmutableBlockHeader(
|
||||||
version,
|
constants.BlockVersion,
|
||||||
parents,
|
parents,
|
||||||
hashMerkleRoot,
|
hashMerkleRoot,
|
||||||
&externalapi.DomainHash{},
|
&externalapi.DomainHash{},
|
||||||
|
@ -220,10 +220,6 @@ func (v *blockValidator) validateGasLimit(block *externalapi.DomainBlock) error
|
|||||||
|
|
||||||
func (v *blockValidator) checkBlockMass(block *externalapi.DomainBlock) error {
|
func (v *blockValidator) checkBlockMass(block *externalapi.DomainBlock) error {
|
||||||
mass := uint64(0)
|
mass := uint64(0)
|
||||||
if block.Header.DAAScore() < v.hf1DAAScore {
|
|
||||||
mass += v.headerEstimatedSerializedSize(block.Header)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, transaction := range block.Transactions {
|
for _, transaction := range block.Transactions {
|
||||||
v.transactionValidator.PopulateMass(transaction)
|
v.transactionValidator.PopulateMass(transaction)
|
||||||
|
|
||||||
|
@ -1307,7 +1307,7 @@ func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consens
|
|||||||
|
|
||||||
return &externalapi.DomainBlock{
|
return &externalapi.DomainBlock{
|
||||||
Header: blockheader.NewImmutableBlockHeader(
|
Header: blockheader.NewImmutableBlockHeader(
|
||||||
constants.BlockVersionBeforeHF1,
|
constants.BlockVersion,
|
||||||
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{consensusConfig.GenesisHash}},
|
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{consensusConfig.GenesisHash}},
|
||||||
merkle.CalculateHashMerkleRoot([]*externalapi.DomainTransaction{tx}),
|
merkle.CalculateHashMerkleRoot([]*externalapi.DomainTransaction{tx}),
|
||||||
&externalapi.DomainHash{},
|
&externalapi.DomainHash{},
|
||||||
|
@ -108,11 +108,7 @@ func TestCheckParentsIncest(t *testing.T) {
|
|||||||
t.Fatalf("AddBlock: %+v", err)
|
t.Fatalf("AddBlock: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
version := constants.BlockVersionBeforeHF1
|
version := constants.BlockVersion
|
||||||
if consensusConfig.HF1DAAScore == 0 {
|
|
||||||
version = constants.BlockVersionAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
directParentsRelationBlock := &externalapi.DomainBlock{
|
directParentsRelationBlock := &externalapi.DomainBlock{
|
||||||
Header: blockheader.NewImmutableBlockHeader(
|
Header: blockheader.NewImmutableBlockHeader(
|
||||||
version,
|
version,
|
||||||
|
@ -56,16 +56,9 @@ func (v *blockValidator) checkParentsLimit(header externalapi.BlockHeader) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *blockValidator) checkBlockVersion(header externalapi.BlockHeader) error {
|
func (v *blockValidator) checkBlockVersion(header externalapi.BlockHeader) error {
|
||||||
if header.DAAScore() >= v.hf1DAAScore {
|
if header.Version() != constants.BlockVersion {
|
||||||
if header.Version() != constants.BlockVersionAfterHF1 {
|
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
ruleerrors.ErrWrongBlockVersion, "After HF1 the block version should be %d", constants.BlockVersionAfterHF1)
|
ruleerrors.ErrWrongBlockVersion, "The block version should be %d", constants.BlockVersion)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if header.Version() != constants.BlockVersionBeforeHF1 {
|
|
||||||
return errors.Wrapf(
|
|
||||||
ruleerrors.ErrWrongBlockVersion, "Beofre HF1 the block version should be %d", constants.BlockVersionBeforeHF1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,7 @@ func CheckBlockVersion(t *testing.T, tc testapi.TestConsensus, consensusConfig *
|
|||||||
t.Fatalf("BuildBlockWithParents: %+v", err)
|
t.Fatalf("BuildBlockWithParents: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedVersion := constants.BlockVersionBeforeHF1
|
expectedVersion := constants.BlockVersion
|
||||||
if consensusConfig.HF1DAAScore == 0 {
|
|
||||||
expectedVersion = constants.BlockVersionAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Header = blockheader.NewImmutableBlockHeader(
|
block.Header = blockheader.NewImmutableBlockHeader(
|
||||||
expectedVersion+1,
|
expectedVersion+1,
|
||||||
block.Header.Parents(),
|
block.Header.Parents(),
|
||||||
|
@ -24,7 +24,6 @@ type blockValidator struct {
|
|||||||
maxBlockParents externalapi.KType
|
maxBlockParents externalapi.KType
|
||||||
timestampDeviationTolerance int
|
timestampDeviationTolerance int
|
||||||
targetTimePerBlock time.Duration
|
targetTimePerBlock time.Duration
|
||||||
hf1DAAScore uint64
|
|
||||||
maxBlockLevel int
|
maxBlockLevel int
|
||||||
|
|
||||||
databaseContext model.DBReader
|
databaseContext model.DBReader
|
||||||
@ -64,7 +63,6 @@ func New(powMax *big.Int,
|
|||||||
maxBlockParents externalapi.KType,
|
maxBlockParents externalapi.KType,
|
||||||
timestampDeviationTolerance int,
|
timestampDeviationTolerance int,
|
||||||
targetTimePerBlock time.Duration,
|
targetTimePerBlock time.Duration,
|
||||||
hf1DAAScore uint64,
|
|
||||||
maxBlockLevel int,
|
maxBlockLevel int,
|
||||||
|
|
||||||
databaseContext model.DBReader,
|
databaseContext model.DBReader,
|
||||||
@ -104,7 +102,6 @@ func New(powMax *big.Int,
|
|||||||
maxBlockMass: maxBlockMass,
|
maxBlockMass: maxBlockMass,
|
||||||
mergeSetSizeLimit: mergeSetSizeLimit,
|
mergeSetSizeLimit: mergeSetSizeLimit,
|
||||||
maxBlockParents: maxBlockParents,
|
maxBlockParents: maxBlockParents,
|
||||||
hf1DAAScore: hf1DAAScore,
|
|
||||||
maxBlockLevel: maxBlockLevel,
|
maxBlockLevel: maxBlockLevel,
|
||||||
|
|
||||||
timestampDeviationTolerance: timestampDeviationTolerance,
|
timestampDeviationTolerance: timestampDeviationTolerance,
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -111,7 +111,7 @@ func TestGHOSTDAG(t *testing.T) {
|
|||||||
blockID := StringToDomainHash(testBlockData.ID)
|
blockID := StringToDomainHash(testBlockData.ID)
|
||||||
dagTopology.parentsMap[*blockID] = StringToDomainHashSlice(testBlockData.Parents)
|
dagTopology.parentsMap[*blockID] = StringToDomainHashSlice(testBlockData.Parents)
|
||||||
blockHeadersStore.dagMap[*blockID] = blockheader.NewImmutableBlockHeader(
|
blockHeadersStore.dagMap[*blockID] = blockheader.NewImmutableBlockHeader(
|
||||||
constants.BlockVersionBeforeHF1,
|
constants.BlockVersion,
|
||||||
[]externalapi.BlockLevelParents{StringToDomainHashSlice(testBlockData.Parents)},
|
[]externalapi.BlockLevelParents{StringToDomainHashSlice(testBlockData.Parents)},
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
@ -16,7 +16,6 @@ type mergeDepthManager struct {
|
|||||||
|
|
||||||
genesisHash *externalapi.DomainHash
|
genesisHash *externalapi.DomainHash
|
||||||
mergeDepth uint64
|
mergeDepth uint64
|
||||||
hf1DAAScore uint64
|
|
||||||
|
|
||||||
ghostdagDataStore model.GHOSTDAGDataStore
|
ghostdagDataStore model.GHOSTDAGDataStore
|
||||||
mergeDepthRootStore model.MergeDepthRootStore
|
mergeDepthRootStore model.MergeDepthRootStore
|
||||||
@ -34,7 +33,6 @@ func New(
|
|||||||
|
|
||||||
genesisHash *externalapi.DomainHash,
|
genesisHash *externalapi.DomainHash,
|
||||||
mergeDepth uint64,
|
mergeDepth uint64,
|
||||||
hf1DAAScore uint64,
|
|
||||||
|
|
||||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||||
mergeDepthRootStore model.MergeDepthRootStore,
|
mergeDepthRootStore model.MergeDepthRootStore,
|
||||||
@ -49,7 +47,6 @@ func New(
|
|||||||
finalityManager: finalityManager,
|
finalityManager: finalityManager,
|
||||||
genesisHash: genesisHash,
|
genesisHash: genesisHash,
|
||||||
mergeDepth: mergeDepth,
|
mergeDepth: mergeDepth,
|
||||||
hf1DAAScore: hf1DAAScore,
|
|
||||||
ghostdagDataStore: ghostdagDataStore,
|
ghostdagDataStore: ghostdagDataStore,
|
||||||
mergeDepthRootStore: mergeDepthRootStore,
|
mergeDepthRootStore: mergeDepthRootStore,
|
||||||
daaBlocksStore: daaBlocksStore,
|
daaBlocksStore: daaBlocksStore,
|
||||||
@ -71,19 +68,24 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(stagingArea *model.StagingA
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// For validation, we must follow the HF1 DAA score in order to determine the correct depth to verify
|
mergeDepthRoot, err := mdm.MergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
|
||||||
mergeDepthRootByHF1, err := mdm.mergeDepthRootByHF1DAAScoreForValidationOnly(stagingArea, blockHash, isBlockWithTrustedData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, red := range ghostdagData.MergeSetReds() {
|
for _, red := range ghostdagData.MergeSetReds() {
|
||||||
doesRedHaveMergeRootInPast, err := mdm.dagTopologyManager.IsAncestorOf(stagingArea, mergeDepthRootByHF1, red)
|
doesRedHaveMergeRootInPast, err := mdm.dagTopologyManager.IsAncestorOf(stagingArea, mergeDepthRoot, red)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -133,34 +135,6 @@ func (mdm *mergeDepthManager) NonBoundedMergeDepthViolatingBlues(
|
|||||||
return nonBoundedMergeDepthViolatingBlues, nil
|
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) {
|
func (mdm *mergeDepthManager) VirtualMergeDepthRoot(stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
|
||||||
log.Tracef("VirtualMergeDepthRoot start")
|
log.Tracef("VirtualMergeDepthRoot start")
|
||||||
defer log.Tracef("VirtualMergeDepthRoot end")
|
defer log.Tracef("VirtualMergeDepthRoot end")
|
||||||
|
@ -37,7 +37,7 @@ func TestPruning(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"dag-for-test-pruning.json": {
|
"dag-for-test-pruning.json": {
|
||||||
dagconfig.MainnetParams.Name: "503",
|
dagconfig.MainnetParams.Name: "503",
|
||||||
dagconfig.TestnetParams.Name: "502",
|
dagconfig.TestnetParams.Name: "503",
|
||||||
dagconfig.DevnetParams.Name: "503",
|
dagconfig.DevnetParams.Name: "503",
|
||||||
dagconfig.SimnetParams.Name: "503",
|
dagconfig.SimnetParams.Name: "503",
|
||||||
},
|
},
|
||||||
|
@ -58,14 +58,6 @@ func (v *transactionValidator) ValidateTransactionInContextIgnoringUTXO(stagingA
|
|||||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "unfinalized transaction %v", tx)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,13 +73,7 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateFee(stagin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
daaScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, stagingArea, povBlockHash)
|
totalSompiIn, err := v.checkTransactionInputAmounts(tx)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isHF1Activated := daaScore >= v.hf1DAAScore
|
|
||||||
totalSompiIn, err := v.checkTransactionInputAmounts(tx, isHF1Activated)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -149,7 +135,7 @@ func (v *transactionValidator) checkTransactionCoinbaseMaturity(stagingArea *mod
|
|||||||
return nil
|
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
|
totalSompiIn = 0
|
||||||
|
|
||||||
var missingOutpoints []*externalapi.DomainOutpoint
|
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
|
// a transaction are in a unit value known as a sompi. One
|
||||||
// kaspa is a quantity of sompi as defined by the
|
// kaspa is a quantity of sompi as defined by the
|
||||||
// SompiPerKaspa constant.
|
// SompiPerKaspa constant.
|
||||||
totalSompiIn, err = v.checkEntryAmounts(utxoEntry, totalSompiIn, isHF1Activated)
|
totalSompiIn, err = v.checkEntryAmounts(utxoEntry, totalSompiIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -179,24 +165,19 @@ func (v *transactionValidator) checkTransactionInputAmounts(tx *externalapi.Doma
|
|||||||
return totalSompiIn, nil
|
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
|
// The total of all outputs must not be more than the max
|
||||||
// allowed per transaction. Also, we could potentially overflow
|
// allowed per transaction. Also, we could potentially overflow
|
||||||
// the accumulator so check for overflow.
|
// the accumulator so check for overflow.
|
||||||
|
|
||||||
maxSompi := constants.MaxSompiBeforeHF1
|
|
||||||
if isHF1Activated {
|
|
||||||
maxSompi = constants.MaxSompiAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
originTxSompi := entry.Amount()
|
originTxSompi := entry.Amount()
|
||||||
totalSompiInAfter = totalSompiInBefore + originTxSompi
|
totalSompiInAfter = totalSompiInBefore + originTxSompi
|
||||||
if totalSompiInAfter < totalSompiInBefore ||
|
if totalSompiInAfter < totalSompiInBefore ||
|
||||||
totalSompiInAfter > maxSompi {
|
totalSompiInAfter > constants.MaxSompi {
|
||||||
return 0, errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
return 0, errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
||||||
"inputs is %d which is higher than max "+
|
"inputs is %d which is higher than max "+
|
||||||
"allowed value of %d", totalSompiInBefore,
|
"allowed value of %d", totalSompiInBefore,
|
||||||
maxSompi)
|
constants.MaxSompi)
|
||||||
}
|
}
|
||||||
return totalSompiInAfter, nil
|
return totalSompiInAfter, nil
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,11 @@ import (
|
|||||||
|
|
||||||
// ValidateTransactionInIsolation validates the parts of the transaction that can be validated context-free
|
// ValidateTransactionInIsolation validates the parts of the transaction that can be validated context-free
|
||||||
func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction, povDAAScore uint64) error {
|
func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction, povDAAScore uint64) error {
|
||||||
isHF1Activated := povDAAScore >= v.hf1DAAScore
|
|
||||||
err := v.checkTransactionInputCount(tx)
|
err := v.checkTransactionInputCount(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = v.checkTransactionAmountRanges(tx, isHF1Activated)
|
err = v.checkTransactionAmountRanges(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -63,18 +62,13 @@ func (v *transactionValidator) checkTransactionInputCount(tx *externalapi.Domain
|
|||||||
return nil
|
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
|
// Ensure the transaction amounts are in range. Each transaction
|
||||||
// output must not be negative or more than the max allowed per
|
// output must not be negative or more than the max allowed per
|
||||||
// transaction. Also, the total of all outputs must abide by the same
|
// transaction. Also, the total of all outputs must abide by the same
|
||||||
// restrictions. All amounts in a transaction are in a unit value known
|
// 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
|
// as a sompi. One kaspa is a quantity of sompi as defined by the
|
||||||
// sompiPerKaspa constant.
|
// sompiPerKaspa constant.
|
||||||
maxSompi := constants.MaxSompiBeforeHF1
|
|
||||||
if isHF1Activated {
|
|
||||||
maxSompi = constants.MaxSompiAfterHF1
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalSompi uint64
|
var totalSompi uint64
|
||||||
for _, txOut := range tx.Outputs {
|
for _, txOut := range tx.Outputs {
|
||||||
sompi := txOut.Value
|
sompi := txOut.Value
|
||||||
@ -82,9 +76,9 @@ func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.Doma
|
|||||||
return errors.Wrap(ruleerrors.ErrTxOutValueZero, "zero value outputs are forbidden")
|
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 "+
|
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.
|
// Binary arithmetic guarantees that any overflow is detected and reported.
|
||||||
@ -94,14 +88,14 @@ func (v *transactionValidator) checkTransactionAmountRanges(tx *externalapi.Doma
|
|||||||
if newTotalSompi < totalSompi {
|
if newTotalSompi < totalSompi {
|
||||||
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
||||||
"outputs exceeds max allowed value of %d",
|
"outputs exceeds max allowed value of %d",
|
||||||
maxSompi)
|
constants.MaxSompi)
|
||||||
}
|
}
|
||||||
totalSompi = newTotalSompi
|
totalSompi = newTotalSompi
|
||||||
if totalSompi > maxSompi {
|
if totalSompi > constants.MaxSompi {
|
||||||
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
return errors.Wrapf(ruleerrors.ErrBadTxOutValue, "total value of all transaction "+
|
||||||
"outputs is %d which is higher than max "+
|
"outputs is %d which is higher than max "+
|
||||||
"allowed value of %d", totalSompi,
|
"allowed value of %d", totalSompi,
|
||||||
maxSompi)
|
constants.MaxSompi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ type txSubnetworkData struct {
|
|||||||
func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
|
func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
|
||||||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
||||||
cfg := *consensusConfig
|
cfg := *consensusConfig
|
||||||
cfg.HF1DAAScore = 20
|
|
||||||
|
|
||||||
factory := consensus.NewFactory()
|
factory := consensus.NewFactory()
|
||||||
tc, teardown, err := factory.NewTestConsensus(&cfg, "TestValidateTransactionInIsolationAndPopulateMass")
|
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},
|
{"good one", 1, 1, 1, subnetworks.SubnetworkIDNative, nil, nil, nil, 0},
|
||||||
{"no inputs", 0, 1, 1, subnetworks.SubnetworkIDNative, nil, nil, ruleerrors.ErrNoTxInputs, 0},
|
{"no inputs", 0, 1, 1, subnetworks.SubnetworkIDNative, nil, nil, ruleerrors.ErrNoTxInputs, 0},
|
||||||
{"no outputs", 1, 0, 1, subnetworks.SubnetworkIDNative, nil, nil, nil, 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,
|
subnetworks.SubnetworkIDNative,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
ruleerrors.ErrBadTxOutValue, 0},
|
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,
|
subnetworks.SubnetworkIDNative,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil, cfg.HF1DAAScore},
|
nil, 0},
|
||||||
{"too much sompi in one output - after hf", 1, 1, constants.MaxSompiAfterHF1 + 1,
|
{"too much sompi in one output - after hf", 1, 1, constants.MaxSompi + 1,
|
||||||
subnetworks.SubnetworkIDNative,
|
subnetworks.SubnetworkIDNative,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
ruleerrors.ErrBadTxOutValue, cfg.HF1DAAScore},
|
ruleerrors.ErrBadTxOutValue, 0},
|
||||||
{"too much sompi in one output", 1, 1, constants.MaxSompiAfterHF1 + 1,
|
{"too much sompi in one output", 1, 1, constants.MaxSompi + 1,
|
||||||
subnetworks.SubnetworkIDNative,
|
subnetworks.SubnetworkIDNative,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
@ -21,7 +21,6 @@ type transactionValidator struct {
|
|||||||
sigCache *txscript.SigCache
|
sigCache *txscript.SigCache
|
||||||
sigCacheECDSA *txscript.SigCacheECDSA
|
sigCacheECDSA *txscript.SigCacheECDSA
|
||||||
txMassCalculator *txmass.Calculator
|
txMassCalculator *txmass.Calculator
|
||||||
hf1DAAScore uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a new TransactionValidator
|
// New instantiates a new TransactionValidator
|
||||||
@ -32,8 +31,7 @@ func New(blockCoinbaseMaturity uint64,
|
|||||||
pastMedianTimeManager model.PastMedianTimeManager,
|
pastMedianTimeManager model.PastMedianTimeManager,
|
||||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||||
daaBlocksStore model.DAABlocksStore,
|
daaBlocksStore model.DAABlocksStore,
|
||||||
txMassCalculator *txmass.Calculator,
|
txMassCalculator *txmass.Calculator) model.TransactionValidator {
|
||||||
hf1DAAScore uint64) model.TransactionValidator {
|
|
||||||
|
|
||||||
return &transactionValidator{
|
return &transactionValidator{
|
||||||
blockCoinbaseMaturity: blockCoinbaseMaturity,
|
blockCoinbaseMaturity: blockCoinbaseMaturity,
|
||||||
@ -46,6 +44,5 @@ func New(blockCoinbaseMaturity uint64,
|
|||||||
sigCache: txscript.NewSigCache(sigCacheSize),
|
sigCache: txscript.NewSigCache(sigCacheSize),
|
||||||
sigCacheECDSA: txscript.NewSigCacheECDSA(sigCacheSize),
|
sigCacheECDSA: txscript.NewSigCacheECDSA(sigCacheSize),
|
||||||
txMassCalculator: txMassCalculator,
|
txMassCalculator: txMassCalculator,
|
||||||
hf1DAAScore: hf1DAAScore,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
|
|
||||||
func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
||||||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
||||||
consensusConfig.HF1DAAScore = consensusConfig.GenesisBlock.Header.DAAScore() + 1000
|
|
||||||
factory := consensus.NewFactory()
|
factory := consensus.NewFactory()
|
||||||
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
|
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
|
||||||
"TestValidateTransactionInContextAndPopulateFee")
|
"TestValidateTransactionInContextAndPopulateFee")
|
||||||
@ -92,7 +91,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
|||||||
Sequence: constants.MaxTxInSequenceNum,
|
Sequence: constants.MaxTxInSequenceNum,
|
||||||
SigOpCount: 1,
|
SigOpCount: 1,
|
||||||
UTXOEntry: utxo.NewUTXOEntry(
|
UTXOEntry: utxo.NewUTXOEntry(
|
||||||
constants.MaxSompiBeforeHF1+1,
|
21e14+1,
|
||||||
scriptPublicKey,
|
scriptPublicKey,
|
||||||
false,
|
false,
|
||||||
0),
|
0),
|
||||||
@ -104,7 +103,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
|||||||
Sequence: constants.MaxTxInSequenceNum,
|
Sequence: constants.MaxTxInSequenceNum,
|
||||||
SigOpCount: 1,
|
SigOpCount: 1,
|
||||||
UTXOEntry: utxo.NewUTXOEntry(
|
UTXOEntry: utxo.NewUTXOEntry(
|
||||||
constants.MaxSompiAfterHF1+1,
|
constants.MaxSompi+1,
|
||||||
scriptPublicKey,
|
scriptPublicKey,
|
||||||
false,
|
false,
|
||||||
0),
|
0),
|
||||||
@ -163,7 +162,7 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
|||||||
Gas: 0,
|
Gas: 0,
|
||||||
LockTime: 0}
|
LockTime: 0}
|
||||||
|
|
||||||
txWithLargeAmountAfterHF := externalapi.DomainTransaction{
|
txWithInvalidAmount := externalapi.DomainTransaction{
|
||||||
Version: constants.MaxTransactionVersion,
|
Version: constants.MaxTransactionVersion,
|
||||||
Inputs: []*externalapi.DomainTransactionInput{&txInputWithLargeAmountAfterHF},
|
Inputs: []*externalapi.DomainTransactionInput{&txInputWithLargeAmountAfterHF},
|
||||||
Outputs: []*externalapi.DomainTransactionOutput{&txOutput},
|
Outputs: []*externalapi.DomainTransactionOutput{&txOutput},
|
||||||
@ -207,9 +206,6 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
|||||||
povBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x01})
|
povBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x01})
|
||||||
tc.DAABlocksStore().StageDAAScore(stagingArea, povBlockHash, consensusConfig.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockDAAScore())
|
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
|
// Just use some stub ghostdag data
|
||||||
tc.GHOSTDAGDataStore().Stage(stagingArea, povBlockHash, externalapi.NewBlockGHOSTDAGData(
|
tc.GHOSTDAGDataStore().Stage(stagingArea, povBlockHash, externalapi.NewBlockGHOSTDAGData(
|
||||||
0,
|
0,
|
||||||
@ -242,24 +238,17 @@ func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
|
|||||||
isValid: false,
|
isValid: false,
|
||||||
expectedError: ruleerrors.ErrImmatureSpend,
|
expectedError: ruleerrors.ErrImmatureSpend,
|
||||||
},
|
},
|
||||||
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompiBeforeHF1)
|
{ // The total inputs amount is bigger than the allowed maximum before the HF (21e14)
|
||||||
name: "checkTransactionInputAmounts - invalid - before HF",
|
name: "checkTransactionInputAmounts - valid",
|
||||||
tx: &txWithLargeAmountBeforeHF,
|
tx: &txWithLargeAmountBeforeHF,
|
||||||
povBlockHash: povBlockHash,
|
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,
|
isValid: true,
|
||||||
expectedError: nil,
|
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",
|
name: "checkTransactionInputAmounts - invalid - after HF",
|
||||||
tx: &txWithLargeAmountAfterHF,
|
tx: &txWithInvalidAmount,
|
||||||
povBlockHash: povAfterHFBlockHash,
|
povBlockHash: povBlockHash,
|
||||||
isValid: false,
|
isValid: false,
|
||||||
expectedError: ruleerrors.ErrBadTxOutValue,
|
expectedError: ruleerrors.ErrBadTxOutValue,
|
||||||
},
|
},
|
||||||
|
@ -3,11 +3,8 @@ package constants
|
|||||||
import "math"
|
import "math"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// BlockVersionBeforeHF1 represents the current version of blocks mined before HF1
|
// BlockVersion represents the current block version
|
||||||
BlockVersionBeforeHF1 uint16 = 0
|
BlockVersion uint16 = 1
|
||||||
|
|
||||||
// BlockVersionAfterHF1 represents the current version of blocks mined after HF1
|
|
||||||
BlockVersionAfterHF1 uint16 = 1
|
|
||||||
|
|
||||||
// MaxTransactionVersion is the current latest supported transaction version.
|
// MaxTransactionVersion is the current latest supported transaction version.
|
||||||
MaxTransactionVersion uint16 = 0
|
MaxTransactionVersion uint16 = 0
|
||||||
@ -18,11 +15,8 @@ const (
|
|||||||
// SompiPerKaspa is the number of sompi in one kaspa (1 KAS).
|
// SompiPerKaspa is the number of sompi in one kaspa (1 KAS).
|
||||||
SompiPerKaspa = 100_000_000
|
SompiPerKaspa = 100_000_000
|
||||||
|
|
||||||
// MaxSompiBeforeHF1 is the maximum transaction amount allowed in sompi before the HF1 hard fork is activated.
|
// MaxSompi is the maximum transaction amount allowed in sompi.
|
||||||
MaxSompiBeforeHF1 = uint64(21_000_000 * SompiPerKaspa)
|
MaxSompi = uint64(29_000_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)
|
|
||||||
|
|
||||||
// MaxTxInSequenceNum is the maximum sequence number the sequence field
|
// MaxTxInSequenceNum is the maximum sequence number the sequence field
|
||||||
// of a transaction input can be.
|
// of a transaction input can be.
|
||||||
|
@ -188,7 +188,6 @@ type Params struct {
|
|||||||
MaxBlockLevel int
|
MaxBlockLevel int
|
||||||
|
|
||||||
MergeDepth uint64
|
MergeDepth uint64
|
||||||
HF1DAAScore uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeRPCServerAddress returns addr with the current network default
|
// 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.
|
// 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,
|
||||||
HF1DAAScore: 14687583,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestnetParams defines the network parameters for the test Kaspa network.
|
// TestnetParams defines the network parameters for the test Kaspa network.
|
||||||
@ -351,7 +349,6 @@ var TestnetParams = Params{
|
|||||||
|
|
||||||
MaxBlockLevel: 250,
|
MaxBlockLevel: 250,
|
||||||
MergeDepth: defaultMergeDepth,
|
MergeDepth: defaultMergeDepth,
|
||||||
HF1DAAScore: 172800,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimnetParams defines the network parameters for the simulation test Kaspa
|
// SimnetParams defines the network parameters for the simulation test Kaspa
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||||
"github.com/kaspanet/kaspad/domain/miningmanager/blocktemplatebuilder"
|
"github.com/kaspanet/kaspad/domain/miningmanager/blocktemplatebuilder"
|
||||||
mempoolpkg "github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
mempoolpkg "github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -22,15 +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)
|
||||||
// In the current pruning window (according to 06/04/2022) the header with the most mass weighted 5294 grams.
|
blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, params.MaxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength)
|
||||||
// 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)
|
|
||||||
|
|
||||||
return &miningManager{
|
return &miningManager{
|
||||||
consensusReference: consensusReference,
|
consensusReference: consensusReference,
|
||||||
|
@ -198,9 +198,8 @@ func (mp *mempool) minimumRequiredTransactionRelayFee(mass uint64) uint64 {
|
|||||||
|
|
||||||
// Set the minimum fee to the maximum possible value if the calculated
|
// Set the minimum fee to the maximum possible value if the calculated
|
||||||
// fee is not in the valid range for monetary amounts.
|
// fee is not in the valid range for monetary amounts.
|
||||||
// TODO: Replace it with constants.MaxSompiAfterHF1 once HF is activated
|
if minimumFee > constants.MaxSompi {
|
||||||
if minimumFee > constants.MaxSompiBeforeHF1 {
|
minimumFee = constants.MaxSompi
|
||||||
minimumFee = constants.MaxSompiBeforeHF1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return minimumFee
|
return minimumFee
|
||||||
|
@ -50,12 +50,6 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
|
|||||||
defaultMinimumRelayTransactionFee,
|
defaultMinimumRelayTransactionFee,
|
||||||
100000,
|
100000,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"max standard tx size with max sompi relay fee",
|
|
||||||
MaximumStandardTransactionMass,
|
|
||||||
util.Amount(constants.MaxSompiBeforeHF1),
|
|
||||||
constants.MaxSompiBeforeHF1,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"1500 bytes with 5000 relay fee",
|
"1500 bytes with 5000 relay fee",
|
||||||
1500,
|
1500,
|
||||||
@ -156,8 +150,8 @@ func TestIsTransactionOutputDust(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Maximum allowed value is never dust.
|
// Maximum allowed value is never dust.
|
||||||
"max sompi amount is never dust",
|
"max sompi amount is never dust",
|
||||||
externalapi.DomainTransactionOutput{Value: constants.MaxSompiBeforeHF1, ScriptPublicKey: scriptPublicKey},
|
externalapi.DomainTransactionOutput{Value: constants.MaxSompi, ScriptPublicKey: scriptPublicKey},
|
||||||
util.Amount(constants.MaxSompiBeforeHF1),
|
util.Amount(1000),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -58,12 +58,12 @@ func (id *ID) SerializeToBytes() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FromBytes returns an ID deserialized from the given byte slice.
|
// 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)
|
r := bytes.NewReader(serializedID)
|
||||||
newID := new(ID)
|
newID := new(ID)
|
||||||
err := newID.Deserialize(r)
|
err := newID.Deserialize(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return newID
|
return newID, nil
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,22 @@ func (x *VersionMessage) toAppMessage() (appmessage.Message, error) {
|
|||||||
return nil, err
|
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{
|
return &appmessage.MsgVersion{
|
||||||
ProtocolVersion: x.ProtocolVersion,
|
ProtocolVersion: x.ProtocolVersion,
|
||||||
Network: x.Network,
|
Network: x.Network,
|
||||||
Services: appmessage.ServiceFlag(x.Services),
|
Services: appmessage.ServiceFlag(x.Services),
|
||||||
Timestamp: mstime.UnixMilliseconds(x.Timestamp),
|
Timestamp: mstime.UnixMilliseconds(x.Timestamp),
|
||||||
Address: address,
|
Address: address,
|
||||||
ID: id.FromBytes(x.Id),
|
ID: appMsgID,
|
||||||
UserAgent: x.UserAgent,
|
UserAgent: x.UserAgent,
|
||||||
DisableRelayTx: x.DisableRelayTx,
|
DisableRelayTx: x.DisableRelayTx,
|
||||||
SubnetworkID: subnetworkID,
|
SubnetworkID: subnetworkID,
|
||||||
|
@ -28,15 +28,9 @@ func TestAmountCreation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "max producible",
|
name: "max producible",
|
||||||
amount: 21e6,
|
amount: 29e9,
|
||||||
valid: true,
|
valid: true,
|
||||||
expected: Amount(constants.MaxSompiBeforeHF1),
|
expected: Amount(constants.MaxSompi),
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "exceeds max producible",
|
|
||||||
amount: 21e6 + 1e-8,
|
|
||||||
valid: true,
|
|
||||||
expected: Amount(constants.MaxSompiBeforeHF1) + 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "one hundred",
|
name: "one hundred",
|
||||||
@ -109,10 +103,10 @@ func TestAmountUnitConversions(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "MKAS",
|
name: "MKAS",
|
||||||
amount: Amount(constants.MaxSompiBeforeHF1),
|
amount: Amount(constants.MaxSompi),
|
||||||
unit: AmountMegaKAS,
|
unit: AmountMegaKAS,
|
||||||
converted: 21,
|
converted: 29000,
|
||||||
s: "21 MKAS",
|
s: "29000 MKAS",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "kKAS",
|
name: "kKAS",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user