diff --git a/app/protocol/manager.go b/app/protocol/manager.go index b63313bf11..895627285b 100644 --- a/app/protocol/manager.go +++ b/app/protocol/manager.go @@ -70,6 +70,9 @@ func (m *Manager) AddTransaction(tx *externalapi.DomainTransaction, allowOrphan // AddBlock adds the given block to the DAG and propagates it. func (m *Manager) AddBlock(block *externalapi.DomainBlock) error { + //TODO switch this to debug level + log.Infof("NEW BLOCK ADDED ***************************************") + log.Infof("BlueWork[%s] BlueScore[%d] DAAScore[%d] Bits[%d] Version[%d]", block.Header.BlueWork(), block.Header.BlueScore(), block.Header.DAAScore(), block.Header.Bits(), block.Header.Version()) return m.context.AddBlock(block) } diff --git a/domain/consensus/factory.go b/domain/consensus/factory.go index 25013a1c10..4c70792751 100644 --- a/domain/consensus/factory.go +++ b/domain/consensus/factory.go @@ -349,6 +349,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas config.MaxBlockParents, config.TimestampDeviationTolerance, config.TargetTimePerBlock, + config.HFDAAScore, config.MaxBlockLevel, dbManager, @@ -397,6 +398,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas blockBuilder := blockbuilder.New( dbManager, genesisHash, + config.HFDAAScore, difficultyManager, pastMedianTimeManager, diff --git a/domain/consensus/processes/blockbuilder/block_builder.go b/domain/consensus/processes/blockbuilder/block_builder.go index 14ac3583c2..d7d3bb0266 100644 --- a/domain/consensus/processes/blockbuilder/block_builder.go +++ b/domain/consensus/processes/blockbuilder/block_builder.go @@ -20,6 +20,7 @@ import ( type blockBuilder struct { databaseContext model.DBManager genesisHash *externalapi.DomainHash + hfDAAScore uint64 difficultyManager model.DifficultyManager pastMedianTimeManager model.PastMedianTimeManager @@ -42,6 +43,7 @@ type blockBuilder struct { func New( databaseContext model.DBManager, genesisHash *externalapi.DomainHash, + hfDAAScore uint64, difficultyManager model.DifficultyManager, pastMedianTimeManager model.PastMedianTimeManager, @@ -63,6 +65,7 @@ func New( return &blockBuilder{ databaseContext: databaseContext, genesisHash: genesisHash, + hfDAAScore: hfDAAScore, difficultyManager: difficultyManager, pastMedianTimeManager: pastMedianTimeManager, @@ -225,8 +228,13 @@ func (bb *blockBuilder) buildHeader(stagingArea *model.StagingArea, transactions return nil, err } + version := constants.BlockVersionBeforeHF + if daaScore >= bb.hfDAAScore { + version = constants.BlockVersionAfterHF + } + return blockheader.NewImmutableBlockHeader( - constants.BlockVersion, + version, parents, hashMerkleRoot, acceptedIDMerkleRoot, diff --git a/domain/consensus/processes/blockbuilder/test_block_builder.go b/domain/consensus/processes/blockbuilder/test_block_builder.go index 7f30e8327a..6ed180da16 100644 --- a/domain/consensus/processes/blockbuilder/test_block_builder.go +++ b/domain/consensus/processes/blockbuilder/test_block_builder.go @@ -95,9 +95,14 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingAre }) } + version := constants.BlockVersionBeforeHF + if daaScore >= bb.hfDAAScore { + version = constants.BlockVersionAfterHF + } + bb.nonceCounter++ return blockheader.NewImmutableBlockHeader( - constants.BlockVersion, + version, parents, hashMerkleRoot, &externalapi.DomainHash{}, diff --git a/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go b/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go index befb46e8f6..03f9d6bccd 100644 --- a/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go +++ b/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go @@ -1280,7 +1280,7 @@ func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consens return &externalapi.DomainBlock{ Header: blockheader.NewImmutableBlockHeader( - constants.BlockVersion, + constants.BlockVersionBeforeHF, []externalapi.BlockLevelParents{[]*externalapi.DomainHash{consensusConfig.GenesisHash}}, merkle.CalculateHashMerkleRoot([]*externalapi.DomainTransaction{tx}), &externalapi.DomainHash{}, diff --git a/domain/consensus/processes/blockvalidator/block_header_in_context_test.go b/domain/consensus/processes/blockvalidator/block_header_in_context_test.go index ff1b22e361..f2036bd202 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_context_test.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_context_test.go @@ -109,7 +109,10 @@ func TestCheckParentsIncest(t *testing.T) { t.Fatalf("AddBlock: %+v", err) } - version := constants.BlockVersion + version := constants.BlockVersionBeforeHF + if consensusConfig.HFDAAScore == 0 { + version = constants.BlockVersionAfterHF + } directParentsRelationBlock := &externalapi.DomainBlock{ Header: blockheader.NewImmutableBlockHeader( version, diff --git a/domain/consensus/processes/blockvalidator/block_header_in_isolation.go b/domain/consensus/processes/blockvalidator/block_header_in_isolation.go index f155a3ed4f..db9b4aaf4f 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_isolation.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_isolation.go @@ -59,9 +59,22 @@ func (v *blockValidator) checkParentsLimit(header externalapi.BlockHeader) error } func (v *blockValidator) checkBlockVersion(header externalapi.BlockHeader) error { - if header.Version() != constants.BlockVersion { - return errors.Wrapf( - ruleerrors.ErrWrongBlockVersion, "The block version should be %d", constants.BlockVersion) + /* + if header.Version() != constants.BlockVersion { + return errors.Wrapf( + ruleerrors.ErrWrongBlockVersion, "The block version should be %d", constants.BlockVersion) + } + */ + if header.DAAScore() >= v.hfDAAScore { + if header.Version() != constants.BlockVersionAfterHF { + return errors.Wrapf( + ruleerrors.ErrWrongBlockVersion, "After HF1 the block version should be %d", constants.BlockVersionAfterHF) + } + } else { + if header.Version() != constants.BlockVersionBeforeHF { + return errors.Wrapf( + ruleerrors.ErrWrongBlockVersion, "Beofre HF1 the block version should be %d", constants.BlockVersionBeforeHF) + } } return nil } diff --git a/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go b/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go index e85b921a6a..35ad0ac49f 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go @@ -63,7 +63,11 @@ func CheckBlockVersion(t *testing.T, tc testapi.TestConsensus, consensusConfig * t.Fatalf("BuildBlockWithParents: %+v", err) } - expectedVersion := constants.BlockVersion + expectedVersion := constants.BlockVersionBeforeHF + if consensusConfig.HFDAAScore == 0 { + expectedVersion = constants.BlockVersionAfterHF + } + block.Header = blockheader.NewImmutableBlockHeader( expectedVersion+1, block.Header.Parents(), diff --git a/domain/consensus/processes/blockvalidator/blockvalidator.go b/domain/consensus/processes/blockvalidator/blockvalidator.go index 53411a1c44..1ca4568810 100644 --- a/domain/consensus/processes/blockvalidator/blockvalidator.go +++ b/domain/consensus/processes/blockvalidator/blockvalidator.go @@ -24,6 +24,7 @@ type blockValidator struct { maxBlockParents externalapi.KType timestampDeviationTolerance int targetTimePerBlock time.Duration + hfDAAScore uint64 maxBlockLevel int databaseContext model.DBReader @@ -63,6 +64,7 @@ func New(powMax *big.Int, maxBlockParents externalapi.KType, timestampDeviationTolerance int, targetTimePerBlock time.Duration, + hfDAAScore uint64, maxBlockLevel int, databaseContext model.DBReader, @@ -102,6 +104,7 @@ func New(powMax *big.Int, maxBlockMass: maxBlockMass, mergeSetSizeLimit: mergeSetSizeLimit, maxBlockParents: maxBlockParents, + hfDAAScore: hfDAAScore, maxBlockLevel: maxBlockLevel, timestampDeviationTolerance: timestampDeviationTolerance, diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go index b78a622c10..ca238481c5 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go @@ -111,7 +111,7 @@ func TestGHOSTDAG(t *testing.T) { blockID := StringToDomainHash(testBlockData.ID) dagTopology.parentsMap[*blockID] = StringToDomainHashSlice(testBlockData.Parents) blockHeadersStore.dagMap[*blockID] = blockheader.NewImmutableBlockHeader( - constants.BlockVersion, + constants.BlockVersionBeforeHF, []externalapi.BlockLevelParents{StringToDomainHashSlice(testBlockData.Parents)}, nil, nil, diff --git a/domain/consensus/utils/constants/constants.go b/domain/consensus/utils/constants/constants.go index 57036b1f99..2f077ae8b3 100644 --- a/domain/consensus/utils/constants/constants.go +++ b/domain/consensus/utils/constants/constants.go @@ -4,7 +4,8 @@ import "math" const ( // BlockVersion represents the current block version - BlockVersion uint16 = 1 + BlockVersionBeforeHF uint16 = 1 + BlockVersionAfterHF uint16 = 2 // MaxTransactionVersion is the current latest supported transaction version. MaxTransactionVersion uint16 = 0 diff --git a/domain/consensus/utils/pow/fishhashplus_kernel.go b/domain/consensus/utils/pow/fishhashplus_kernel.go new file mode 100644 index 0000000000..e26311929d --- /dev/null +++ b/domain/consensus/utils/pow/fishhashplus_kernel.go @@ -0,0 +1,71 @@ +package pow + +import ( + "github.com/karlsen-network/karlsend/domain/consensus/model/externalapi" + + //"crypto/sha3" + "encoding/binary" +) + +func fishhashPlusKernel(ctx *fishhashContext, seed hash512) hash256 { + indexLimit := uint32(ctx.FullDatasetNumItems) + mix := mergeHashes(seed, seed) + + //log.Debugf("lookup matrix : ") + for i := uint32(0); i < numDatasetAccesses; i++ { + + mixGroup := [8]uint32{} + for c := uint32(0); c < 8; c++ { + mixGroup[c] = binary.LittleEndian.Uint32(mix[(4*4*c+0):]) ^ binary.LittleEndian.Uint32(mix[(4*4*c+4):]) ^ binary.LittleEndian.Uint32(mix[(4*4*c+8):]) ^ binary.LittleEndian.Uint32(mix[(4*4*c+12):]) + } + + p0 := (mixGroup[0] ^ mixGroup[3] ^ mixGroup[6]) % indexLimit + p1 := (mixGroup[1] ^ mixGroup[4] ^ mixGroup[7]) % indexLimit + p2 := (mixGroup[2] ^ mixGroup[5] ^ i) % indexLimit + + fetch0 := lookup(ctx, p0) + fetch1 := lookup(ctx, p1) + fetch2 := lookup(ctx, p2) + + for j := 0; j < 32; j++ { + binary.LittleEndian.PutUint32( + fetch1[4*j:], + fnv1(binary.LittleEndian.Uint32(mix[4*j:4*j+4]), binary.LittleEndian.Uint32(fetch1[4*j:4*j+4]))) + binary.LittleEndian.PutUint32( + fetch2[4*j:], + binary.LittleEndian.Uint32(mix[4*j:4*j+4])^binary.LittleEndian.Uint32(fetch2[4*j:4*j+4])) + } + + //fmt.Printf("The NEW fetch1 is : %x \n", fetch1) + //fmt.Printf("The NEW fetch2 is : %x \n", fetch2) + + for j := 0; j < 16; j++ { + binary.LittleEndian.PutUint64( + mix[8*j:], + binary.LittleEndian.Uint64(fetch0[8*j:8*j+8])*binary.LittleEndian.Uint64(fetch1[8*j:8*j+8])+binary.LittleEndian.Uint64(fetch2[8*j:8*j+8])) + } + //log.Debugf("\n") + } + + mixHash := hash256{} + for i := 0; i < (len(mix) / 4); i += 4 { + j := 4 * i + h1 := fnv1(binary.LittleEndian.Uint32(mix[j:]), binary.LittleEndian.Uint32(mix[j+4:])) + h2 := fnv1(h1, binary.LittleEndian.Uint32(mix[j+8:])) + h3 := fnv1(h2, binary.LittleEndian.Uint32(mix[j+12:])) + binary.LittleEndian.PutUint32(mixHash[i:], h3) + } + + return mixHash +} + +func fishHashPlus(ctx *fishhashContext, hashin *externalapi.DomainHash) *externalapi.DomainHash { + + seed := hash512{} + copy(seed[:], hashin.ByteSlice()) + + output := fishhashPlusKernel(ctx, seed) + outputArray := [32]byte{} + copy(outputArray[:], output[:]) + return externalapi.NewDomainHashFromByteArray(&outputArray) +} diff --git a/domain/consensus/utils/pow/pow.go b/domain/consensus/utils/pow/pow.go index 745d04d5a7..37b9276382 100644 --- a/domain/consensus/utils/pow/pow.go +++ b/domain/consensus/utils/pow/pow.go @@ -13,7 +13,7 @@ import ( "math/big" ) -const hashingAlgoVersion = "fishhash-kls-0.0.1" +const hashingAlgoVersion = "fishhash-kls-0.0.2" // State is an intermediate data structure with pre-computed values to speed up mining. type State struct { @@ -23,7 +23,8 @@ type State struct { Target big.Int prePowHash externalapi.DomainHash //cache cache - context fishhashContext + context fishhashContext + blockVersion uint16 } // var context *fishhashContext @@ -91,14 +92,17 @@ func NewState(header externalapi.MutableBlockHeader, generatedag bool) *State { header.SetTimeInMilliseconds(timestamp) header.SetNonce(nonce) + log.Debugf("BlueWork[%s] BlueScore[%d] DAAScore[%d] Version[%d]", header.BlueWork(), header.BlueScore(), header.DAAScore(), header.Version()) + return &State{ Target: *target, prePowHash: *prePowHash, //will remove matrix opow //mat: *generateMatrix(prePowHash), - Timestamp: timestamp, - Nonce: nonce, - context: *getContext(generatedag, log), + Timestamp: timestamp, + Nonce: nonce, + context: *getContext(generatedag, log), + blockVersion: header.Version(), } } @@ -132,19 +136,25 @@ func (state *State) CalculateProofOfWorkValue() *big.Int { } //log.Debugf("Hash prePowHash %x\n", state.prePowHash.ByteSlice()) //fmt.Printf("Hash prePowHash %x\n", state.prePowHash.ByteSlice()) + powHash := writer.Finalize() + //middleHash := state.mat.HeavyHash(powHash) - //log.Debugf("Hash b3-1: %x\n", powHash.ByteSlice()) - //fmt.Printf("Hash b3-1: %x\n", powHash.ByteSlice()) - middleHash := fishHash(&state.context, powHash) - //log.Debugf("Hash fish: %x\n", middleHash.ByteSlice()) - //fmt.Printf("Hash fish: %x\n", middleHash.ByteSlice()) + //log.Infof("Hash b3-1: %x", powHash.ByteSlice()) + middleHash := powHash + if state.blockVersion == 1 { + middleHash = fishHash(&state.context, powHash) + } else { + middleHash = fishHashPlus(&state.context, powHash) + } + + //log.Infof("Hash fish: %x", middleHash.ByteSlice()) writer2 := hashes.NewPoWHashWriter() writer2.InfallibleWrite(middleHash.ByteSlice()) finalHash := writer2.Finalize() - //log.Debugf("Hash b3-2: %x\n", finalHash.ByteSlice()) + //log.Infof("Hash b3-2: %x", finalHash.ByteSlice()) return toBig(finalHash) } diff --git a/domain/dagconfig/params.go b/domain/dagconfig/params.go index f86014f3fb..d10da45664 100644 --- a/domain/dagconfig/params.go +++ b/domain/dagconfig/params.go @@ -188,6 +188,7 @@ type Params struct { MaxBlockLevel int MergeDepth uint64 + HFDAAScore uint64 } // NormalizeRPCServerAddress returns addr with the current network default @@ -341,6 +342,8 @@ var TestnetParams = Params{ MaxBlockLevel: 250, MergeDepth: defaultMergeDepth, + // todo: define the fork date DAAscore + HFDAAScore: 6000000, } // SimnetParams defines the network parameters for the simulation test Kaspa diff --git a/version/version.go b/version/version.go index 5a73b8071e..17d3e7d0d6 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs const ( appMajor uint = 2 appMinor uint = 0 - appPatch uint = 0 + appPatch uint = 1 ) // appBuild is defined as a variable so it can be overridden during the build