diff --git a/blockdag/dag.go b/blockdag/dag.go index 4054ede9e..df4fc6bd5 100644 --- a/blockdag/dag.go +++ b/blockdag/dag.go @@ -27,6 +27,8 @@ const ( // maxOrphanBlocks is the maximum number of orphan blocks that can be // queued. maxOrphanBlocks = 100 + + isDAGCurrentMaxDiff = 12 * time.Hour ) // orphanBlock represents a block that we don't yet have the parent for. It @@ -1276,8 +1278,8 @@ func (dag *BlockDAG) isCurrent() bool { } else { dagTimestamp = selectedTip.timestamp } - minus24Hours := dag.AdjustedTime().Add(-24 * time.Hour).Unix() - return dagTimestamp >= minus24Hours + dagTime := time.Unix(dagTimestamp, 0) + return dag.AdjustedTime().Sub(dagTime) <= isDAGCurrentMaxDiff } // AdjustedTime returns the adjusted time according to @@ -1715,11 +1717,11 @@ func (dag *BlockDAG) antiPastBetween(lowHash, highHash *daghash.Hash, maxEntries // This function is safe for concurrent access. func (dag *BlockDAG) AntiPastHashesBetween(lowHash, highHash *daghash.Hash, maxHashes uint64) ([]*daghash.Hash, error) { dag.dagLock.RLock() + defer dag.dagLock.RUnlock() hashes, err := dag.antiPastHashesBetween(lowHash, highHash, maxHashes) if err != nil { return nil, err } - dag.dagLock.RUnlock() return hashes, nil } @@ -1793,11 +1795,11 @@ func (dag *BlockDAG) RUnlock() { // This function is safe for concurrent access. func (dag *BlockDAG) AntiPastHeadersBetween(lowHash, highHash *daghash.Hash, maxHeaders uint64) ([]*wire.BlockHeader, error) { dag.dagLock.RLock() + defer dag.dagLock.RUnlock() headers, err := dag.antiPastHeadersBetween(lowHash, highHash, maxHeaders) if err != nil { return nil, err } - dag.dagLock.RUnlock() return headers, nil } diff --git a/blockdag/dag_test.go b/blockdag/dag_test.go index 5c14ef692..b5c1c14f3 100644 --- a/blockdag/dag_test.go +++ b/blockdag/dag_test.go @@ -926,7 +926,7 @@ func testFinalizeNodesBelowFinalityPoint(t *testing.T, deleteDiffData bool) { nodes := make([]*blockNode, 0, finalityInterval) currentNode := dag.genesis nodes = append(nodes, currentNode) - for i := 0; i <= finalityInterval*2; i++ { + for i := uint64(0); i <= finalityInterval*2; i++ { currentNode = addNode(currentNode) nodes = append(nodes, currentNode) } @@ -1073,3 +1073,18 @@ func TestDAGIndexFailedStatus(t *testing.T) { t.Fatalf("invalidBlockGrandChildNode status to have %b flags raised (got %b)", statusInvalidAncestor, invalidBlockGrandChildNode.status) } } + +func TestIsDAGCurrentMaxDiff(t *testing.T) { + netParams := []*dagconfig.Params{ + &dagconfig.MainnetParams, + &dagconfig.TestnetParams, + &dagconfig.DevnetParams, + &dagconfig.RegressionNetParams, + &dagconfig.SimnetParams, + } + for _, params := range netParams { + if params.TargetTimePerBlock*time.Duration(params.FinalityInterval) < isDAGCurrentMaxDiff { + t.Errorf("in %s, a DAG can be considered current even if it's below the finality point", params.Name) + } + } +} diff --git a/blockdag/external_dag_test.go b/blockdag/external_dag_test.go index 4bc3c6784..7c4864ad9 100644 --- a/blockdag/external_dag_test.go +++ b/blockdag/external_dag_test.go @@ -73,7 +73,7 @@ func TestFinality(t *testing.T) { currentNode := genesis // First we build a chain of params.FinalityInterval blocks for future use - for i := 0; i < params.FinalityInterval; i++ { + for i := uint64(0); i < params.FinalityInterval; i++ { currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()}) if err != nil { t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err) @@ -85,7 +85,7 @@ func TestFinality(t *testing.T) { // Now we build a new chain of 2 * params.FinalityInterval blocks, pointed to genesis, and // we expect the block with height 1 * params.FinalityInterval to be the last finality point currentNode = genesis - for i := 0; i < params.FinalityInterval; i++ { + for i := uint64(0); i < params.FinalityInterval; i++ { currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()}) if err != nil { t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err) @@ -94,7 +94,7 @@ func TestFinality(t *testing.T) { expectedFinalityPoint := currentNode - for i := 0; i < params.FinalityInterval; i++ { + for i := uint64(0); i < params.FinalityInterval; i++ { currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()}) if err != nil { t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err) @@ -166,9 +166,17 @@ func TestFinality(t *testing.T) { // a getblocks message it should always be able to send // all the necessary invs. func TestFinalityInterval(t *testing.T) { - params := dagconfig.SimnetParams - if params.FinalityInterval > wire.MaxInvPerMsg { - t.Errorf("dagconfig.SimnetParams.FinalityInterval should be lower or equal to wire.MaxInvPerMsg") + netParams := []*dagconfig.Params{ + &dagconfig.MainnetParams, + &dagconfig.TestnetParams, + &dagconfig.DevnetParams, + &dagconfig.RegressionNetParams, + &dagconfig.SimnetParams, + } + for _, params := range netParams { + if params.FinalityInterval > wire.MaxInvPerMsg { + t.Errorf("FinalityInterval in %s should be lower or equal to wire.MaxInvPerMsg", params.Name) + } } } diff --git a/blockdag/thresholdstate.go b/blockdag/thresholdstate.go index a08a1c9af..0ea99c7af 100644 --- a/blockdag/thresholdstate.go +++ b/blockdag/thresholdstate.go @@ -267,8 +267,8 @@ func (dag *BlockDAG) thresholdState(prevNode *blockNode, checker thresholdCondit // This function is safe for concurrent access. func (dag *BlockDAG) ThresholdState(deploymentID uint32) (ThresholdState, error) { dag.dagLock.Lock() + defer dag.dagLock.Unlock() state, err := dag.deploymentState(dag.selectedTip(), deploymentID) - dag.dagLock.Unlock() return state, err } @@ -279,8 +279,8 @@ func (dag *BlockDAG) ThresholdState(deploymentID uint32) (ThresholdState, error) // This function is safe for concurrent access. func (dag *BlockDAG) IsDeploymentActive(deploymentID uint32) (bool, error) { dag.dagLock.Lock() + defer dag.dagLock.Unlock() state, err := dag.deploymentState(dag.selectedTip(), deploymentID) - dag.dagLock.Unlock() if err != nil { return false, err } diff --git a/dagconfig/params.go b/dagconfig/params.go index 561940461..c1700e726 100644 --- a/dagconfig/params.go +++ b/dagconfig/params.go @@ -47,9 +47,14 @@ var ( devnetPowMax = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 239), bigOne) ) -const ghostdagK = 10 -const difficultyAdjustmentWindowSize = 2640 -const timestampDeviationTolerance = 132 +const ( + ghostdagK = 10 + difficultyAdjustmentWindowSize = 2640 + timestampDeviationTolerance = 132 + finalityDuration = 24 * time.Hour + targetTimePerBlock = 1 * time.Second + finalityInterval = uint64(finalityDuration / targetTimePerBlock) +) // ConsensusDeployment defines details related to a specific consensus rule // change that is voted in. This is part of BIP0009. @@ -132,7 +137,7 @@ type Params struct { TargetTimePerBlock time.Duration // FinalityInterval is the interval that determines the finality window of the DAG. - FinalityInterval int + FinalityInterval uint64 // TimestampDeviationTolerance is the maximum offset a block timestamp // is allowed to be in the future before it gets delayed @@ -195,8 +200,8 @@ var MainnetParams = Params{ PowMax: mainPowMax, BlockCoinbaseMaturity: 100, SubsidyReductionInterval: 210000, - TargetTimePerBlock: time.Second * 1, // 1 second - FinalityInterval: 1000, + TargetTimePerBlock: targetTimePerBlock, + FinalityInterval: finalityInterval, DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize, TimestampDeviationTolerance: timestampDeviationTolerance, @@ -252,8 +257,8 @@ var RegressionNetParams = Params{ PowMax: regressionPowMax, BlockCoinbaseMaturity: 100, SubsidyReductionInterval: 150, - TargetTimePerBlock: time.Second * 1, // 1 second - FinalityInterval: 1000, + TargetTimePerBlock: targetTimePerBlock, + FinalityInterval: finalityInterval, DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize, TimestampDeviationTolerance: timestampDeviationTolerance, @@ -307,8 +312,8 @@ var TestnetParams = Params{ PowMax: testnetPowMax, BlockCoinbaseMaturity: 100, SubsidyReductionInterval: 210000, - TargetTimePerBlock: time.Second * 1, // 1 second - FinalityInterval: 1000, + TargetTimePerBlock: targetTimePerBlock, + FinalityInterval: finalityInterval, DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize, TimestampDeviationTolerance: timestampDeviationTolerance, @@ -368,8 +373,8 @@ var SimnetParams = Params{ PowMax: simnetPowMax, BlockCoinbaseMaturity: 100, SubsidyReductionInterval: 210000, - TargetTimePerBlock: time.Second * 1, // 1 second - FinalityInterval: 1000, + TargetTimePerBlock: targetTimePerBlock, + FinalityInterval: finalityInterval, DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize, TimestampDeviationTolerance: timestampDeviationTolerance, @@ -421,8 +426,8 @@ var DevnetParams = Params{ PowMax: devnetPowMax, BlockCoinbaseMaturity: 100, SubsidyReductionInterval: 210000, - TargetTimePerBlock: time.Second * 1, // 1 second - FinalityInterval: 1000, + TargetTimePerBlock: targetTimePerBlock, + FinalityInterval: finalityInterval, DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize, TimestampDeviationTolerance: timestampDeviationTolerance, diff --git a/netsync/manager.go b/netsync/manager.go index 202a6f268..ba3de9a73 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -6,6 +6,11 @@ package netsync import ( "fmt" + "net" + "sync" + "sync/atomic" + "time" + "github.com/kaspanet/kaspad/blockdag" "github.com/kaspanet/kaspad/dagconfig" "github.com/kaspanet/kaspad/database" @@ -15,10 +20,6 @@ import ( "github.com/kaspanet/kaspad/util/daghash" "github.com/kaspanet/kaspad/wire" "github.com/pkg/errors" - "net" - "sync" - "sync/atomic" - "time" ) const ( diff --git a/wire/invvect.go b/wire/invvect.go index 4fd5b885a..75c914354 100644 --- a/wire/invvect.go +++ b/wire/invvect.go @@ -14,7 +14,7 @@ import ( const ( // MaxInvPerMsg is the maximum number of inventory vectors that can be in a // single kaspa inv message. - MaxInvPerMsg = 1 << 16 + MaxInvPerMsg = 1 << 17 // MaxSyncBlockInvPerGetDataMsg is the maximum number of sync block inventory // vectors that can be in a single getData message. diff --git a/wire/msggetdata_test.go b/wire/msggetdata_test.go index 8dda9e067..0d58b98c6 100644 --- a/wire/msggetdata_test.go +++ b/wire/msggetdata_test.go @@ -29,7 +29,7 @@ func TestGetData(t *testing.T) { // Ensure max payload is expected value for latest protocol version. // Num inventory vectors (varInt) + max allowed inventory vectors. - wantPayload := uint32(2359305) + wantPayload := uint32(4718601) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ diff --git a/wire/msginv_test.go b/wire/msginv_test.go index c312d265a..343b22b95 100644 --- a/wire/msginv_test.go +++ b/wire/msginv_test.go @@ -29,7 +29,7 @@ func TestInv(t *testing.T) { // Ensure max payload is expected value for latest protocol version. // Num inventory vectors (varInt) + max allowed inventory vectors. - wantPayload := uint32(2359305) + wantPayload := uint32(4718601) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ diff --git a/wire/msgnotfound_test.go b/wire/msgnotfound_test.go index 8df829e9c..baf1a19bd 100644 --- a/wire/msgnotfound_test.go +++ b/wire/msgnotfound_test.go @@ -29,7 +29,7 @@ func TestNotFound(t *testing.T) { // Ensure max payload is expected value for latest protocol version. // Num inventory vectors (varInt) + max allowed inventory vectors. - wantPayload := uint32(2359305) + wantPayload := uint32(4718601) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+