Hard fork - new genesis with the utxo set of the last block (#1856)

* UTXO dump of block 0fca37ca667c2d550a6c4416dad9717e50927128c424fa4edbebc436ab13aeef

* Activate HF immediately and change reward to 1000

* Change protocol version and datadir location

* Delete comments

* Fix zero hash to muhash zero hash in genesis utxo dump check

* Don't omit genesis as direct parent

* Fix tests

* Change subsidy to 500

* Dont assume genesis multiset is empty

* Fix BlockReward test

* Fix TestValidateAndInsertImportedPruningPoint test

* Fix pruning point genesis utxo set

* Fix tests related to mainnet utxo set

* Dont change the difficulty before you have a full window

* Fix TestBlockWindow tests

* Remove global utxo set variable, and persist mainnetnet utxo deserialization between runs

* Fix last tests

* Make peer banning opt-in

* small fix for a test

* Fix go lint

* Fix Ori's review comments

* Change DAA score of genesis to checkpoint DAA score and fix all tests

* Fix the BlockLevel bits counting

* Fix some tests and make them run a little faster

* Change datadir name back to kaspa-mainnet and change db path from /data to /datadir

* Last changes for the release and change the version to 0.11.5

Co-authored-by: Ori Newman <orinewman1@gmail.com>
Co-authored-by: Ori Newman <>
Co-authored-by: msutton <mikisiton2@gmail.com>
This commit is contained in:
Elichai Turkel 2021-11-25 20:18:43 +02:00 committed by GitHub
parent 2a1b38ce7a
commit dbf18d8052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 497 additions and 453 deletions

View File

@ -20,7 +20,10 @@ import (
"github.com/kaspanet/kaspad/version"
)
const leveldbCacheSizeMiB = 256
const (
leveldbCacheSizeMiB = 256
defaultDataDirname = "datadir"
)
var desiredLimits = &limits.DesiredLimits{
FileLimitWant: 2048,
@ -159,7 +162,7 @@ func (app *kaspadApp) main(startedChan chan<- struct{}) error {
// dbPath returns the path to the block database given a database type.
func databasePath(cfg *config.Config) string {
return filepath.Join(cfg.AppDir, "data")
return filepath.Join(cfg.AppDir, defaultDataDirname)
}
func removeDatabase(cfg *config.Config) error {

View File

@ -12,7 +12,7 @@ import (
const (
// ProtocolVersion is the latest protocol version this package supports.
ProtocolVersion uint32 = 1
ProtocolVersion uint32 = 2
// DefaultServices describes the default services that are supported by
// the server.

View File

@ -102,7 +102,7 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection, outgoingRoute *routerpkg.Route) {
if protocolErr := (protocolerrors.ProtocolError{}); errors.As(err, &protocolErr) {
if !m.context.Config().DisableBanning && protocolErr.ShouldBan {
if m.context.Config().EnableBanning && protocolErr.ShouldBan {
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
err := m.context.ConnectionManager().Ban(netConnection)

View File

@ -159,7 +159,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
dagTraversalManager := dagTraversalManagers[0]
// Processes
parentsManager := parentssanager.New(config.GenesisHash, config.HardForkOmitGenesisFromParentsDAAScore)
parentsManager := parentssanager.New(config.GenesisHash)
blockParentBuilder := blockparentbuilder.New(
dbManager,
blockHeaderStore,
@ -168,7 +168,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
reachabilityDataStore,
pruningStore,
config.HardForkOmitGenesisFromParentsDAAScore,
config.GenesisHash,
)
pastMedianTimeManager := f.pastMedianTimeConsructor(

View File

@ -16,8 +16,8 @@ import (
func TestFinality(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
// Set finalityInterval to 50 blocks, so that test runs quickly
consensusConfig.FinalityDuration = 50 * consensusConfig.TargetTimePerBlock
// Set finalityInterval to 20 blocks, so that test runs quickly
consensusConfig.FinalityDuration = 20 * consensusConfig.TargetTimePerBlock
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestFinality")
@ -180,7 +180,8 @@ func TestFinality(t *testing.T) {
func TestBoundedMergeDepth(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
// Set finalityInterval to 50 blocks, so that test runs quickly
consensusConfig.FinalityDuration = 50 * consensusConfig.TargetTimePerBlock
consensusConfig.K = 5
consensusConfig.FinalityDuration = 7 * consensusConfig.TargetTimePerBlock
finalityInterval := int(consensusConfig.FinalityDepth())
if int(consensusConfig.K) >= finalityInterval {

View File

@ -16,7 +16,6 @@ type blockParentBuilder struct {
reachabilityDataStore model.ReachabilityDataStore
pruningStore model.PruningStore
hardForkOmitGenesisFromParentsDAAScore uint64
genesisHash *externalapi.DomainHash
}
@ -30,7 +29,6 @@ func New(
reachabilityDataStore model.ReachabilityDataStore,
pruningStore model.PruningStore,
hardForkOmitGenesisFromParentsDAAScore uint64,
genesisHash *externalapi.DomainHash,
) model.BlockParentBuilder {
return &blockParentBuilder{
@ -41,7 +39,6 @@ func New(
reachabilityDataStore: reachabilityDataStore,
pruningStore: pruningStore,
hardForkOmitGenesisFromParentsDAAScore: hardForkOmitGenesisFromParentsDAAScore,
genesisHash: genesisHash,
}
}
@ -217,9 +214,11 @@ func (bpb *blockParentBuilder) BuildParents(stagingArea *model.StagingArea,
parents := make([]externalapi.BlockLevelParents, 0, len(candidatesByLevelToReferenceBlocksMap))
for blockLevel := 0; blockLevel < len(candidatesByLevelToReferenceBlocksMap); blockLevel++ {
if _, ok := candidatesByLevelToReferenceBlocksMap[blockLevel][*bpb.genesisHash]; daaScore >= bpb.hardForkOmitGenesisFromParentsDAAScore && ok && len(candidatesByLevelToReferenceBlocksMap[blockLevel]) == 1 {
if blockLevel > 0 {
if _, ok := candidatesByLevelToReferenceBlocksMap[blockLevel][*bpb.genesisHash]; ok && len(candidatesByLevelToReferenceBlocksMap[blockLevel]) == 1 {
break
}
}
levelBlocks := make(externalapi.BlockLevelParents, 0, len(candidatesByLevelToReferenceBlocksMap[blockLevel]))
for block := range candidatesByLevelToReferenceBlocksMap[blockLevel] {

View File

@ -1,12 +1,20 @@
package blockprocessor
import (
"bytes"
"compress/gzip"
"github.com/kaspanet/go-muhash"
// we need to embed the utxoset of mainnet genesis here
_ "embed"
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/multiset"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/util/staging"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/kaspanet/kaspad/util/staging"
"io"
"sync"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
@ -16,6 +24,9 @@ import (
"github.com/pkg/errors"
)
//go:embed resources/utxos.gz
var utxoDumpFile []byte
func (bp *blockProcessor) setBlockStatusAfterBlockValidation(
stagingArea *model.StagingArea, block *externalapi.DomainBlock, isPruningPoint bool) error {
@ -128,6 +139,11 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea,
}
}
err = bp.ifGenesisSetUtxoSet(block)
if err != nil {
return nil, err
}
var selectedParentChainChanges *externalapi.SelectedChainPath
var virtualUTXODiff externalapi.UTXODiff
var reversalData *model.UTXODiffReversalData
@ -215,6 +231,93 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea,
}, nil
}
var mainnetGenesisUTXOSet externalapi.UTXODiff
var mainnetGenesisMultiSet model.Multiset
var mainnetGenesisOnce sync.Once
var mainnetGenesisErr error
func deserializeMainnetUTXOSet() (externalapi.UTXODiff, model.Multiset, error) {
mainnetGenesisOnce.Do(func() {
toAdd := make(map[externalapi.DomainOutpoint]externalapi.UTXOEntry)
mainnetGenesisMultiSet = multiset.New()
file, err := gzip.NewReader(bytes.NewReader(utxoDumpFile))
if err != nil {
mainnetGenesisErr = err
return
}
for i := 0; ; i++ {
size := make([]byte, 1)
_, err = io.ReadFull(file, size)
if errors.Is(err, io.EOF) {
break
}
if err != nil {
mainnetGenesisErr = err
return
}
serializedUTXO := make([]byte, size[0])
_, err = io.ReadFull(file, serializedUTXO)
if err != nil {
mainnetGenesisErr = err
return
}
mainnetGenesisMultiSet.Add(serializedUTXO)
entry, outpoint, err := utxo.DeserializeUTXO(serializedUTXO)
if err != nil {
mainnetGenesisErr = err
return
}
toAdd[*outpoint] = entry
}
mainnetGenesisUTXOSet, mainnetGenesisErr = utxo.NewUTXODiffFromCollections(utxo.NewUTXOCollection(toAdd), utxo.NewUTXOCollection(make(map[externalapi.DomainOutpoint]externalapi.UTXOEntry)))
})
return mainnetGenesisUTXOSet, mainnetGenesisMultiSet, mainnetGenesisErr
}
func (bp *blockProcessor) ifGenesisSetUtxoSet(block *externalapi.DomainBlock) error {
isGenesis := len(block.Header.DirectParents()) == 0
if !isGenesis {
return nil
}
blockHash := consensushashing.BlockHash(block)
if !block.Header.UTXOCommitment().Equal(externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray())) {
log.Infof("Loading checkpoint UTXO set")
diff, utxoSetMultiset, err := deserializeMainnetUTXOSet()
if err != nil {
return err
}
log.Infof("Finished loading checkpoint UTXO set")
utxoSetHash := utxoSetMultiset.Hash()
if !utxoSetHash.Equal(block.Header.UTXOCommitment()) {
return errors.New("Invalid UTXO set dump")
}
area := model.NewStagingArea()
bp.consensusStateStore.StageVirtualUTXODiff(area, diff)
bp.utxoDiffStore.Stage(area, blockHash, diff, nil)
// commit the multiset of genesis
bp.multisetStore.Stage(area, blockHash, utxoSetMultiset)
err = staging.CommitAllChanges(bp.databaseContext, area)
if err != nil {
return err
}
} else {
// if it's genesis but has an empty muhash then commit an empty multiset and an empty diff
area := model.NewStagingArea()
bp.consensusStateStore.StageVirtualUTXODiff(area, utxo.NewUTXODiff())
bp.utxoDiffStore.Stage(area, blockHash, utxo.NewUTXODiff(), nil)
bp.multisetStore.Stage(area, blockHash, multiset.New())
err := staging.CommitAllChanges(bp.databaseContext, area)
if err != nil {
return err
}
}
return nil
}
func isHeaderOnlyBlock(block *externalapi.DomainBlock) bool {
return len(block.Transactions) == 0
}

View File

@ -140,10 +140,21 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) {
}
}
pruningPointUTXOs, err := tcSyncer.GetPruningPointUTXOs(pruningPoint, nil, 1000)
var fromOutpoint *externalapi.DomainOutpoint
var pruningPointUTXOs []*externalapi.OutpointAndUTXOEntryPair
const step = 100_000
for {
outpointAndUTXOEntryPairs, err := tcSyncer.GetPruningPointUTXOs(pruningPoint, fromOutpoint, step)
if err != nil {
t.Fatalf("GetPruningPointUTXOs: %+v", err)
}
fromOutpoint = outpointAndUTXOEntryPairs[len(outpointAndUTXOEntryPairs)-1].Outpoint
pruningPointUTXOs = append(pruningPointUTXOs, outpointAndUTXOEntryPairs...)
if len(outpointAndUTXOEntryPairs) < step {
break
}
}
err = synceeStaging.AppendImportedPruningPointUTXOs(pruningPointUTXOs)
if err != nil {
t.Fatalf("AppendImportedPruningPointUTXOs: %+v", err)
@ -507,7 +518,7 @@ func TestGetPruningPointUTXOs(t *testing.T) {
// Get pruning point UTXOs in a loop
var allOutpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair
step := 100
const step = 100_000
var fromOutpoint *externalapi.DomainOutpoint
for {
outpointAndUTXOEntryPairs, err := testConsensus.GetPruningPointUTXOs(pruningPoint, fromOutpoint, step)
@ -522,11 +533,17 @@ func TestGetPruningPointUTXOs(t *testing.T) {
}
}
const mainnetUTXOSize = 1232643
expected := len(outputs) + 1
if consensusConfig.Name == "kaspa-mainnet" {
expected += mainnetUTXOSize
}
// Make sure the length of the UTXOs is exactly spendingTransaction.Outputs + 1 coinbase
// output (includingBlock's coinbase)
if len(allOutpointAndUTXOEntryPairs) != len(outputs)+1 {
if len(allOutpointAndUTXOEntryPairs) != expected {
t.Fatalf("Returned an unexpected amount of UTXOs. "+
"Want: %d, got: %d", len(outputs)+2, len(allOutpointAndUTXOEntryPairs))
"Want: %d, got: %d", expected, len(allOutpointAndUTXOEntryPairs))
}
// Make sure all spendingTransaction.Outputs are in the returned UTXOs

View File

@ -4,6 +4,8 @@ import (
"bytes"
"math"
"math/big"
"reflect"
"runtime"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
@ -21,6 +23,31 @@ import (
"github.com/pkg/errors"
)
func TestBlockValidator_ValidateBodyInIsolation(t *testing.T) {
tests := []func(t *testing.T, tc testapi.TestConsensus, cfg *consensus.Config){
CheckBlockSanity,
CheckBlockHashMerkleRoot,
BlockMass,
CheckBlockDuplicateTransactions,
CheckBlockContainsOnlyOneCoinbase,
CheckBlockDoubleSpends,
CheckFirstBlockTransactionIsCoinbase,
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
tc, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestChainedTransactions")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
for _, test := range tests {
testName := runtime.FuncForPC(reflect.ValueOf(test).Pointer()).Name()
t.Run(testName, func(t *testing.T) {
test(t, tc, consensusConfig)
})
}
})
}
func TestChainedTransactions(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.BlockCoinbaseMaturity = 0
@ -89,16 +116,9 @@ func TestChainedTransactions(t *testing.T) {
})
}
// TestCheckBlockSanity tests the CheckBlockSanity function to ensure it works
// CheckBlockSanity tests the CheckBlockSanity function to ensure it works
// as expected.
func TestCheckBlockSanity(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockSanity")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
func CheckBlockSanity(t *testing.T, tc testapi.TestConsensus, _ *consensus.Config) {
blockHash := consensushashing.BlockHash(&exampleValidBlock)
if len(exampleValidBlock.Transactions) < 3 {
t.Fatalf("Too few transactions in block, expect at least 3, got %v", len(exampleValidBlock.Transactions))
@ -108,7 +128,7 @@ func TestCheckBlockSanity(t *testing.T) {
tc.BlockStore().Stage(stagingArea, blockHash, &exampleValidBlock)
err = tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
err := tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
if err != nil {
t.Fatalf("Failed validating block in isolation: %v", err)
}
@ -129,7 +149,6 @@ func TestCheckBlockSanity(t *testing.T) {
if err != nil {
t.Errorf("CheckBlockSanity: Expected block to be be body in isolation valid, got error instead: %v", err)
}
})
}
var unOrderedParentsBlock = externalapi.DomainBlock{
@ -1025,15 +1044,7 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
},
}
func TestCheckBlockHashMerkleRoot(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockHashMerkleRoot")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func CheckBlockHashMerkleRoot(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
@ -1052,18 +1063,9 @@ func TestCheckBlockHashMerkleRoot(t *testing.T) {
if err != nil {
t.Fatalf("ValidateAndInsertBlock: %+v", err)
}
})
}
func TestBlockMass(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockMass")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func BlockMass(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := initBlockWithInvalidBlockMass(consensusConfig, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
@ -1077,7 +1079,6 @@ func TestBlockMass(t *testing.T) {
t.Fatalf("ValidateBodyInIsolationTest: TestBlockMass:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrBlockMassTooHigh, err)
}
})
}
func initBlockWithInvalidBlockMass(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
@ -1113,16 +1114,7 @@ func initBlockWithInvalidBlockMass(consensusConfig *consensus.Config, tc testapi
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
}
func TestCheckBlockDuplicateTransactions(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockDuplicateTransactions")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func CheckBlockDuplicateTransactions(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := initBlockWithDuplicateTransaction(consensusConfig, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
@ -1136,7 +1128,6 @@ func TestCheckBlockDuplicateTransactions(t *testing.T) {
t.Fatalf("ValidateBodyInIsolationTest: TestCheckBlockDuplicateTransactions:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrDuplicateTx, err)
}
})
}
func initBlockWithDuplicateTransaction(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
@ -1170,16 +1161,7 @@ func initBlockWithDuplicateTransaction(consensusConfig *consensus.Config, tc tes
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx, tx})
}
func TestCheckBlockContainsOnlyOneCoinbase(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockContainsOnlyOneCoinbase")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func CheckBlockContainsOnlyOneCoinbase(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := initBlockWithMoreThanOneCoinbase(consensusConfig, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
@ -1193,7 +1175,6 @@ func TestCheckBlockContainsOnlyOneCoinbase(t *testing.T) {
t.Fatalf("ValidateBodyInIsolationTest: TestCheckBlockContainsOnlyOneCoinbase:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrMultipleCoinbases, err)
}
})
}
func initBlockWithMoreThanOneCoinbase(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
@ -1227,16 +1208,7 @@ func initBlockWithMoreThanOneCoinbase(consensusConfig *consensus.Config, tc test
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
}
func TestCheckBlockDoubleSpends(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockDoubleSpends")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func CheckBlockDoubleSpends(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := initBlockWithDoubleSpends(consensusConfig, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
@ -1250,7 +1222,6 @@ func TestCheckBlockDoubleSpends(t *testing.T) {
t.Fatalf("ValidateBodyInIsolationTest: TestCheckBlockDoubleSpends:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrDoubleSpendInSameBlock, err)
}
})
}
func initBlockWithDoubleSpends(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
@ -1303,27 +1274,18 @@ func initBlockWithDoubleSpends(consensusConfig *consensus.Config, tc testapi.Tes
&emptyCoinbase, []*externalapi.DomainTransaction{tx, txSameOutpoint})
}
func TestCheckFirstBlockTransactionIsCoinbase(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckFirstBlockTransactionIsCoinbase")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
func CheckFirstBlockTransactionIsCoinbase(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block := initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig)
blockHash := consensushashing.BlockHash(block)
stagingArea := model.NewStagingArea()
tc.BlockStore().Stage(stagingArea, blockHash, block)
err = tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
err := tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
if err == nil || !errors.Is(err, ruleerrors.ErrFirstTxNotCoinbase) {
t.Fatalf("ValidateBodyInIsolationTest: TestCheckFirstBlockTransactionIsCoinbase:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrFirstTxNotCoinbase, err)
}
})
}
func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consensus.Config) *externalapi.DomainBlock {

View File

@ -67,8 +67,8 @@ func TestValidateMedianTime(t *testing.T) {
blockTime := tip.Header.TimeInMilliseconds()
for i := 0; i < 100; i++ {
blockTime += 1000
for i := 0; i < 10; i++ {
blockTime += 100
_, tipHash = addBlock(blockTime, []*externalapi.DomainHash{tipHash}, nil)
}
@ -163,7 +163,7 @@ func TestCheckParentsIncest(t *testing.T) {
func TestCheckMergeSizeLimit(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.MergeSetSizeLimit = 2 * uint64(consensusConfig.K)
consensusConfig.MergeSetSizeLimit = 5
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckMergeSizeLimit")
if err != nil {

View File

@ -1,6 +1,9 @@
package blockvalidator_test
import (
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"reflect"
"runtime"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
@ -13,18 +16,30 @@ import (
"github.com/pkg/errors"
)
func TestCheckParentsLimit(t *testing.T) {
func TestBlockValidator_ValidateHeaderInIsolation(t *testing.T) {
tests := []func(t *testing.T, tc testapi.TestConsensus, cfg *consensus.Config){
CheckParentsLimit,
CheckBlockVersion,
CheckBlockTimestampInIsolation,
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentsLimit")
tc, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestBlockValidator_ValidateHeaderInIsolation")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
for _, test := range tests {
testName := runtime.FuncForPC(reflect.ValueOf(test).Pointer()).Name()
t.Run(testName, func(t *testing.T) {
test(t, tc, consensusConfig)
})
}
})
}
func CheckParentsLimit(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
for i := externalapi.KType(0); i < consensusConfig.MaxBlockParents+1; i++ {
_, _, err = tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
_, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@ -39,19 +54,9 @@ func TestCheckParentsLimit(t *testing.T) {
if !errors.Is(err, ruleerrors.ErrTooManyParents) {
t.Fatalf("Unexpected error: %+v", err)
}
})
}
func TestCheckBlockVersion(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockVersion")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
func CheckBlockVersion(t *testing.T, tc testapi.TestConsensus, consensusConfig *consensus.Config) {
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
@ -76,10 +81,9 @@ func TestCheckBlockVersion(t *testing.T) {
if !errors.Is(err, ruleerrors.ErrBlockVersionIsUnknown) {
t.Fatalf("Unexpected error: %+v", err)
}
})
}
func TestCheckBlockTimestampInIsolation(t *testing.T) {
func CheckBlockTimestampInIsolation(t *testing.T, tc testapi.TestConsensus, cfg *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()

View File

@ -49,10 +49,12 @@ func (v *blockValidator) ValidatePruningPointViolationAndProofOfWorkAndDifficult
}
}
if !blockHash.Equal(v.genesisHash) {
err = v.checkProofOfWork(header)
if err != nil {
return err
}
}
err = v.validateDifficulty(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {

View File

@ -101,11 +101,14 @@ func TestPOW(t *testing.T) {
t.Fatal(err)
}
random := rand.New(rand.NewSource(0))
// Difficulty is too high on mainnet to actually mine.
if consensusConfig.Name != "kaspa-mainnet" {
mining.SolveBlock(validBlock, random)
_, err = tc.ValidateAndInsertBlock(validBlock, true)
if err != nil {
t.Fatal(err)
}
}
})
}
@ -296,7 +299,7 @@ func TestCheckPruningPointViolation(t *testing.T) {
func TestValidateDifficulty(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
mocDifficulty := &mocDifficultyManager{}
mocDifficulty := &mocDifficultyManager{genesisDaaScore: consensusConfig.GenesisBlock.Header.DAAScore()}
factory.SetTestDifficultyManager(func(_ model.DBReader, _ model.GHOSTDAGManager, _ model.GHOSTDAGDataStore,
_ model.BlockHeaderStore, daaBlocksStore model.DAABlocksStore, _ model.DAGTopologyManager,
_ model.DAGTraversalManager, _ *big.Int, _ int, _ bool, _ time.Duration,
@ -342,6 +345,7 @@ type mocDifficultyManager struct {
testDifficulty uint32
testGenesisBits uint32
daaBlocksStore model.DAABlocksStore
genesisDaaScore uint64
}
// RequiredDifficulty returns the difficulty required for the test
@ -352,7 +356,7 @@ func (dm *mocDifficultyManager) RequiredDifficulty(*model.StagingArea, *external
// StageDAADataAndReturnRequiredDifficulty returns the difficulty required for the test
func (dm *mocDifficultyManager) StageDAADataAndReturnRequiredDifficulty(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) (uint32, error) {
// Populate daaBlocksStore with fake values
dm.daaBlocksStore.StageDAAScore(stagingArea, blockHash, 0)
dm.daaBlocksStore.StageDAAScore(stagingArea, blockHash, dm.genesisDaaScore)
dm.daaBlocksStore.StageBlockDAAAddedBlocks(stagingArea, blockHash, nil)
return dm.testDifficulty, nil

View File

@ -86,36 +86,5 @@ func TestBlockRewardSwitch(t *testing.T) {
t.Fatalf("Subsidy has unexpected value. Want: %d, got: %d", consensusConfig.MinSubsidy, subsidy)
}
}
// Add another block. We expect it to be another pruning point
lastPruningPointHash, _, err := tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
// Make sure that another pruning point had been added
pruningPointHeaders, err = tc.PruningPointHeaders()
if err != nil {
t.Fatalf("PruningPointHeaders: %+v", pruningPointHeaders)
}
expectedPruningPointHeaderAmount = expectedPruningPointHeaderAmount + 1
if uint64(len(pruningPointHeaders)) != expectedPruningPointHeaderAmount {
t.Fatalf("Unexpected amount of pruning point headers. "+
"Want: %d, got: %d", expectedPruningPointHeaderAmount, len(pruningPointHeaders))
}
// Make sure that the last pruning point has a post-switch subsidy
lastPruningPoint, err := tc.GetBlock(lastPruningPointHash)
if err != nil {
t.Fatalf("GetBlock: %+v", err)
}
lastPruningPointCoinbase := lastPruningPoint.Transactions[transactionhelper.CoinbaseTransactionIndex]
_, _, subsidy, err := tc.CoinbaseManager().ExtractCoinbaseDataBlueScoreAndSubsidy(lastPruningPointCoinbase)
if err != nil {
t.Fatalf("ExtractCoinbaseDataBlueScoreAndSubsidy: %+v", err)
}
if subsidy != consensusConfig.SubsidyGenesisReward {
t.Fatalf("Subsidy has unexpected value. Want: %d, got: %d", consensusConfig.SubsidyGenesisReward, subsidy)
}
})
}

View File

@ -2,6 +2,8 @@ package coinbasemanager
import (
"encoding/binary"
"math/big"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
@ -10,7 +12,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/pkg/errors"
"math/big"
)
type coinbaseManager struct {
@ -190,51 +191,7 @@ func (c *coinbaseManager) CalcBlockSubsidy(stagingArea *model.StagingArea,
return c.subsidyGenesisReward, nil
}
isBlockRewardFixed, err := c.isBlockRewardFixed(stagingArea, blockPruningPoint)
if err != nil {
return 0, err
}
if isBlockRewardFixed {
return c.subsidyGenesisReward, nil
}
averagePastSubsidy, err := c.calculateAveragePastSubsidy(stagingArea, blockHash)
if err != nil {
return 0, err
}
mergeSetSubsidySum, err := c.calculateMergeSetSubsidySum(stagingArea, blockHash)
if err != nil {
return 0, err
}
subsidyRandomVariable, err := c.calculateSubsidyRandomVariable(stagingArea, blockHash)
if err != nil {
return 0, err
}
pastSubsidy := new(big.Rat).Mul(averagePastSubsidy, c.subsidyPastRewardMultiplier)
mergeSetSubsidy := new(big.Rat).Mul(mergeSetSubsidySum, c.subsidyMergeSetRewardMultiplier)
// In order to avoid unsupported negative exponents in powInt64, flip
// the numerator and the denominator manually
subsidyRandom := new(big.Rat)
if subsidyRandomVariable >= 0 {
subsidyRandom = subsidyRandom.SetInt64(1 << subsidyRandomVariable)
} else {
subsidyRandom = subsidyRandom.SetFrac64(1, 1<<(-subsidyRandomVariable))
}
blockSubsidyBigRat := new(big.Rat).Add(mergeSetSubsidy, new(big.Rat).Mul(pastSubsidy, subsidyRandom))
blockSubsidyBigInt := new(big.Int).Div(blockSubsidyBigRat.Num(), blockSubsidyBigRat.Denom())
blockSubsidyUint64 := blockSubsidyBigInt.Uint64()
clampedBlockSubsidy := blockSubsidyUint64
if clampedBlockSubsidy < c.minSubsidy {
clampedBlockSubsidy = c.minSubsidy
} else if clampedBlockSubsidy > c.maxSubsidy {
clampedBlockSubsidy = c.maxSubsidy
}
return clampedBlockSubsidy, nil
return c.maxSubsidy, nil
}
func (c *coinbaseManager) calculateAveragePastSubsidy(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (*big.Rat, error) {

View File

@ -75,7 +75,7 @@ func TestVirtualDiff(t *testing.T) {
blockB.Transactions[0].Outputs[0].Value,
blockB.Transactions[0].Outputs[0].ScriptPublicKey,
true,
2, //Expected virtual DAA score
consensusConfig.GenesisBlock.Header.DAAScore()+2, //Expected virtual DAA score
)) {
t.Fatalf("Unexpected entry %s", entry)
}

View File

@ -2,7 +2,6 @@ package consensusstatemanager
import (
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/multiset"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/pkg/errors"
@ -23,8 +22,16 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(stagingArea
if blockHash.Equal(csm.genesisHash) {
log.Debugf("Block %s is the genesis. By definition, "+
"it has an empty UTXO diff, empty acceptance data, and a blank multiset", blockHash)
return utxo.NewUTXODiff(), externalapi.AcceptanceData{}, multiset.New(), nil
"it has a predefined UTXO diff, empty acceptance data, and a predefined multiset", blockHash)
multiset, err := csm.multisetStore.Get(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
}
utxoDiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
}
return utxoDiff, externalapi.AcceptanceData{}, multiset, nil
}
blockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, stagingArea, blockHash, false)

View File

@ -4,7 +4,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/multiset"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
)
@ -19,8 +18,8 @@ func (csm *consensusStateManager) calculateMultiset(stagingArea *model.StagingAr
if blockHash.Equal(csm.genesisHash) {
log.Debugf("Selected parent is nil, which could only happen for the genesis. " +
"The genesis, by definition, has an empty multiset")
return multiset.New(), nil
"The genesis has a predefined multiset")
return csm.multisetStore.Get(csm.databaseContext, stagingArea, blockHash)
}
ms, err := csm.multisetStore.Get(csm.databaseContext, stagingArea, blockGHOSTDAGData.SelectedParent())

View File

@ -3,8 +3,6 @@ package consensusstatemanager
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/util/staging"
"github.com/kaspanet/kaspad/domain/consensus/model"
@ -129,7 +127,11 @@ func (csm *consensusStateManager) selectedParentInfo(
if lastUnverifiedBlock.Equal(csm.genesisHash) {
log.Debugf("the most recent unverified block is the genesis block, "+
"which by definition has status: %s", externalapi.StatusUTXOValid)
return lastUnverifiedBlock, externalapi.StatusUTXOValid, utxo.NewUTXODiff(), nil
utxoDiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, stagingArea, lastUnverifiedBlock)
if err != nil {
return nil, 0, nil, err
}
return lastUnverifiedBlock, externalapi.StatusUTXOValid, utxoDiff, nil
}
lastUnverifiedBlockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, stagingArea, lastUnverifiedBlock, false)
if err != nil {

View File

@ -285,7 +285,7 @@ func TestTransactionAcceptance(t *testing.T) {
if err != nil {
t.Fatalf("Error getting blockF: %+v", err)
}
updatedDAAScoreVirtualBlock := 26
updatedDAAScoreVirtualBlock := consensusConfig.GenesisBlock.Header.DAAScore() + 26
//We expect the second transaction in the "blue block" (blueChildOfRedBlock) to be accepted because the merge set is ordered topologically
//and the red block is ordered topologically before the "blue block" so the input is known in the UTXOSet.
expectedAcceptanceData := externalapi.AcceptanceData{

View File

@ -40,12 +40,12 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"C", "D"},
id: "E",
expectedWindow: []string{"C", "D", "B"},
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindow: []string{"C", "D", "B"},
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"A"},
@ -60,37 +60,38 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "H", "C", "D", "B", "G"},
expectedWindow: []string{"F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "H", "C", "D", "B", "G"},
expectedWindow: []string{"I", "F", "D", "H", "C", "G", "B"},
},
//
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "H", "C", "D", "B", "G"},
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "H", "C", "D", "B", "G"},
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "C", "D", "B", "G"},
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "C", "D", "B"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "G"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "C", "D"},
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
},
},
dagconfig.TestnetParams.Name: {
@ -132,37 +133,37 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "H", "C", "D", "G", "B"},
expectedWindow: []string{"F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "H", "C", "D", "G", "B"},
expectedWindow: []string{"I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "H", "C", "D", "G", "B"},
expectedWindow: []string{"J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "H", "C", "D", "G", "B"},
expectedWindow: []string{"K", "J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "C", "D", "G", "B"},
expectedWindow: []string{"L", "K", "J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "C", "D", "G"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "C", "D", "H", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "C", "D"},
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "C", "D", "H"},
},
},
dagconfig.DevnetParams.Name: {
@ -204,37 +205,37 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "D", "C", "H", "B", "G"},
expectedWindow: []string{"F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "D", "C", "H", "B", "G"},
expectedWindow: []string{"I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "D", "C", "H", "B", "G"},
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "D", "C", "H", "B", "G"},
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "C", "H", "B", "G"},
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "C", "H", "B"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "C", "H"},
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
},
},
dagconfig.SimnetParams.Name: {
@ -276,37 +277,37 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "D", "H", "C", "G", "B"},
expectedWindow: []string{"F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "D", "H", "C", "G", "B"},
expectedWindow: []string{"I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "G", "B"},
expectedWindow: []string{"J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "G", "B"},
expectedWindow: []string{"K", "J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "G", "B"},
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "G"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "D", "C", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "D", "C"},
},
},
}

View File

@ -105,10 +105,14 @@ func (dm *difficultyManager) requiredDifficultyFromTargetsWindow(targetsWindow b
return dm.genesisBits, nil
}
// in the past this was < 2 as the comment explains, we changed it to under the window size to
// make the hashrate(which is ~1.5GH/s) constant in the first 2641 blocks so that we won't have a lot of tips
// We need at least 2 blocks to get a timestamp interval
// We could instead clamp the timestamp difference to `targetTimePerBlock`,
// but then everything will cancel out and we'll get the target from the last block, which will be the same as genesis.
if len(targetsWindow) < 2 {
// We add 64 as a safety margin
if len(targetsWindow) < 2 || len(targetsWindow) < dm.difficultyAdjustmentWindowSize + 64 {
return dm.genesisBits, nil
}
windowMinTimestamp, windowMaxTimeStamp, windowsMinIndex, _ := targetsWindow.minMaxTimestamps()
@ -157,7 +161,11 @@ func (dm *difficultyManager) calculateDaaScoreAndAddedBlocks(stagingArea *model.
isBlockWithTrustedData bool) (uint64, []*externalapi.DomainHash, error) {
if blockHash.Equal(dm.genesisHash) {
return 0, nil, nil
genesisHeader, err := dm.headerStore.BlockHeader(dm.databaseContext, stagingArea, dm.genesisHash)
if err != nil {
return 0, nil, err
}
return genesisHeader.DAAScore(), nil, nil
}
ghostdagData, err := dm.ghostdagStore.Get(dm.databaseContext, stagingArea, blockHash, false)

View File

@ -19,12 +19,6 @@ import (
func TestDifficulty(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
// Mainnet's genesis is too new, so if we'll build on it we'll get to the future very quickly.
// TODO: Once it gets older, we should unskip this test.
if consensusConfig.Name == "kaspa-mainnet" {
return
}
if consensusConfig.DisableDifficultyAdjustment {
return
}
@ -37,7 +31,7 @@ func TestDifficulty(t *testing.T) {
}
consensusConfig.K = 1
consensusConfig.DifficultyAdjustmentWindowSize = 265
consensusConfig.DifficultyAdjustmentWindowSize = 140
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestDifficulty")
@ -114,7 +108,7 @@ func TestDifficulty(t *testing.T) {
"window size, the difficulty should be the same as genesis'")
}
}
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize+100; i++ {
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize+10; i++ {
tip, tipHash = addBlock(0, tipHash)
if tip.Header.Bits() != consensusConfig.GenesisBlock.Header.Bits() {
t.Fatalf("As long as the block rate remains the same, the difficulty shouldn't change")
@ -136,9 +130,9 @@ func TestDifficulty(t *testing.T) {
var expectedBits uint32
switch consensusConfig.Name {
case dagconfig.TestnetParams.Name, dagconfig.DevnetParams.Name:
expectedBits = uint32(0x1e7f83df)
expectedBits = uint32(0x1e7f1441)
case dagconfig.MainnetParams.Name:
expectedBits = uint32(0x1e7f83df)
expectedBits = uint32(0x1d02c50f)
}
if tip.Header.Bits() != expectedBits {
@ -237,7 +231,7 @@ func TestDifficulty(t *testing.T) {
func TestDAAScore(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.DifficultyAdjustmentWindowSize = 265
consensusConfig.DifficultyAdjustmentWindowSize = 86
stagingArea := model.NewStagingArea()
@ -269,9 +263,9 @@ func TestDAAScore(t *testing.T) {
t.Fatalf("DAAScore: %+v", err)
}
blockBlueScore3ExpectedDAAScore := uint64(2)
blockBlueScore3ExpectedDAAScore := uint64(2) + consensusConfig.GenesisBlock.Header.DAAScore()
if blockBlueScore3DAAScore != blockBlueScore3ExpectedDAAScore {
t.Fatalf("DAA score is expected to be %d but got %d", blockBlueScore3ExpectedDAAScore, blockBlueScore3ExpectedDAAScore)
t.Fatalf("DAA score is expected to be %d but got %d", blockBlueScore3ExpectedDAAScore, blockBlueScore3DAAScore)
}
tipDAAScore := blockBlueScore3ExpectedDAAScore

View File

@ -7,15 +7,13 @@ import (
)
type parentsManager struct {
hardForkOmitGenesisFromParentsDAAScore uint64
genesisHash *externalapi.DomainHash
}
// New instantiates a new ParentsManager
func New(genesisHash *externalapi.DomainHash, hardForkOmitGenesisFromParentsDAAScore uint64) model.ParentsManager {
func New(genesisHash *externalapi.DomainHash) model.ParentsManager {
return &parentsManager{
genesisHash: genesisHash,
hardForkOmitGenesisFromParentsDAAScore: hardForkOmitGenesisFromParentsDAAScore,
}
}
@ -25,7 +23,7 @@ func (pm *parentsManager) ParentsAtLevel(blockHeader externalapi.BlockHeader, le
parentsAtLevel = blockHeader.Parents()[level]
}
if len(parentsAtLevel) == 0 && len(blockHeader.DirectParents()) > 0 && blockHeader.DAAScore() >= pm.hardForkOmitGenesisFromParentsDAAScore {
if len(parentsAtLevel) == 0 && len(blockHeader.DirectParents()) > 0 {
return externalapi.BlockLevelParents{pm.genesisHash}
}
@ -33,11 +31,7 @@ func (pm *parentsManager) ParentsAtLevel(blockHeader externalapi.BlockHeader, le
}
func (pm *parentsManager) Parents(blockHeader externalapi.BlockHeader) []externalapi.BlockLevelParents {
numParents := len(blockHeader.Parents())
if blockHeader.DAAScore() >= pm.hardForkOmitGenesisFromParentsDAAScore {
numParents = constants.MaxBlockLevel + 1
}
numParents := constants.MaxBlockLevel + 1
parents := make([]externalapi.BlockLevelParents, numParents)
for i := 0; i < numParents; i++ {
parents[i] = pm.ParentsAtLevel(blockHeader, i)

View File

@ -36,14 +36,16 @@ func TestPruning(t *testing.T) {
dagconfig.SimnetParams.Name: "1582",
},
"dag-for-test-pruning.json": {
dagconfig.MainnetParams.Name: "502",
dagconfig.MainnetParams.Name: "503",
dagconfig.TestnetParams.Name: "502",
dagconfig.DevnetParams.Name: "502",
dagconfig.SimnetParams.Name: "503",
dagconfig.SimnetParams.Name: "502",
},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
// Improve the performance of the test a little
consensusConfig.DisableDifficultyAdjustment = true
err := filepath.Walk("./testdata", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@ -71,6 +73,7 @@ func TestPruning(t *testing.T) {
consensusConfig.DifficultyAdjustmentWindowSize = 400
factory := consensus.NewFactory()
factory.SetTestLevelDBCacheSize(128)
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestPruning")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)

View File

@ -675,7 +675,19 @@ func (pm *pruningManager) calculateDiffBetweenPreviousAndCurrentPruningPoints(st
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.calculateDiffBetweenPreviousAndCurrentPruningPoints")
defer onEnd()
if currentPruningHash.Equal(pm.genesisHash) {
return utxo.NewUTXODiff(), nil
iter, err := pm.consensusStateManager.RestorePastUTXOSetIterator(stagingArea, currentPruningHash)
if err != nil {
return nil, err
}
set := make(map[externalapi.DomainOutpoint]externalapi.UTXOEntry)
for ok := iter.First(); ok; ok = iter.Next() {
outpoint, entry, err := iter.Get()
if err != nil {
return nil, err
}
set[*outpoint] = entry
}
return utxo.NewUTXODiffFromCollections(utxo.NewUTXOCollection(set), utxo.NewUTXOCollection(make(map[externalapi.DomainOutpoint]externalapi.UTXOEntry)))
}
pruningPointIndex, err := pm.pruningStore.CurrentPruningPointIndex(pm.databaseContext, stagingArea)

View File

@ -49,7 +49,7 @@ func TestCheckLockTimeVerifyConditionedByDAAScore(t *testing.T) {
}
fees := uint64(1)
//Create a CLTV script:
targetDAAScore := uint64(30)
targetDAAScore := consensusConfig.GenesisBlock.Header.DAAScore() + uint64(30)
redeemScriptCLTV, err := createScriptCLTV(targetDAAScore)
if err != nil {
t.Fatalf("Failed to create a script using createScriptCLTV: %v", err)
@ -156,7 +156,7 @@ func TestCheckLockTimeVerifyConditionedByDAAScoreWithWrongLockTime(t *testing.T)
}
fees := uint64(1)
//Create a CLTV script:
targetDAAScore := uint64(30)
targetDAAScore := consensusConfig.GenesisBlock.Header.DAAScore() + uint64(30)
redeemScriptCLTV, err := createScriptCLTV(targetDAAScore)
if err != nil {
t.Fatalf("Failed to create a script using createScriptCLTV: %v", err)

View File

@ -37,5 +37,7 @@ const (
LockTimeThreshold = 5e11 // Tue Nov 5 00:53:20 1985 UTC
// MaxBlockLevel is the maximum possible block level.
MaxBlockLevel = 255
// This is technically 255, but we clamped it at 256 - block level of mainnet genesis
// This means that any block that has a level lower or equal to genesis will be level 0.
MaxBlockLevel = 225
)

View File

@ -104,9 +104,10 @@ func BlockLevel(header externalapi.BlockHeader) int {
}
proofOfWorkValue := NewState(header.ToMutable()).CalculateProofOfWorkValue()
for blockLevel := 0; ; blockLevel++ {
if blockLevel == constants.MaxBlockLevel || proofOfWorkValue.Bit(blockLevel+1) != 0 {
return blockLevel
}
level := constants.MaxBlockLevel - proofOfWorkValue.BitLen()
// If the block has a level lower than genesis make it zero.
if level < 0 {
level = 0
}
return level
}

View File

@ -22,7 +22,7 @@ import (
//
const (
defaultMaxCoinbasePayloadLength = 172
defaultMaxCoinbasePayloadLength = 204
// defaultMaxBlockMass is a bound on the mass of a block, larger values increase the bound d
// on the round trip time of a block, which affects the other parameters as described below
defaultMaxBlockMass = 500_000
@ -49,7 +49,7 @@ const (
defaultMergeSetSizeLimit = defaultGHOSTDAGK * 10
defaultSubsidyGenesisReward = 1 * constants.SompiPerKaspa
defaultMinSubsidy = 1 * constants.SompiPerKaspa
defaultMaxSubsidy = 1000 * constants.SompiPerKaspa
defaultMaxSubsidy = 500 * constants.SompiPerKaspa
defaultBaseSubsidy = 50 * constants.SompiPerKaspa
defaultFixedSubsidySwitchPruningPointInterval uint64 = 7
defaultCoinbasePayloadScriptPublicKeyMaxLength = 150

View File

@ -36,10 +36,14 @@ var genesisTxPayload = []byte{
0x20, 0xd7, 0x90, 0xd7, 0x9c, 0xd7, 0x94, 0xd7,
0x9b, 0xd7, 0x9d, 0x20, 0xd7, 0xaa, 0xd7, 0xa2,
0xd7, 0x91, 0xd7, 0x93, 0xd7, 0x95, 0xd7, 0x9f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Bitcoin block hash 00000000000000000001733c62adb19f1b77fa0735d0e11f25af36fc9ca908a5
0x00, 0x01, 0x73, 0x3c, 0x62, 0xad, 0xb1, 0x9f,
0x1b, 0x77, 0xfa, 0x07, 0x35, 0xd0, 0xe1, 0x1f,
0x25, 0xaf, 0x36, 0xfc, 0x9c, 0xa9, 0x08, 0xa5,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Bitcoin block hash 0000000000000000000b1f8e1c17b0133d439174e52efbb0c41c3583a8aa66b0
0x00, 0x0b, 0x1f, 0x8e, 0x1c, 0x17, 0xb0, 0x13,
0x3d, 0x43, 0x91, 0x74 ,0xe5, 0x2e, 0xfb, 0xb0,
0xc4, 0x1c, 0x35, 0x83, 0xa8, 0xaa, 0x66, 0xb0,
0x0f, 0xca, 0x37, 0xca, 0x66, 0x7c, 0x2d, 0x55, // Checkpoint block hash 0fca37ca667c2d550a6c4416dad9717e50927128c424fa4edbebc436ab13aeef
0x0a, 0x6c, 0x44, 0x16, 0xda, 0xd9, 0x71, 0x7e,
0x50, 0x92, 0x71, 0x28, 0xc4, 0x24, 0xfa, 0x4e,
0xdb, 0xeb, 0xc4, 0x36, 0xab, 0x13, 0xae, 0xef,
}
// genesisCoinbaseTx is the coinbase transaction for the genesis blocks for
@ -50,19 +54,13 @@ var genesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0, []*externa
// genesisHash is the hash of the first block in the block DAG for the main
// network (genesis block).
var genesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0xca, 0xeb, 0x97, 0x96, 0x0a, 0x16, 0x0c, 0x21,
0x1a, 0x6b, 0x21, 0x96, 0xbd, 0x78, 0x39, 0x9f,
0xd4, 0xc4, 0xcc, 0x5b, 0x50, 0x9f, 0x55, 0xc1,
0x2c, 0x8a, 0x7d, 0x81, 0x5f, 0x75, 0x36, 0xea,
0x58, 0xc2, 0xd4, 0x19, 0x9e, 0x21, 0xf9, 0x10, 0xd1, 0x57, 0x1d, 0x11, 0x49, 0x69, 0xce, 0xce, 0xf4, 0x8f, 0x9, 0xf9, 0x34, 0xd4, 0x2c, 0xcb, 0x6a, 0x28, 0x1a, 0x15, 0x86, 0x8f, 0x29, 0x99,
})
// genesisMerkleRoot is the hash of the first transaction in the genesis block
// for the main network.
var genesisMerkleRoot = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0xca, 0xed, 0xaf, 0x7d, 0x4a, 0x08, 0xbb, 0xe8,
0x90, 0x11, 0x64, 0x0c, 0x48, 0x41, 0xb6, 0x6d,
0x5b, 0xba, 0x67, 0xd7, 0x28, 0x8c, 0xe6, 0xd6,
0x72, 0x28, 0xdb, 0x00, 0x09, 0x66, 0xe9, 0x74,
0x8e, 0xc8, 0x98, 0x56, 0x8c, 0x68, 0x1, 0xd1, 0x3d, 0xf4, 0xee, 0x6e, 0x2a, 0x1b, 0x54, 0xb7, 0xe6, 0x23, 0x6f, 0x67, 0x1f, 0x20, 0x95, 0x4f, 0x5, 0x30, 0x64, 0x10, 0x51, 0x8e, 0xeb, 0x32,
})
// genesisBlock defines the genesis block of the block DAG which serves as the
@ -73,11 +71,13 @@ var genesisBlock = externalapi.DomainBlock{
[]externalapi.BlockLevelParents{},
genesisMerkleRoot,
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x17cfb020c02,
0x1e7fffff,
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x71, 0x0f, 0x27, 0xdf, 0x42, 0x3e, 0x63, 0xaa, 0x6c, 0xdb, 0x72, 0xb8, 0x9e, 0xa5, 0xa0, 0x6c, 0xff, 0xa3, 0x99, 0xd6, 0x6f, 0x16, 0x77, 0x04, 0x45, 0x5b, 0x5a, 0xf5, 0x9d, 0xef, 0x8e, 0x20,
}),
1637609671037,
486722099,
0x3392c,
0,
1312860, // Checkpoint DAA score
0,
big.NewInt(0),
&externalapi.DomainHash{},

View File

@ -186,8 +186,6 @@ type Params struct {
FixedSubsidySwitchPruningPointInterval uint64
FixedSubsidySwitchHashRateThreshold *big.Int
HardForkOmitGenesisFromParentsDAAScore uint64
}
// NormalizeRPCServerAddress returns addr with the current network default
@ -213,7 +211,15 @@ var MainnetParams = Params{
Net: appmessage.Mainnet,
RPCPort: "16110",
DefaultPort: "16111",
DNSSeeds: []string{"mainnet-dnsseed.daglabs-dev.com"},
DNSSeeds: []string{
"mainnet-dnsseed.daglabs-dev.com",
// This DNS seeder is run by Denis Mashkevich
"mainnet-dnsseed-1.kaspanet.org",
// This DNS seeder is run by Denis Mashkevich
"mainnet-dnsseed-2.kaspanet.org",
// This DNS seeder is run by Elichai Turkel
"kaspa.turkel.in",
},
// DAG parameters
GenesisBlock: &genesisBlock,
@ -266,7 +272,6 @@ var MainnetParams = Params{
PruningProofM: defaultPruningProofM,
FixedSubsidySwitchPruningPointInterval: defaultFixedSubsidySwitchPruningPointInterval,
FixedSubsidySwitchHashRateThreshold: big.NewInt(150_000_000_000),
HardForkOmitGenesisFromParentsDAAScore: 1320000,
}
// TestnetParams defines the network parameters for the test Kaspa network.
@ -329,7 +334,6 @@ var TestnetParams = Params{
PruningProofM: defaultPruningProofM,
FixedSubsidySwitchPruningPointInterval: defaultFixedSubsidySwitchPruningPointInterval,
FixedSubsidySwitchHashRateThreshold: big.NewInt(150_000_000_000),
HardForkOmitGenesisFromParentsDAAScore: 2e6,
}
// SimnetParams defines the network parameters for the simulation test Kaspa
@ -396,7 +400,6 @@ var SimnetParams = Params{
PruningProofM: defaultPruningProofM,
FixedSubsidySwitchPruningPointInterval: defaultFixedSubsidySwitchPruningPointInterval,
FixedSubsidySwitchHashRateThreshold: big.NewInt(150_000_000_000),
HardForkOmitGenesisFromParentsDAAScore: 5,
}
// DevnetParams defines the network parameters for the development Kaspa network.
@ -459,7 +462,6 @@ var DevnetParams = Params{
PruningProofM: defaultPruningProofM,
FixedSubsidySwitchPruningPointInterval: defaultFixedSubsidySwitchPruningPointInterval,
FixedSubsidySwitchHashRateThreshold: big.NewInt(150_000_000_000),
HardForkOmitGenesisFromParentsDAAScore: 3000,
}
var (

View File

@ -40,7 +40,7 @@ func TestValidateAndInsertTransaction(t *testing.T) {
miningManager := miningFactory.NewMiningManager(consensusReference, &consensusConfig.Params, mempool.DefaultConfig(&consensusConfig.Params))
transactionsToInsert := make([]*externalapi.DomainTransaction, 10)
for i := range transactionsToInsert {
transactionsToInsert[i] = createTransactionWithUTXOEntry(t, i)
transactionsToInsert[i] = createTransactionWithUTXOEntry(t, i, 0)
_, err = miningManager.ValidateAndInsertTransaction(transactionsToInsert[i], false, true)
if err != nil {
t.Fatalf("ValidateAndInsertTransaction: %v", err)
@ -89,7 +89,7 @@ func TestImmatureSpend(t *testing.T) {
tcAsConsensusPointer := &tcAsConsensus
consensusReference := consensusreference.NewConsensusReference(&tcAsConsensusPointer)
miningManager := miningFactory.NewMiningManager(consensusReference, &consensusConfig.Params, mempool.DefaultConfig(&consensusConfig.Params))
tx := createTransactionWithUTXOEntry(t, 0)
tx := createTransactionWithUTXOEntry(t, 0, consensusConfig.GenesisBlock.Header.DAAScore())
_, err = miningManager.ValidateAndInsertTransaction(tx, false, false)
txRuleError := &mempool.TxRuleError{}
if !errors.As(err, txRuleError) || txRuleError.RejectCode != mempool.RejectImmatureSpend {
@ -119,7 +119,7 @@ func TestInsertDoubleTransactionsToMempool(t *testing.T) {
tcAsConsensusPointer := &tcAsConsensus
consensusReference := consensusreference.NewConsensusReference(&tcAsConsensusPointer)
miningManager := miningFactory.NewMiningManager(consensusReference, &consensusConfig.Params, mempool.DefaultConfig(&consensusConfig.Params))
transaction := createTransactionWithUTXOEntry(t, 0)
transaction := createTransactionWithUTXOEntry(t, 0, 0)
_, err = miningManager.ValidateAndInsertTransaction(transaction, false, true)
if err != nil {
t.Fatalf("ValidateAndInsertTransaction: %v", err)
@ -186,7 +186,7 @@ func TestHandleNewBlockTransactions(t *testing.T) {
miningManager := miningFactory.NewMiningManager(consensusReference, &consensusConfig.Params, mempool.DefaultConfig(&consensusConfig.Params))
transactionsToInsert := make([]*externalapi.DomainTransaction, 10)
for i := range transactionsToInsert {
transaction := createTransactionWithUTXOEntry(t, i)
transaction := createTransactionWithUTXOEntry(t, i, 0)
transactionsToInsert[i] = transaction
_, err = miningManager.ValidateAndInsertTransaction(transaction, false, true)
if err != nil {
@ -253,12 +253,12 @@ func TestDoubleSpendWithBlock(t *testing.T) {
tcAsConsensusPointer := &tcAsConsensus
consensusReference := consensusreference.NewConsensusReference(&tcAsConsensusPointer)
miningManager := miningFactory.NewMiningManager(consensusReference, &consensusConfig.Params, mempool.DefaultConfig(&consensusConfig.Params))
transactionInTheMempool := createTransactionWithUTXOEntry(t, 0)
transactionInTheMempool := createTransactionWithUTXOEntry(t, 0, 0)
_, err = miningManager.ValidateAndInsertTransaction(transactionInTheMempool, false, true)
if err != nil {
t.Fatalf("ValidateAndInsertTransaction: %v", err)
}
doubleSpendTransactionInTheBlock := createTransactionWithUTXOEntry(t, 0)
doubleSpendTransactionInTheBlock := createTransactionWithUTXOEntry(t, 0, 0)
doubleSpendTransactionInTheBlock.Inputs[0].PreviousOutpoint = transactionInTheMempool.Inputs[0].PreviousOutpoint
blockTransactions := []*externalapi.DomainTransaction{nil, doubleSpendTransactionInTheBlock}
_, err = miningManager.HandleNewBlockTransactions(blockTransactions)
@ -571,7 +571,7 @@ func TestRevalidateHighPriorityTransactions(t *testing.T) {
})
}
func createTransactionWithUTXOEntry(t *testing.T, i int) *externalapi.DomainTransaction {
func createTransactionWithUTXOEntry(t *testing.T, i int, daaScore uint64) *externalapi.DomainTransaction {
prevOutTxID := externalapi.DomainTransactionID{}
prevOutPoint := externalapi.DomainOutpoint{TransactionID: prevOutTxID, Index: uint32(i)}
scriptPublicKey, redeemScript := testutils.OpTrueScript()
@ -587,7 +587,7 @@ func createTransactionWithUTXOEntry(t *testing.T, i int) *externalapi.DomainTran
100000000, // 1 KAS
scriptPublicKey,
true,
uint64(0)),
daaScore),
}
txOut := externalapi.DomainTransactionOutput{
Value: 10000,

View File

@ -29,7 +29,6 @@ import (
const (
defaultConfigFilename = "kaspad.conf"
defaultDataDirname = "data"
defaultLogLevel = "info"
defaultLogDirname = "logs"
defaultLogFilename = "kaspad.log"
@ -86,7 +85,7 @@ type Flags struct {
Listeners []string `long:"listen" description:"Add an interface/port to listen for connections (default all interfaces port: 16111, testnet: 16211)"`
TargetOutboundPeers int `long:"outpeers" description:"Target number of outbound peers"`
MaxInboundPeers int `long:"maxinpeers" description:"Max number of inbound peers"`
DisableBanning bool `long:"nobanning" description:"Disable banning of misbehaving peers"`
EnableBanning bool `long:"enablebanning" description:"Enable banning of misbehaving peers"`
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"`

View File

@ -14,7 +14,7 @@ import (
func TestGetHashrateString(t *testing.T) {
var results = map[string]string{
dagconfig.MainnetParams.Name: "131.07 KH/s",
dagconfig.MainnetParams.Name: "1.53 GH/s",
dagconfig.TestnetParams.Name: "131.07 KH/s",
dagconfig.DevnetParams.Name: "131.07 KH/s",
dagconfig.SimnetParams.Name: "2.00 KH/s",

View File

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