Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fishhash plus implementation with hard fork procedure #47

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/protocol/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
2 changes: 2 additions & 0 deletions domain/consensus/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
config.MaxBlockParents,
config.TimestampDeviationTolerance,
config.TargetTimePerBlock,
config.HFDAAScore,
config.MaxBlockLevel,

dbManager,
Expand Down Expand Up @@ -397,6 +398,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockBuilder := blockbuilder.New(
dbManager,
genesisHash,
config.HFDAAScore,

difficultyManager,
pastMedianTimeManager,
Expand Down
10 changes: 9 additions & 1 deletion domain/consensus/processes/blockbuilder/block_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
type blockBuilder struct {
databaseContext model.DBManager
genesisHash *externalapi.DomainHash
hfDAAScore uint64

difficultyManager model.DifficultyManager
pastMedianTimeManager model.PastMedianTimeManager
Expand All @@ -42,6 +43,7 @@ type blockBuilder struct {
func New(
databaseContext model.DBManager,
genesisHash *externalapi.DomainHash,
hfDAAScore uint64,

difficultyManager model.DifficultyManager,
pastMedianTimeManager model.PastMedianTimeManager,
Expand All @@ -63,6 +65,7 @@ func New(
return &blockBuilder{
databaseContext: databaseContext,
genesisHash: genesisHash,
hfDAAScore: hfDAAScore,

difficultyManager: difficultyManager,
pastMedianTimeManager: pastMedianTimeManager,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
*/
Comment on lines +62 to +67
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why this is commented? Explicit error in case an old node would send a wrong version block after hardfork is needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has been replaced by a conditional check on BlockVersionAfterHF BlockVersionBeforeHF to reject block with bad version after or before HF

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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
3 changes: 3 additions & 0 deletions domain/consensus/processes/blockvalidator/blockvalidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type blockValidator struct {
maxBlockParents externalapi.KType
timestampDeviationTolerance int
targetTimePerBlock time.Duration
hfDAAScore uint64
maxBlockLevel int

databaseContext model.DBReader
Expand Down Expand Up @@ -63,6 +64,7 @@ func New(powMax *big.Int,
maxBlockParents externalapi.KType,
timestampDeviationTolerance int,
targetTimePerBlock time.Duration,
hfDAAScore uint64,
maxBlockLevel int,

databaseContext model.DBReader,
Expand Down Expand Up @@ -102,6 +104,7 @@ func New(powMax *big.Int,
maxBlockMass: maxBlockMass,
mergeSetSizeLimit: mergeSetSizeLimit,
maxBlockParents: maxBlockParents,
hfDAAScore: hfDAAScore,
maxBlockLevel: maxBlockLevel,

timestampDeviationTolerance: timestampDeviationTolerance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion domain/consensus/utils/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
71 changes: 71 additions & 0 deletions domain/consensus/utils/pow/fishhashplus_kernel.go
Original file line number Diff line number Diff line change
@@ -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)
}
32 changes: 21 additions & 11 deletions domain/consensus/utils/pow/pow.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -23,7 +23,8 @@ type State struct {
Target big.Int
prePowHash externalapi.DomainHash
//cache cache
context fishhashContext
context fishhashContext
blockVersion uint16
}

// var context *fishhashContext
Expand Down Expand Up @@ -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(),
}
}

Expand Down Expand Up @@ -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)
}
Expand Down
3 changes: 3 additions & 0 deletions domain/dagconfig/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ type Params struct {
MaxBlockLevel int

MergeDepth uint64
HFDAAScore uint64
}

// NormalizeRPCServerAddress returns addr with the current network default
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading