diff --git a/.gitignore b/.gitignore
index 1ee8b83022ef..11007c3b3c35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,4 @@ profile.cov
/dashboard/assets/package-lock.json
**/yarn-error.log
+beta-data/
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 25e361b9c0eb..874b4e88f1c0 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -166,6 +166,10 @@ var (
Name: "mio",
Usage: "Mio network: Error-Correction Codes Proof-of-Work Test Network",
}
+ BetaFlag = &cli.BoolFlag{
+ Name: "beta",
+ Usage: "Beta network: ECCBeta Proof-of-Work Network",
+ }
// Dev mode
DeveloperFlag = &cli.BoolFlag{
@@ -1002,6 +1006,7 @@ var (
KilnFlag,*/
GwangjuFlag,
MioFlag,
+ BetaFlag,
}
// NetworkFlags is the flag group of all built-in supported networks.
NetworkFlags = append([]cli.Flag{
@@ -1048,6 +1053,9 @@ func MakeDataDir(ctx *cli.Context) string {
if ctx.Bool(MioFlag.Name) {
return filepath.Join(path, "mio")
}
+ if ctx.Bool(BetaFlag.Name) {
+ return filepath.Join(path, "beta")
+ }
return path
}
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
@@ -1110,7 +1118,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls = params.GwangjuBootnodes
case ctx.Bool(MioFlag.Name):
urls = params.MioBootnodes
-
+ case ctx.Bool(BetaFlag.Name):
+ urls = params.BetaBootnodes
}
// don't apply defaults if BootstrapNodes is already set
@@ -1575,6 +1584,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "gwangju")
case ctx.Bool(MioFlag.Name) && cfg.DataDir == node.DefaultDataDir():
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "mio")
+ case ctx.Bool(BetaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
+ cfg.DataDir = filepath.Join(node.DefaultDataDir(), "beta")
}
}
@@ -1968,6 +1979,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.Genesis = core.DefaultMioGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.MioGenesisHash)
+ case ctx.Bool(BetaFlag.Name):
+ if !ctx.IsSet(NetworkIdFlag.Name) {
+ cfg.NetworkId = 91510
+ }
+ cfg.Genesis = core.DefaultBetaGenesisBlock()
+ SetDNSDiscoveryDefaults(cfg, params.BetaGenesisHash)
+
case ctx.Bool(DeveloperFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337
@@ -2225,6 +2243,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
genesis = core.DefaultGwangjuGenesisBlock()
case ctx.Bool(MioFlag.Name):
genesis = core.DefaultMioGenesisBlock()
+ case ctx.Bool(BetaFlag.Name):
+ genesis = core.DefaultBetaGenesisBlock()
case ctx.Bool(DeveloperFlag.Name):
Fatalf("Developer chains are ephemeral")
}
@@ -2249,13 +2269,17 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (*core.BlockChain, ethdb.Data
if err != nil {
Fatalf("%v", err)
}
+ eccbetaConfig, err := core.LoadEccbetaConfig(chainDb, gspec)
+ if err != nil {
+ Fatalf("%v", err)
+ }
ethashConfig := ethconfig.Defaults.Ethash
if ctx.Bool(FakePoWFlag.Name) {
ethashConfig.PowMode = ethash.ModeFake
}
- engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, eccpowConfig, kaijuConfig, nil, false, chainDb)
+ engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, eccpowConfig, kaijuConfig, eccbetaConfig, nil, false, chainDb)
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
diff --git a/cmd/worldland/main.go b/cmd/worldland/main.go
index ae4f50c441a5..739d67d9dc40 100644
--- a/cmd/worldland/main.go
+++ b/cmd/worldland/main.go
@@ -299,6 +299,9 @@ func prepare(ctx *cli.Context) {
case ctx.IsSet(utils.MioFlag.Name):
log.Info("Starting Worldland on Mio testnet ...")
+ case ctx.IsSet(utils.BetaFlag.Name):
+ log.Info("Starting Worldland on Beta network ...")
+
case ctx.IsSet(utils.DeveloperFlag.Name):
log.Info("Starting Worldland in ephemeral dev mode...")
log.Warn(`You are running Worldland in --dev mode. Please note the following:
diff --git a/consensus/eccbeta/LDPCDecoder.go b/consensus/eccbeta/LDPCDecoder.go
new file mode 100644
index 000000000000..604b3ad8e06d
--- /dev/null
+++ b/consensus/eccbeta/LDPCDecoder.go
@@ -0,0 +1,210 @@
+package eccbeta
+
+import (
+ "encoding/binary"
+ "math"
+
+ "github.com/cryptoecc/WorldLand/core/types"
+ "github.com/cryptoecc/WorldLand/crypto"
+)
+
+//OptimizedDecoding return hashVector, outputWord, LRrtl
+func OptimizedDecoding(parameters Parameters, hashVector []int, H, rowInCol, colInRow [][]int) ([]int, []int, [][]float64) {
+ outputWord := make([]int, parameters.n)
+ LRqtl := make([][]float64, parameters.n)
+ LRrtl := make([][]float64, parameters.n)
+ LRft := make([]float64, parameters.n)
+
+ for i := 0; i < parameters.n; i++ {
+ LRqtl[i] = make([]float64, parameters.m)
+ LRrtl[i] = make([]float64, parameters.m)
+ LRft[i] = math.Log((1-crossErr)/crossErr) * float64((hashVector[i]*2 - 1))
+ }
+ LRpt := make([]float64, parameters.n)
+
+ for ind := 1; ind <= maxIter; ind++ {
+ for t := 0; t < parameters.n; t++ {
+ temp3 := 0.0
+
+ for mp := 0; mp < parameters.wc; mp++ {
+ temp3 = infinityTest(temp3 + LRrtl[t][rowInCol[mp][t]])
+ }
+ for m := 0; m < parameters.wc; m++ {
+ temp4 := temp3
+ temp4 = infinityTest(temp4 - LRrtl[t][rowInCol[m][t]])
+ LRqtl[t][rowInCol[m][t]] = infinityTest(LRft[t] + temp4)
+ }
+ }
+
+ for k := 0; k < parameters.wr; k++ {
+ for l := 0; l < parameters.wr; l++ {
+ temp3 := 0.0
+ sign := 1.0
+ tempSign := 0.0
+ for m := 0; m < parameters.wr; m++ {
+ if m != l {
+ temp3 = temp3 + funcF(math.Abs(LRqtl[colInRow[m][k]][k]))
+ if LRqtl[colInRow[m][k]][k] > 0.0 {
+ tempSign = 1.0
+ } else {
+ tempSign = -1.0
+ }
+ sign = sign * tempSign
+ }
+ }
+ magnitude := funcF(temp3)
+ LRrtl[colInRow[l][k]][k] = infinityTest(sign * magnitude)
+ }
+ }
+
+ for t := 0; t < parameters.n; t++ {
+ LRpt[t] = infinityTest(LRft[t])
+ for k := 0; k < parameters.wc; k++ {
+ LRpt[t] += LRrtl[t][rowInCol[k][t]]
+ LRpt[t] = infinityTest(LRpt[t])
+ }
+
+ /*
+ if LRpt[t] >= 0 {
+ outputWord[t] = 1
+ } else {
+ outputWord[t] = 0
+ }*/
+ }
+ }
+
+ for t := 0; t < parameters.n; t++ {
+ if LRpt[t] >= 0 {
+ outputWord[t] = 1
+ } else {
+ outputWord[t] = 0
+ }
+ }
+
+ return hashVector, outputWord, LRrtl
+}
+
+//OptimizedDecoding return hashVector, outputWord, LRrtl
+func OptimizedDecodingSeoul(parameters Parameters, hashVector []int, H, rowInCol, colInRow [][]int) ([]int, []int, [][]float64) {
+ outputWord := make([]int, parameters.n)
+ LRqtl := make([][]float64, parameters.n)
+ LRrtl := make([][]float64, parameters.n)
+ LRft := make([]float64, parameters.n)
+
+ for i := 0; i < parameters.n; i++ {
+ LRqtl[i] = make([]float64, parameters.m)
+ LRrtl[i] = make([]float64, parameters.m)
+ LRft[i] = math.Log((1-crossErr)/crossErr) * float64((hashVector[i]*2 - 1))
+ }
+ LRpt := make([]float64, parameters.n)
+
+ for ind := 1; ind <= maxIter; ind++ {
+ for t := 0; t < parameters.n; t++ {
+ temp3 := 0.0
+
+ for mp := 0; mp < parameters.wc; mp++ {
+ temp3 = infinityTest(temp3 + LRrtl[t][rowInCol[mp][t]])
+ }
+ for m := 0; m < parameters.wc; m++ {
+ temp4 := temp3
+ temp4 = infinityTest(temp4 - LRrtl[t][rowInCol[m][t]])
+ LRqtl[t][rowInCol[m][t]] = infinityTest(LRft[t] + temp4)
+ }
+ }
+
+ for k := 0; k < parameters.m; k++ {
+ for l := 0; l < parameters.wr; l++ {
+ temp3 := 0.0
+ sign := 1.0
+ tempSign := 0.0
+ for m := 0; m < parameters.wr; m++ {
+ if m != l {
+ temp3 = temp3 + funcF(math.Abs(LRqtl[colInRow[m][k]][k]))
+ if LRqtl[colInRow[m][k]][k] > 0.0 {
+ tempSign = 1.0
+ } else {
+ tempSign = -1.0
+ }
+ sign = sign * tempSign
+ }
+ }
+ magnitude := funcF(temp3)
+ LRrtl[colInRow[l][k]][k] = infinityTest(sign * magnitude)
+ }
+ }
+
+ for t := 0; t < parameters.n; t++ {
+ LRpt[t] = infinityTest(LRft[t])
+ for k := 0; k < parameters.wc; k++ {
+ LRpt[t] += LRrtl[t][rowInCol[k][t]]
+ LRpt[t] = infinityTest(LRpt[t])
+ }
+
+
+ if LRpt[t] >= 0 {
+ outputWord[t] = 1
+ } else {
+ outputWord[t] = 0
+ }
+ }
+ }
+ /*
+ for t := 0; t < parameters.n; t++ {
+ if LRpt[t] >= 0 {
+ outputWord[t] = 1
+ } else {
+ outputWord[t] = 0
+ }
+ }*/
+
+ return hashVector, outputWord, LRrtl
+}
+
+
+//VerifyOptimizedDecoding return bool, hashVector, outputword, digest which are used for validation
+func VerifyOptimizedDecoding(header *types.Header, hash []byte) (bool, []int, []int, []byte) {
+ parameters, _ := setParameters(header)
+ H := generateH(parameters)
+ colInRow, rowInCol := generateQ(parameters, H)
+
+ seed := make([]byte, 40)
+ copy(seed, hash)
+ binary.LittleEndian.PutUint64(seed[32:], header.Nonce.Uint64())
+ seed = crypto.Keccak512(seed)
+
+ hashVector := generateHv(parameters, seed)
+ hashVectorOfVerification, outputWordOfVerification, _ := OptimizedDecoding(parameters, hashVector, H, rowInCol, colInRow)
+ //hashVectorOfVerification, outputWordOfVerification, _ := OptimizedDecodingSeoul(parameters, hashVector, H, rowInCol, colInRow)
+
+ flag , _ := MakeDecision(header, colInRow, outputWordOfVerification)
+
+ if flag {
+ return true, hashVectorOfVerification, outputWordOfVerification, seed
+ }
+
+ return false, hashVectorOfVerification, outputWordOfVerification, seed
+}
+
+//VerifyOptimizedDecoding return bool, hashVector, outputword, digest which are used for validation
+func VerifyOptimizedDecodingSeoul(header *types.Header, hash []byte) (bool, []int, []int, []byte) {
+ parameters, _ := setParameters_Seoul(header)
+ H := generateH(parameters)
+ colInRow, rowInCol := generateQ(parameters, H)
+
+ seed := make([]byte, 40)
+ copy(seed, hash)
+ binary.LittleEndian.PutUint64(seed[32:], header.Nonce.Uint64())
+ seed = crypto.Keccak512(seed)
+
+ hashVector := generateHv(parameters, seed)
+ //hashVectorOfVerification, outputWordOfVerification, _ := OptimizedDecoding(parameters, hashVector, H, rowInCol, colInRow)
+ hashVectorOfVerification, outputWordOfVerification, _ := OptimizedDecodingSeoul(parameters, hashVector, H, rowInCol, colInRow)
+
+ flag , _ := MakeDecision_Seoul(header, colInRow, outputWordOfVerification)
+
+ if flag {
+ return true, hashVectorOfVerification, outputWordOfVerification, seed
+ }
+
+ return false, hashVectorOfVerification, outputWordOfVerification, seed
+}
diff --git a/consensus/eccbeta/LDPCDecoder_test.go b/consensus/eccbeta/LDPCDecoder_test.go
new file mode 100644
index 000000000000..99b36d826040
--- /dev/null
+++ b/consensus/eccbeta/LDPCDecoder_test.go
@@ -0,0 +1,79 @@
+package eccbeta
+
+import (
+ "math/rand"
+ "reflect"
+ "testing"
+
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+func TestNonceDecoding(t *testing.T) {
+ LDPCNonce := generateRandomNonce()
+ EncodedNonce := types.EncodeNonce(LDPCNonce)
+ DecodedNonce := EncodedNonce.Uint64()
+
+ if LDPCNonce == DecodedNonce {
+ t.Logf("LDPCNonce : %v\n", LDPCNonce)
+ t.Logf("Decoded Nonce : %v\n", DecodedNonce)
+ } else {
+ t.Errorf("LDPCNonce : %v\n", LDPCNonce)
+ t.Errorf("Decoded Nonce : %v\n", DecodedNonce)
+ }
+}
+
+func TestGenerateH(t *testing.T) {
+ for i := 0; i < 10; i++ {
+ header := new(types.Header)
+ header.Difficulty = ProbToDifficulty(Table[0].miningProb)
+
+ parameters, _ := setParameters(header)
+
+ H1 := generateH(parameters)
+ H2 := generateH(parameters)
+
+ if !reflect.DeepEqual(H1, H2) {
+ t.Error("Wrong")
+ }
+ }
+}
+
+func TestRandShuffle(t *testing.T) {
+ for attempt := 0; attempt < 100; attempt++ {
+ var hSeed int64
+ var colOrder []int
+
+ for i := 1; i < 4; i++ {
+ colOrder = nil
+ for j := 0; j < 32; j++ {
+ colOrder = append(colOrder, j)
+ }
+
+ rand.Seed(hSeed)
+ rand.Shuffle(len(colOrder), func(i, j int) {
+ colOrder[i], colOrder[j] = colOrder[j], colOrder[i]
+ })
+ hSeed--
+ }
+
+ var hSeed2 int64
+ var colOrder2 []int
+
+ for i := 1; i < 4; i++ {
+ colOrder2 = nil
+ for j := 0; j < 32; j++ {
+ colOrder2 = append(colOrder2, j)
+ }
+
+ rand.Seed(hSeed2)
+ rand.Shuffle(len(colOrder2), func(i, j int) {
+ colOrder2[i], colOrder2[j] = colOrder2[j], colOrder2[i]
+ })
+ hSeed2--
+ }
+
+ if !reflect.DeepEqual(colOrder, colOrder2) {
+ t.Error("Wrong")
+ }
+ }
+}
diff --git a/consensus/eccbeta/LDPCDifficulty.go b/consensus/eccbeta/LDPCDifficulty.go
new file mode 100644
index 000000000000..3b20bb2f8d43
--- /dev/null
+++ b/consensus/eccbeta/LDPCDifficulty.go
@@ -0,0 +1,262 @@
+package eccbeta
+
+import (
+ "math"
+ "math/big"
+
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+/*
+ https://ethereum.stackexchange.com/questions/5913/how-does-the-ethereum-homestead-difficulty-adjustment-algorithm-work?noredirect=1&lq=1
+ https://github.com/ethereum/EIPs/issues/100
+
+ Ethereum difficulty adjustment
+ algorithm:
+ diff = (parent_diff +
+ (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99))
+ ) + 2^(periodCount - 2)
+
+ LDPC difficulty adjustment
+ algorithm:
+ diff = (parent_diff +
+ (parent_diff / 256 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // BlockGenerationTime), -99)))
+
+ Why 8?
+ This number is sensitivity of blockgeneration time
+ If this number is high, difficulty is not changed much when block generation time is different from goal of block generation time
+ But if this number is low, difficulty is changed much when block generatin time is different from goal of block generation time
+
+*/
+
+// "github.com/cryptoecc/WorldLand/consensus/ethash/consensus.go"
+// Some weird constants to avoid constant memory allocs for them.
+var (
+ MinimumDifficulty = ProbToDifficulty(Table[0].miningProb)
+ BlockGenerationTime = big.NewInt(36) // 36) // 10 ) // 36)
+ Sensitivity = big.NewInt(8)
+ SensitivityAnnapurna = big.NewInt(1024)
+ threshold = big.NewInt(7)
+
+ // BlockGenerationTime for Seoul
+ BlockGenerationTimeSeoul = big.NewInt(10) // 36) // 10 ) // 36)
+ SeoulDifficulty = big.NewInt(1023)
+
+ //initLevel int = 10
+ minLevel int = 10
+ diff_interval = 100
+
+ //count int = -1
+ //init_c int = 2
+)
+
+const (
+ // frontierDurationLimit is for Frontier:
+ // The decision boundary on the blocktime duration used to determine
+ // whether difficulty should go up or down.
+ frontierDurationLimit = 10
+ // minimumDifficulty The minimum that the difficulty may ever be.
+ minimumDifficulty = 131072
+ // expDiffPeriod is the exponential difficulty period
+ expDiffPeriodUint = 100000
+ // difficultyBoundDivisorBitShift is the bound divisor of the difficulty (2048),
+ // This constant is the right-shifts to use for the division.
+ difficultyBoundDivisor = 11
+)
+
+// MakeLDPCDifficultyCalculator calculate difficulty using difficulty table
+func MakeLDPCDifficultyCalculator() func(time uint64, parent *types.Header) *big.Int {
+ return func(time uint64, parent *types.Header) *big.Int {
+ bigTime := new(big.Int).SetUint64(time)
+ bigParentTime := new(big.Int).SetUint64(parent.Time)
+
+ // holds intermediate values to make the algo easier to read & audit
+ x := new(big.Int)
+ y := new(big.Int)
+
+ // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // BlockGenerationTime
+ x.Sub(bigTime, bigParentTime)
+ //fmt.Printf("block_timestamp - parent_timestamp : %v\n", x)
+
+ x.Div(x, BlockGenerationTime)
+ //fmt.Printf("(block_timestamp - parent_timestamp) / BlockGenerationTime : %v\n", x)
+
+ if parent.UncleHash == types.EmptyUncleHash {
+ //fmt.Printf("No uncle\n")
+ x.Sub(big1, x)
+ } else {
+ //fmt.Printf("Uncle block exists")
+ x.Sub(big2, x)
+ }
+ //fmt.Printf("(2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) / BlockGenerationTime : %v\n", x)
+
+ // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99)
+ if x.Cmp(bigMinus99) < 0 {
+ x.Set(bigMinus99)
+ }
+ //fmt.Printf("max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ // parent_diff + (parent_diff / Sensitivity * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // BlockGenerationTime), -99))
+ y.Div(parent.Difficulty, Sensitivity)
+ //fmt.Printf("parent.Difficulty / 8 : %v\n", y)
+
+ x.Mul(y, x)
+ //fmt.Printf("parent.Difficulty / 8 * max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ x.Add(parent.Difficulty, x)
+ //fmt.Printf("parent.Difficulty - parent.Difficulty / 8 * max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ // minimum difficulty can ever be (before exponential factor)
+ if x.Cmp(MinimumDifficulty) < 0 {
+ x.Set(MinimumDifficulty)
+ }
+
+ //fmt.Printf("x : %v, Minimum difficulty : %v\n", x, MinimumDifficulty)
+ return x
+ }
+}
+
+func MakeLDPCDifficultyCalculator_Seoul() func(time uint64, parent *types.Header) *big.Int {
+ return func(time uint64, parent *types.Header) *big.Int {
+ bigTime := new(big.Int).SetUint64(time)
+ bigParentTime := new(big.Int).SetUint64(parent.Time)
+
+ // holds intermediate values to make the algo easier to read & audit
+ x := new(big.Int)
+ y := new(big.Int)
+
+ // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // BlockGenerationTime
+ x.Sub(bigTime, bigParentTime)
+ //fmt.Printf("block_timestamp - parent_timestamp : %v\n", x)
+
+ x.Div(x, BlockGenerationTimeSeoul)
+ //fmt.Printf("(block_timestamp - parent_timestamp) / BlockGenerationTime : %v\n", x)
+
+ if parent.UncleHash == types.EmptyUncleHash {
+ //fmt.Printf("No uncle\n")
+ x.Sub(big1, x)
+ } else {
+ //fmt.Printf("Uncle block exists")
+ x.Sub(big2, x)
+ }
+ //fmt.Printf("(2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) / BlockGenerationTime : %v\n", x)
+
+ // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99)
+ if x.Cmp(bigMinus99) < 0 {
+ x.Set(bigMinus99)
+ }
+ //fmt.Printf("max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ // parent_diff + (parent_diff / Sensitivity * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // BlockGenerationTime), -99))
+ y.Div(parent.Difficulty, Sensitivity)
+ //fmt.Printf("parent.Difficulty / 8 : %v\n", y)
+
+ x.Mul(y, x)
+ //fmt.Printf("parent.Difficulty / 8 * max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ x.Add(parent.Difficulty, x)
+ //fmt.Printf("parent.Difficulty - parent.Difficulty / 8 * max(1 - (block_timestamp - parent_timestamp) / BlockGenerationTime, -99) : %v\n", x)
+
+ // minimum difficulty can ever be (before exponential factor)
+ if x.Cmp(SeoulDifficulty) < 0 {
+ x.Set(SeoulDifficulty)
+ }
+
+ //fmt.Printf("x : %v, Minimum difficulty : %v\n", x, MinimumDifficulty)
+ return x
+ }
+}
+
+func MakeLDPCDifficultyCalculatorAnnapurna() func(time uint64, parent *types.Header) *big.Int {
+ return func(time uint64, parent *types.Header) *big.Int {
+ bigTime := new(big.Int).SetUint64(time)
+ bigParentTime := new(big.Int).SetUint64(parent.Time)
+
+ // holds intermediate values to make the algo easier to read & audit
+ x := new(big.Int)
+ y := new(big.Int)
+
+ // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // BlockGenerationTime
+ x.Sub(bigTime, bigParentTime)
+ //fmt.Printf("block_timestamp - parent_timestamp : %v\n", x)
+
+ x.Div(x, threshold)
+ //fmt.Printf("(block_timestamp - parent_timestamp) // 7 : %v\n", x)
+
+ if parent.UncleHash == types.EmptyUncleHash {
+ //fmt.Printf("No uncle\n")
+ x.Sub(big1, x)
+ } else {
+ //fmt.Printf("Uncle block exists")
+ x.Sub(big2, x)
+ }
+ //fmt.Printf("(2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 7 : %v\n", x)
+
+ // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 7, -99)
+ if x.Cmp(bigMinus99) < 0 {
+ x.Set(bigMinus99)
+ }
+ //fmt.Printf("max(1 - (block_timestamp - parent_timestamp) / 7, -99) : %v\n", x)
+
+ // parent_diff + (parent_diff / Sensitivity * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 7), -99))
+ y.Div(parent.Difficulty, SensitivityAnnapurna)
+ //fmt.Printf("parent.Difficulty / 1024 : %v\n", y)
+
+ x.Mul(y, x)
+ //fmt.Printf("parent.Difficulty / 1024 * max(1 - (block_timestamp - parent_timestamp) // 7, -99) : %v\n", x)
+
+ x.Add(parent.Difficulty, x)
+ //fmt.Printf("parent.Difficulty - parent.Difficulty / 8 * max(1 - (block_timestamp - parent_timestamp) // 7, -99) : %v\n", x)
+
+ // minimum difficulty can ever be (before exponential factor)
+ if x.Cmp(SeoulDifficulty) < 0 {
+ x.Set(SeoulDifficulty)
+ }
+
+ //fmt.Printf("x : %v, Minimum difficulty : %v\n", x, MinimumDifficulty)
+ return x
+ }
+}
+
+// SearchLevel return next level by using currentDifficulty of header
+// Type of Ethereum difficulty is *bit.Int so arg is *big.int
+func SearchLevel(difficulty *big.Int) int {
+ // foo := MakeLDPCDifficultyCalculator()
+ // Next level := SearchNextLevel(foo(currentBlock's time stamp, parentBlock))
+
+ var currentProb = DifficultyToProb(difficulty)
+ var level int
+
+ distance := 1.0
+ for i := range Table {
+ if math.Abs(currentProb-Table[i].miningProb) <= distance {
+ level = Table[i].level
+ distance = math.Abs(currentProb - Table[i].miningProb)
+ } else {
+ break
+ }
+ }
+
+ return level
+}
+
+// SearchLevel return next level by using currentDifficulty of header
+// Type of Ethereum difficulty is *bit.Int so arg is *big.int
+func SearchLevel_Seoul(difficulty *big.Int) int {
+
+ var level int
+
+ difficultyf := new(big.Rat).SetInt(difficulty)
+ level_prob := big.NewRat(29, 20)
+ difficultyf.Quo(difficultyf, new(big.Rat).SetInt(SeoulDifficulty))
+
+ for {
+ difficultyf.Quo(difficultyf, level_prob)
+ level++
+ if difficultyf.Cmp(big.NewRat(1, 1)) < 0 {
+ break
+ }
+ }
+
+ return level
+}
diff --git a/consensus/eccbeta/LDPCDifficulty_test.go b/consensus/eccbeta/LDPCDifficulty_test.go
new file mode 100644
index 000000000000..358c64a97199
--- /dev/null
+++ b/consensus/eccbeta/LDPCDifficulty_test.go
@@ -0,0 +1,65 @@
+package eccbeta
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+func TestTablePrint(t *testing.T) {
+ for i := range Table {
+ fmt.Printf("level : %v, n : %v, wc : %v, wr : %v, decisionFrom : %v, decisionTo : %v, decisionStep : %v, miningProb : %v \n", Table[i].level, Table[i].n, Table[i].wc, Table[i].wr, Table[i].decisionFrom, Table[i].decisionTo, Table[i].decisionStep, Table[i].miningProb)
+ }
+}
+
+func TestPrintReciprocal(t *testing.T) {
+ for i := range Table {
+ val := 1 / Table[i].miningProb
+ bigInt := FloatToBigInt(val)
+ fmt.Printf("Reciprocal of miningProb : %v \t big Int : %v\n", val, bigInt)
+ }
+}
+
+func TestConversionFunc(t *testing.T) {
+ for i := range Table {
+ difficulty := ProbToDifficulty(Table[i].miningProb)
+ miningProb := DifficultyToProb(difficulty)
+
+ // Consider only integer part.
+ fmt.Printf("Difficulty : %v \t MiningProb : %v\t, probability compare : %v \n", difficulty, miningProb, math.Abs(miningProb-Table[i].miningProb) < 1)
+ }
+}
+
+func TestDifficultyChange(t *testing.T) {
+ var hash []byte
+ currentLevel := 0
+ currentBlock := new(types.Header)
+ // Parent block's timestamp is 0
+ // compare elapse time(timestamp) and parent block's timestamp(0)
+ currentBlock.Difficulty = big.NewInt(0)
+ currentBlock.Time = 0
+ currentBlock.UncleHash = types.EmptyUncleHash
+ for i := 0; i < 5; i++ {
+ fmt.Printf("Current Difficulty : %v\n", currentBlock.Difficulty)
+
+ startTime := time.Now()
+
+ RunOptimizedConcurrencyLDPC(currentBlock, hash)
+ timeStamp := uint64(time.Since(startTime).Seconds())
+ fmt.Printf("Block generation time : %v\n", timeStamp)
+
+ difficultyCalculator := MakeLDPCDifficultyCalculator()
+ nextDifficulty := difficultyCalculator(timeStamp, currentBlock)
+ currentBlock.Difficulty = nextDifficulty
+ nextLevel := SearchLevel(nextDifficulty)
+
+ fmt.Printf("Current prob : %v, Next Level : %v, Next difficulty : %v, Next difficulty from table : %v\n\n", Table[currentLevel].miningProb, Table[nextLevel].level, nextDifficulty, ProbToDifficulty(Table[nextLevel].miningProb))
+ // currentBlock.ParentHash = outputWord conversion from []int to [32]byte
+ currentLevel = nextLevel
+ fmt.Printf("Current Level : %v\n", currentLevel)
+ }
+}
diff --git a/consensus/eccbeta/LDPCDifficulty_utils.go b/consensus/eccbeta/LDPCDifficulty_utils.go
new file mode 100644
index 000000000000..daa434cde0c8
--- /dev/null
+++ b/consensus/eccbeta/LDPCDifficulty_utils.go
@@ -0,0 +1,518 @@
+package eccbeta
+
+import (
+ "math/big"
+)
+
+// Table : level, n, wc, wr, decisionFrom, decisionTo, decisionStep, _, miningProb
+/*
+ How to decision
+ 1. The number of ones in outputword % decision_step == 0
+ 2. The number of ones in outputword exists between decision_from to decision_to
+
+ How to change difficulty level
+ - Reciprocal of difficulty is probability
+ - Therefore We can define difficulty is reciprocal of probability
+ - Find close probability
+
+*/
+type difficulty struct {
+ level int
+ n int
+ wc int
+ wr int
+ decisionFrom int
+ decisionTo int
+ decisionStep int
+ _ float32
+ miningProb float64
+}
+
+// FloatToBigInt convert float64 to big integer
+func FloatToBigInt(val float64) *big.Int {
+ // float64 -> bit float -> big int
+ bigFloat := big.NewFloat(val)
+ bigInt := new(big.Int)
+ bigFloat.Int(bigInt)
+
+ return bigInt
+}
+
+// BigIntToFloat convert big int to float64
+func BigIntToFloat(val *big.Int) float64 {
+ // big int -> bit float -> float64
+ bigFloat := new(big.Float).SetInt(val)
+ floatVal, _ := bigFloat.Float64()
+
+ return floatVal
+}
+
+// DifficultyToProb convert difficulty to probability of table
+func DifficultyToProb(difficulty *big.Int) float64 {
+ //big Int -> 1/bigInt -> float64
+ prob := 1 / BigIntToFloat(difficulty)
+ return prob
+}
+
+// ProbToDifficulty convert probability to difficulty of header
+func ProbToDifficulty(miningProb float64) *big.Int {
+ // float64 -> 1/float64 -> big Int
+ difficulty := FloatToBigInt(1 / miningProb)
+ return difficulty
+}
+
+
+func getTable(level int ) difficulty {
+ n := 64 + level * 4
+ return difficulty{level, n, 3, 4, 1/4 * n, 3/4 * n, 1, 0, 0}
+}
+
+
+// Table is difficulty table slice
+var Table = []difficulty{
+ {0, 32, 3, 4, 10, 22, 2, 0.329111, 3.077970e-05},
+ {1, 32, 3, 4, 10, 22, 2, 0.329111, 3.077970e-05},
+ {2, 32, 3, 4, 10, 16, 2, 0.329111, 2.023220e-05},
+ {3, 32, 3, 4, 16, 16, 1, 0.329111, 9.684650e-06},
+ {4, 32, 3, 4, 14, 14, 1, 0.329111, 6.784080e-06},
+ {5, 36, 3, 4, 12, 24, 2, 0.329111, 4.830240e-06},
+ {6, 36, 3, 4, 12, 18, 2, 0.369449, 3.125970e-06},
+ {7, 32, 3, 4, 12, 12, 1, 0.369449, 2.862890e-06},
+ {8, 44, 3, 4, 14, 30, 2, 0.369449, 1.637790e-06},
+ {9, 36, 3, 4, 18, 18, 1, 0.369449, 1.421700e-06},
+ {10, 36, 3, 4, 16, 16, 1, 0.369449, 1.051350e-06},
+ {11, 44, 3, 4, 14, 22, 2, 0.411046, 1.029740e-06},
+ {12, 40, 3, 4, 12, 28, 2, 0.411046, 7.570880e-07},
+ {13, 36, 3, 4, 14, 14, 1, 0.411046, 4.865630e-07},
+ {14, 40, 3, 4, 12, 20, 2, 0.411046, 4.813320e-07},
+ {15, 44, 3, 4, 22, 22, 1, 0.411046, 4.216920e-07},
+ {16, 44, 3, 4, 20, 20, 1, 0.411046, 3.350070e-07},
+ {17, 48, 3, 4, 14, 34, 2, 0.452453, 2.677070e-07},
+ {18, 40, 3, 4, 20, 20, 1, 0.452453, 2.055750e-07},
+ {19, 44, 3, 4, 18, 18, 1, 0.452453, 1.788400e-07},
+ {20, 48, 3, 4, 14, 24, 2, 0.452453, 1.664080e-07},
+ {21, 40, 3, 4, 18, 18, 1, 0.452453, 1.583110e-07},
+ {22, 40, 3, 4, 16, 16, 1, 0.452453, 7.917230e-08},
+ {23, 44, 3, 4, 16, 16, 1, 0.498513, 7.103820e-08},
+ {24, 48, 3, 4, 24, 24, 1, 0.498513, 6.510890e-08},
+ {25, 48, 3, 4, 22, 22, 1, 0.498513, 5.300760e-08},
+ {26, 52, 3, 4, 14, 40, 2, 0.498513, 4.266600e-08},
+ {27, 48, 3, 4, 20, 20, 1, 0.498513, 2.990510e-08},
+ {28, 40, 3, 4, 14, 14, 1, 0.498513, 2.927380e-08},
+ {29, 52, 3, 4, 14, 26, 2, 0.498513, 2.626790e-08},
+ {30, 60, 3, 4, 18, 42, 2, 0.498513, 1.485240e-08},
+ {31, 48, 3, 4, 18, 18, 1, 0.546238, 1.267290e-08},
+ {32, 52, 3, 4, 26, 26, 1, 0.546238, 9.891110e-09},
+ {33, 60, 3, 4, 18, 30, 2, 0.546238, 9.019200e-09},
+ {34, 48, 3, 4, 16, 32, 1, 0.546238, 8.762650e-09},
+ {35, 52, 3, 4, 24, 24, 1, 0.546238, 8.213140e-09},
+ {36, 56, 3, 4, 16, 42, 2, 0.546238, 6.658250e-09},
+ {37, 52, 3, 4, 22, 22, 1, 0.546238, 4.856960e-09},
+ {38, 48, 3, 4, 16, 16, 1, 0.546238, 4.381330e-09},
+ {39, 56, 3, 4, 16, 28, 2, 0.546238, 4.068000e-09},
+ {40, 60, 3, 4, 30, 30, 1, 0.546238, 3.186040e-09},
+ {41, 60, 3, 4, 28, 28, 1, 0.578290, 2.725470e-09},
+ {42, 64, 3, 4, 18, 46, 2, 0.578290, 2.410890e-09},
+ {43, 52, 3, 4, 20, 20, 1, 0.578290, 2.181360e-09},
+ {44, 60, 3, 4, 26, 26, 1, 0.578290, 1.737940e-09},
+ {45, 52, 3, 4, 18, 34, 1, 0.578290, 1.595330e-09},
+ {46, 56, 3, 4, 28, 28, 1, 0.578290, 1.481830e-09},
+ {47, 64, 3, 4, 18, 32, 2, 0.578290, 1.454780e-09},
+ {48, 56, 3, 4, 26, 26, 1, 0.578290, 1.250550e-09},
+ {49, 60, 3, 4, 24, 24, 1, 0.578290, 8.614860e-10},
+ {50, 52, 3, 4, 18, 18, 1, 0.578290, 7.976650e-10},
+ {51, 56, 3, 4, 24, 24, 1, 0.628015, 7.700380e-10},
+ {52, 60, 3, 4, 22, 38, 1, 0.628015, 6.978800e-10},
+ {53, 52, 3, 4, 16, 36, 1, 0.628015, 5.069080e-10},
+ {54, 64, 3, 4, 32, 32, 1, 0.628015, 4.986660e-10},
+ {55, 64, 3, 4, 30, 30, 1, 0.628015, 4.315180e-10},
+ {56, 68, 3, 4, 18, 50, 2, 0.628015, 3.848530e-10},
+ {57, 56, 3, 4, 22, 22, 1, 0.628015, 3.643130e-10},
+ {58, 60, 3, 4, 22, 22, 1, 0.628015, 3.489400e-10},
+ {59, 64, 3, 4, 28, 28, 1, 0.628015, 2.836780e-10},
+ {60, 56, 3, 4, 20, 36, 1, 0.628015, 2.809120e-10},
+ {61, 52, 3, 4, 16, 16, 1, 0.666500, 2.534540e-10},
+ {62, 60, 3, 4, 20, 40, 1, 0.666500, 2.427110e-10},
+ {63, 68, 3, 4, 18, 34, 2, 0.666500, 2.309280e-10},
+ {64, 64, 3, 4, 26, 26, 1, 0.666500, 1.466250e-10},
+ {65, 56, 3, 4, 20, 20, 1, 0.666500, 1.404560e-10},
+ {66, 76, 3, 4, 22, 54, 2, 0.666500, 1.375500e-10},
+ {67, 60, 3, 4, 20, 20, 1, 0.666500, 1.213550e-10},
+ {68, 56, 3, 4, 18, 38, 1, 0.666500, 9.340240e-11},
+ {69, 76, 3, 4, 22, 38, 2, 0.666500, 8.174200e-11},
+ {70, 68, 3, 4, 34, 34, 1, 0.666500, 7.700290e-11},
+ {71, 68, 3, 4, 32, 32, 1, 0.666500, 6.729690e-11},
+ {72, 64, 3, 4, 24, 24, 1, 0.706860, 6.217280e-11},
+ {73, 72, 3, 4, 18, 56, 2, 0.706860, 6.056200e-11},
+ {74, 56, 3, 4, 18, 18, 1, 0.706860, 4.670120e-11},
+ {75, 68, 3, 4, 30, 30, 1, 0.706860, 4.543980e-11},
+ {76, 64, 3, 4, 22, 42, 1, 0.706860, 4.517330e-11},
+ {77, 72, 3, 4, 18, 36, 2, 0.706860, 3.615450e-11},
+ {78, 76, 3, 4, 38, 38, 1, 0.706860, 2.593400e-11},
+ {79, 68, 3, 4, 28, 28, 1, 0.706860, 2.438720e-11},
+ {80, 76, 3, 4, 36, 36, 1, 0.706860, 2.303460e-11},
+ {81, 64, 3, 4, 22, 22, 1, 0.706860, 2.258660e-11},
+ {82, 80, 3, 4, 22, 58, 2, 0.706860, 2.229400e-11},
+ {83, 76, 3, 4, 34, 34, 1, 0.706860, 1.626350e-11},
+ {84, 64, 3, 4, 20, 40, 1, 0.706860, 1.465310e-11},
+ {85, 80, 3, 4, 22, 40, 2, 0.763542, 1.319160e-11},
+ {86, 72, 3, 4, 36, 36, 1, 0.763542, 1.174900e-11},
+ {87, 68, 3, 4, 26, 26, 1, 0.763542, 1.078820e-11},
+ {88, 72, 3, 4, 34, 34, 1, 0.763542, 1.035690e-11},
+ {89, 76, 3, 4, 32, 32, 1, 0.763542, 9.311370e-12},
+ {90, 68, 3, 4, 24, 44, 1, 0.763542, 8.173020e-12},
+ {91, 64, 3, 4, 20, 20, 1, 0.763542, 7.326570e-12},
+ {92, 72, 3, 4, 32, 32, 1, 0.763542, 7.160350e-12},
+ {93, 76, 3, 4, 30, 30, 1, 0.763542, 4.440960e-12},
+ {94, 80, 3, 4, 40, 40, 1, 0.763542, 4.089220e-12},
+ {95, 68, 3, 4, 24, 24, 1, 0.763542, 4.086510e-12},
+ {96, 72, 3, 4, 30, 30, 1, 0.763542, 3.975570e-12},
+ {97, 80, 3, 4, 38, 38, 1, 0.763542, 3.656430e-12},
+ {98, 76, 3, 4, 28, 48, 1, 0.763542, 3.634830e-12},
+ {99, 84, 3, 4, 22, 62, 2, 0.763542, 3.566880e-12},
+ {100, 68, 3, 4, 22, 46, 1, 0.783762, 2.750600e-12},
+ {101, 80, 3, 4, 36, 36, 1, 0.783762, 2.630600e-12},
+ {102, 84, 3, 4, 22, 42, 2, 0.783762, 2.102180e-12},
+ {103, 72, 3, 4, 28, 28, 1, 0.783762, 1.828850e-12},
+ {104, 76, 3, 4, 28, 28, 1, 0.783762, 1.817420e-12},
+ {105, 80, 3, 4, 34, 34, 1, 0.783762, 1.548670e-12},
+ {106, 72, 3, 4, 26, 46, 1, 0.783762, 1.441670e-12},
+ {107, 68, 3, 4, 22, 22, 1, 0.783762, 1.375300e-12},
+ {108, 76, 3, 4, 26, 50, 1, 0.783762, 1.314800e-12},
+ {109, 92, 3, 4, 24, 68, 2, 0.783762, 1.296220e-12},
+ {110, 68, 3, 4, 20, 48, 1, 0.783762, 8.516070e-13},
+ {111, 80, 3, 4, 32, 32, 1, 0.783762, 7.636740e-13},
+ {112, 92, 3, 4, 24, 46, 2, 0.783762, 7.585130e-13},
+ {113, 72, 3, 4, 26, 26, 1, 0.824961, 7.208340e-13},
+ {114, 76, 3, 4, 26, 26, 1, 0.824961, 6.573980e-13},
+ {115, 80, 3, 4, 30, 50, 1, 0.824961, 6.475910e-13},
+ {116, 84, 3, 4, 42, 42, 1, 0.824961, 6.374900e-13},
+ {117, 84, 3, 4, 40, 40, 1, 0.824961, 5.734350e-13},
+ {118, 88, 3, 4, 22, 66, 2, 0.824961, 5.640630e-13},
+ {119, 72, 3, 4, 24, 48, 1, 0.824961, 5.032200e-13},
+ {120, 76, 3, 4, 24, 52, 1, 0.824961, 4.325430e-13},
+ {121, 68, 3, 4, 20, 20, 1, 0.824961, 4.258030e-13},
+ {122, 84, 3, 4, 38, 38, 1, 0.824961, 4.195890e-13},
+ {123, 88, 3, 4, 22, 44, 2, 0.824961, 3.312130e-13},
+ {124, 80, 3, 4, 30, 30, 1, 0.824961, 3.237950e-13},
+ {125, 84, 3, 4, 36, 36, 1, 0.824961, 2.533670e-13},
+ {126, 72, 3, 4, 24, 24, 1, 0.824961, 2.516100e-13},
+ {127, 80, 3, 4, 28, 52, 1, 0.824961, 2.424700e-13},
+ {128, 92, 3, 4, 46, 46, 1, 0.865704, 2.208090e-13},
+ {129, 76, 3, 4, 24, 24, 1, 0.865704, 2.162710e-13},
+ {130, 96, 3, 4, 26, 72, 2, 0.865704, 2.099840e-13},
+ {131, 92, 3, 4, 44, 44, 1, 0.865704, 2.006580e-13},
+ {132, 72, 3, 4, 22, 50, 1, 0.865704, 1.605310e-13},
+ {133, 92, 3, 4, 42, 42, 1, 0.865704, 1.511670e-13},
+ {134, 84, 3, 4, 34, 34, 1, 0.865704, 1.288510e-13},
+ {135, 96, 3, 4, 26, 48, 2, 0.865704, 1.224810e-13},
+ {136, 80, 3, 4, 28, 28, 1, 0.865704, 1.212350e-13},
+ {137, 88, 3, 4, 44, 44, 1, 0.865704, 9.836240e-14},
+ {138, 92, 3, 4, 40, 40, 1, 0.865704, 9.542830e-14},
+ {139, 88, 3, 4, 42, 42, 1, 0.865704, 8.895450e-14},
+ {140, 80, 3, 4, 26, 54, 1, 0.865704, 8.227740e-14},
+ {141, 72, 3, 4, 22, 22, 1, 0.865704, 8.026550e-14},
+ {142, 88, 3, 4, 40, 40, 1, 0.865704, 6.609120e-14},
+ {143, 84, 3, 4, 32, 32, 1, 0.865704, 5.648410e-14},
+ {144, 92, 3, 4, 38, 38, 1, 0.908949, 5.127400e-14},
+ {145, 72, 3, 4, 20, 52, 1, 0.908949, 4.822030e-14},
+ {146, 84, 3, 4, 30, 54, 1, 0.908949, 4.372420e-14},
+ {147, 80, 3, 4, 26, 26, 1, 0.908949, 4.113870e-14},
+ {148, 88, 3, 4, 38, 38, 1, 0.908949, 4.084490e-14},
+ {149, 96, 3, 4, 48, 48, 1, 0.908949, 3.497970e-14},
+ {150, 100, 3, 4, 26, 76, 2, 0.908949, 3.365420e-14},
+ {151, 96, 3, 4, 46, 46, 1, 0.908949, 3.192740e-14},
+ {152, 80, 3, 4, 24, 56, 1, 0.908949, 2.593890e-14},
+ {153, 96, 3, 4, 44, 44, 1, 0.908949, 2.435890e-14},
+ {154, 72, 3, 4, 20, 20, 1, 0.908949, 2.411020e-14},
+ {155, 92, 3, 4, 36, 36, 1, 0.908949, 2.388460e-14},
+ {156, 84, 3, 4, 30, 30, 1, 0.908949, 2.186210e-14},
+ {157, 88, 3, 4, 36, 36, 1, 0.908949, 2.137330e-14},
+ {158, 92, 3, 4, 34, 58, 1, 0.908949, 1.967320e-14},
+ {159, 100, 3, 4, 26, 50, 2, 0.908949, 1.957080e-14},
+ {160, 96, 3, 4, 42, 42, 1, 0.908949, 1.568040e-14},
+ {161, 84, 3, 4, 28, 56, 1, 0.908949, 1.529960e-14},
+ {162, 80, 3, 4, 24, 24, 1, 0.954202, 1.296950e-14},
+ {163, 108, 3, 4, 28, 82, 2, 0.954202, 1.237200e-14},
+ {164, 92, 3, 4, 34, 34, 1, 0.954202, 9.836600e-15},
+ {165, 88, 3, 4, 34, 34, 1, 0.954202, 9.667440e-15},
+ {166, 96, 3, 4, 40, 40, 1, 0.954202, 8.634600e-15},
+ {167, 88, 3, 4, 32, 56, 1, 0.954202, 7.725050e-15},
+ {168, 84, 3, 4, 28, 28, 1, 0.954202, 7.649800e-15},
+ {169, 92, 3, 4, 32, 60, 1, 0.954202, 7.305750e-15},
+ {170, 108, 3, 4, 28, 54, 2, 0.954202, 7.154920e-15},
+ {171, 100, 3, 4, 50, 50, 1, 0.954202, 5.487490e-15},
+ {172, 104, 3, 4, 26, 78, 2, 0.954202, 5.340690e-15},
+ {173, 100, 3, 4, 48, 48, 1, 0.954202, 5.028760e-15},
+ {174, 84, 3, 4, 26, 58, 1, 0.954202, 4.951260e-15},
+ {175, 96, 3, 4, 38, 38, 1, 0.954202, 4.134930e-15},
+ {176, 100, 3, 4, 46, 46, 1, 0.954202, 3.881360e-15},
+ {177, 88, 3, 4, 32, 32, 1, 0.954202, 3.862530e-15},
+ {178, 92, 3, 4, 32, 32, 1, 0.954202, 3.652870e-15},
+ {179, 96, 3, 4, 36, 60, 1, 0.954202, 3.505650e-15},
+ {180, 104, 3, 4, 26, 52, 2, 0.993877, 3.096920e-15},
+ {181, 88, 3, 4, 30, 58, 1, 0.993877, 2.785770e-15},
+ {182, 100, 3, 4, 44, 44, 1, 0.993877, 2.543880e-15},
+ {183, 92, 3, 4, 30, 62, 1, 0.993877, 2.493880e-15},
+ {184, 84, 3, 4, 26, 26, 1, 0.993877, 2.475630e-15},
+ {185, 112, 3, 4, 28, 86, 2, 0.993877, 2.003890e-15},
+ {186, 108, 3, 4, 54, 54, 1, 0.993877, 1.937830e-15},
+ {187, 108, 3, 4, 52, 52, 1, 0.993877, 1.788370e-15},
+ {188, 96, 3, 4, 36, 36, 1, 0.993877, 1.752820e-15},
+ {189, 84, 3, 4, 24, 60, 1, 0.993877, 1.514630e-15},
+ {190, 100, 3, 4, 42, 42, 1, 0.993877, 1.433180e-15},
+ {191, 108, 3, 4, 50, 50, 1, 0.993877, 1.408830e-15},
+ {192, 88, 3, 4, 30, 30, 1, 0.993877, 1.392880e-15},
+ {193, 96, 3, 4, 34, 62, 1, 0.993877, 1.339400e-15},
+ {194, 92, 3, 4, 30, 30, 1, 0.993877, 1.246940e-15},
+ {195, 112, 3, 4, 28, 56, 2, 0.993877, 1.155930e-15},
+ {196, 108, 3, 4, 48, 48, 1, 0.993877, 9.534230e-16},
+ {197, 88, 3, 4, 28, 60, 1, 0.993877, 9.258750e-16},
+ {198, 104, 3, 4, 52, 52, 1, 1.035782, 8.531480e-16},
+ {199, 92, 3, 4, 28, 64, 1, 1.035782, 7.972240e-16},
+ {200, 104, 3, 4, 50, 50, 1, 1.035782, 7.847010e-16},
+ {201, 84, 3, 4, 24, 24, 1, 1.035782, 7.573130e-16},
+ {202, 100, 3, 4, 40, 40, 1, 1.035782, 7.043820e-16},
+ {203, 96, 3, 4, 34, 34, 1, 1.035782, 6.696990e-16},
+ {204, 100, 3, 4, 38, 62, 1, 1.035782, 6.138180e-16},
+ {205, 104, 3, 4, 48, 48, 1, 1.035782, 6.121340e-16},
+ {206, 108, 3, 4, 46, 46, 1, 1.035782, 5.596910e-16},
+ {207, 96, 3, 4, 32, 64, 1, 1.035782, 4.694950e-16},
+ {208, 88, 3, 4, 28, 28, 1, 1.035782, 4.629380e-16},
+ {209, 104, 3, 4, 46, 46, 1, 1.035782, 4.079260e-16},
+ {210, 92, 3, 4, 28, 28, 1, 1.035782, 3.986120e-16},
+ {211, 116, 3, 4, 30, 86, 2, 1.035782, 3.215820e-16},
+ {212, 112, 3, 4, 56, 56, 1, 1.035782, 3.079780e-16},
+ {213, 100, 3, 4, 38, 38, 1, 1.035782, 3.069090e-16},
+ {214, 88, 3, 4, 26, 62, 1, 1.035782, 2.893730e-16},
+ {215, 108, 3, 4, 44, 44, 1, 1.035782, 2.884350e-16},
+ {216, 112, 3, 4, 54, 54, 1, 1.035782, 2.851100e-16},
+ {217, 92, 3, 4, 26, 66, 1, 1.035782, 2.429760e-16},
+ {218, 100, 3, 4, 36, 64, 1, 1.083752, 2.410500e-16},
+ {219, 104, 3, 4, 44, 44, 1, 1.083752, 2.347600e-16},
+ {220, 96, 3, 4, 32, 32, 1, 1.083752, 2.347480e-16},
+ {221, 112, 3, 4, 52, 52, 1, 1.083752, 2.266460e-16},
+ {222, 116, 3, 4, 30, 58, 2, 1.083752, 1.850560e-16},
+ {223, 112, 3, 4, 50, 50, 1, 1.083752, 1.555940e-16},
+ {224, 96, 3, 4, 30, 66, 1, 1.083752, 1.536060e-16},
+ {225, 88, 3, 4, 26, 26, 1, 1.083752, 1.446860e-16},
+ {226, 108, 3, 4, 42, 42, 1, 1.083752, 1.322410e-16},
+ {227, 92, 3, 4, 26, 26, 1, 1.083752, 1.214880e-16},
+ {228, 100, 3, 4, 36, 36, 1, 1.083752, 1.205250e-16},
+ {229, 124, 3, 4, 32, 94, 2, 1.083752, 1.192380e-16},
+ {230, 104, 3, 4, 42, 42, 1, 1.083752, 1.182330e-16},
+ {231, 108, 3, 4, 40, 68, 1, 1.083752, 1.093900e-16},
+ {232, 112, 3, 4, 48, 48, 1, 1.083752, 9.304980e-17},
+ {233, 100, 3, 4, 34, 66, 1, 1.083752, 8.672750e-17},
+ {234, 88, 3, 4, 24, 64, 1, 1.083752, 8.671340e-17},
+ {235, 96, 3, 4, 30, 30, 1, 1.083752, 7.680300e-17},
+ {236, 124, 3, 4, 32, 62, 2, 1.083752, 6.831000e-17},
+ {237, 108, 3, 4, 40, 40, 1, 1.083752, 5.469510e-17},
+ {238, 104, 3, 4, 40, 40, 1, 1.083752, 5.287900e-17},
+ {239, 120, 3, 4, 30, 90, 2, 1.122176, 5.116510e-17},
+ {240, 112, 3, 4, 46, 46, 1, 1.122176, 4.900210e-17},
+ {241, 116, 3, 4, 58, 58, 1, 1.122176, 4.853020e-17},
+ {242, 96, 3, 4, 28, 68, 1, 1.122176, 4.769400e-17},
+ {243, 116, 3, 4, 56, 56, 1, 1.122176, 4.505610e-17},
+ {244, 100, 3, 4, 34, 34, 1, 1.122176, 4.336370e-17},
+ {245, 88, 3, 4, 24, 24, 1, 1.122176, 4.335670e-17},
+ {246, 104, 3, 4, 38, 66, 1, 1.122176, 4.264440e-17},
+ {247, 108, 3, 4, 38, 70, 1, 1.122176, 4.139190e-17},
+ {248, 116, 3, 4, 54, 54, 1, 1.122176, 3.611940e-17},
+ {249, 120, 3, 4, 30, 60, 2, 1.122176, 2.937590e-17},
+ {250, 100, 3, 4, 32, 68, 1, 1.122176, 2.904870e-17},
+ {251, 116, 3, 4, 52, 52, 1, 1.122176, 2.512890e-17},
+ {252, 96, 3, 4, 28, 28, 1, 1.122176, 2.384700e-17},
+ {253, 112, 3, 4, 44, 44, 1, 1.122176, 2.300220e-17},
+ {254, 104, 3, 4, 38, 38, 1, 1.122176, 2.132220e-17},
+ {255, 108, 3, 4, 38, 38, 1, 1.122176, 2.069600e-17},
+ {256, 112, 3, 4, 42, 70, 1, 1.122176, 1.949710e-17},
+ {257, 128, 3, 4, 32, 98, 2, 1.122176, 1.931040e-17},
+ {258, 124, 3, 4, 62, 62, 1, 1.122176, 1.738220e-17},
+ {259, 124, 3, 4, 60, 60, 1, 1.122176, 1.622110e-17},
+ {260, 104, 3, 4, 36, 68, 1, 1.165058, 1.573970e-17},
+ {261, 116, 3, 4, 50, 50, 1, 1.165058, 1.529120e-17},
+ {262, 108, 3, 4, 36, 72, 1, 1.165058, 1.452810e-17},
+ {263, 100, 3, 4, 32, 32, 1, 1.165058, 1.452430e-17},
+ {264, 124, 3, 4, 58, 58, 1, 1.165058, 1.320160e-17},
+ {265, 128, 3, 4, 32, 64, 2, 1.165058, 1.103980e-17},
+ {266, 112, 3, 4, 42, 42, 1, 1.165058, 9.748530e-18},
+ {267, 124, 3, 4, 56, 56, 1, 1.165058, 9.408340e-18},
+ {268, 100, 3, 4, 30, 70, 1, 1.165058, 9.198900e-18},
+ {269, 116, 3, 4, 48, 48, 1, 1.165058, 8.218710e-18},
+ {270, 104, 3, 4, 36, 36, 1, 1.165058, 7.869870e-18},
+ {271, 120, 3, 4, 60, 60, 1, 1.165058, 7.586620e-18},
+ {272, 112, 3, 4, 40, 72, 1, 1.165058, 7.557840e-18},
+ {273, 108, 3, 4, 36, 36, 1, 1.165058, 7.264050e-18},
+ {274, 120, 3, 4, 58, 58, 1, 1.165058, 7.062330e-18},
+ {275, 124, 3, 4, 54, 54, 1, 1.165058, 5.908890e-18},
+ {276, 120, 3, 4, 56, 56, 1, 1.165058, 5.705970e-18},
+ {277, 104, 3, 4, 34, 70, 1, 1.165058, 5.397190e-18},
+ {278, 108, 3, 4, 34, 74, 1, 1.165058, 4.794130e-18},
+ {279, 100, 3, 4, 30, 30, 1, 1.165058, 4.599450e-18},
+ {280, 120, 3, 4, 54, 54, 1, 1.165058, 4.019430e-18},
+ {281, 116, 3, 4, 46, 46, 1, 1.165058, 3.945320e-18},
+ {282, 112, 3, 4, 40, 40, 1, 1.165058, 3.778920e-18},
+ {283, 116, 3, 4, 44, 72, 1, 1.231412, 3.423190e-18},
+ {284, 124, 3, 4, 52, 52, 1, 1.231412, 3.297090e-18},
+ {285, 100, 3, 4, 28, 72, 1, 1.231412, 2.795780e-18},
+ {286, 128, 3, 4, 64, 64, 1, 1.231412, 2.769110e-18},
+ {287, 112, 3, 4, 38, 74, 1, 1.231412, 2.714430e-18},
+ {288, 104, 3, 4, 34, 34, 1, 1.231412, 2.698600e-18},
+ {289, 128, 3, 4, 62, 62, 1, 1.231412, 2.590140e-18},
+ {290, 120, 3, 4, 52, 52, 1, 1.231412, 2.486040e-18},
+ {291, 108, 3, 4, 34, 34, 1, 1.231412, 2.397060e-18},
+ {292, 128, 3, 4, 60, 60, 1, 1.231412, 2.122380e-18},
+ {293, 104, 3, 4, 32, 72, 1, 1.231412, 1.744360e-18},
+ {294, 116, 3, 4, 44, 44, 1, 1.231412, 1.711600e-18},
+ {295, 124, 3, 4, 50, 50, 1, 1.231412, 1.649820e-18},
+ {296, 128, 3, 4, 58, 58, 1, 1.231412, 1.529130e-18},
+ {297, 108, 3, 4, 32, 76, 1, 1.231412, 1.506960e-18},
+ {298, 100, 3, 4, 28, 28, 1, 1.231412, 1.397890e-18},
+ {299, 120, 3, 4, 50, 50, 1, 1.231412, 1.362180e-18},
+ {300, 116, 3, 4, 42, 74, 1, 1.231412, 1.358390e-18},
+ {301, 112, 3, 4, 38, 38, 1, 1.231412, 1.357210e-18},
+ {302, 128, 3, 4, 56, 56, 1, 1.231412, 9.742990e-19},
+ {303, 112, 3, 4, 36, 76, 1, 1.231412, 9.147070e-19},
+ {304, 104, 3, 4, 32, 32, 1, 1.231412, 8.721800e-19},
+ {305, 108, 3, 4, 32, 32, 1, 1.231412, 7.534800e-19},
+ {306, 124, 3, 4, 48, 48, 1, 1.273354, 7.478050e-19},
+ {307, 116, 3, 4, 42, 42, 1, 1.273354, 6.791960e-19},
+ {308, 120, 3, 4, 48, 48, 1, 1.273354, 6.679650e-19},
+ {309, 124, 3, 4, 46, 78, 1, 1.273354, 6.204930e-19},
+ {310, 120, 3, 4, 46, 74, 1, 1.273354, 5.926870e-19},
+ {311, 128, 3, 4, 54, 54, 1, 1.273354, 5.530780e-19},
+ {312, 104, 3, 4, 30, 74, 1, 1.273354, 5.388680e-19},
+ {313, 116, 3, 4, 40, 76, 1, 1.273354, 4.990110e-19},
+ {314, 112, 3, 4, 36, 36, 1, 1.273354, 4.573530e-19},
+ {315, 108, 3, 4, 30, 78, 1, 1.273354, 4.570100e-19},
+ {316, 124, 3, 4, 46, 46, 1, 1.273354, 3.102460e-19},
+ {317, 120, 3, 4, 46, 46, 1, 1.273354, 2.963440e-19},
+ {318, 112, 3, 4, 34, 78, 1, 1.273354, 2.927770e-19},
+ {319, 128, 3, 4, 52, 52, 1, 1.273354, 2.821290e-19},
+ {320, 104, 3, 4, 30, 30, 1, 1.273354, 2.694340e-19},
+ {321, 116, 3, 4, 40, 40, 1, 1.273354, 2.495060e-19},
+ {322, 120, 3, 4, 44, 76, 1, 1.273354, 2.405750e-19},
+ {323, 124, 3, 4, 44, 80, 1, 1.273354, 2.381080e-19},
+ {324, 108, 3, 4, 30, 30, 1, 1.273354, 2.285050e-19},
+ {325, 116, 3, 4, 38, 78, 1, 1.273354, 1.717170e-19},
+ {326, 104, 3, 4, 28, 76, 1, 1.273354, 1.613020e-19},
+ {327, 112, 3, 4, 34, 34, 1, 1.273354, 1.463890e-19},
+ {328, 128, 3, 4, 50, 50, 1, 1.273354, 1.305320e-19},
+ {329, 120, 3, 4, 44, 44, 1, 1.273354, 1.202870e-19},
+ {330, 124, 3, 4, 44, 44, 1, 1.273354, 1.190540e-19},
+ {331, 128, 3, 4, 48, 80, 1, 1.307736, 1.106170e-19},
+ {332, 120, 3, 4, 42, 78, 1, 1.307736, 9.035000e-20},
+ {333, 112, 3, 4, 32, 80, 1, 1.307736, 9.008150e-20},
+ {334, 116, 3, 4, 38, 38, 1, 1.307736, 8.585840e-20},
+ {335, 124, 3, 4, 42, 82, 1, 1.307736, 8.539640e-20},
+ {336, 104, 3, 4, 28, 28, 1, 1.307736, 8.065090e-20},
+ {337, 116, 3, 4, 36, 80, 1, 1.307736, 5.599310e-20},
+ {338, 128, 3, 4, 48, 48, 1, 1.307736, 5.530870e-20},
+ {339, 120, 3, 4, 42, 42, 1, 1.307736, 4.517500e-20},
+ {340, 112, 3, 4, 32, 32, 1, 1.307736, 4.504080e-20},
+ {341, 128, 3, 4, 46, 82, 1, 1.307736, 4.334810e-20},
+ {342, 124, 3, 4, 42, 42, 1, 1.307736, 4.269820e-20},
+ {343, 120, 3, 4, 40, 80, 1, 1.307736, 3.174430e-20},
+ {344, 124, 3, 4, 40, 84, 1, 1.307736, 2.891760e-20},
+ {345, 116, 3, 4, 36, 36, 1, 1.307736, 2.799660e-20},
+ {346, 112, 3, 4, 30, 82, 1, 1.307736, 2.695640e-20},
+ {347, 128, 3, 4, 46, 46, 1, 1.307736, 2.167410e-20},
+ {348, 116, 3, 4, 34, 82, 1, 1.307736, 1.749650e-20},
+ {349, 120, 3, 4, 40, 40, 1, 1.307736, 1.587220e-20},
+ {350, 128, 3, 4, 44, 84, 1, 1.307736, 1.586440e-20},
+ {351, 124, 3, 4, 40, 40, 1, 1.307736, 1.445880e-20},
+ {352, 112, 3, 4, 30, 30, 1, 1.307736, 1.347820e-20},
+ {353, 120, 3, 4, 38, 82, 1, 1.307736, 1.054790e-20},
+ {354, 124, 3, 4, 38, 86, 1, 1.307736, 9.338320e-21},
+ {355, 116, 3, 4, 34, 34, 1, 1.345734, 8.748240e-21},
+ {356, 128, 3, 4, 44, 44, 1, 1.345734, 7.932220e-21},
+ {357, 128, 3, 4, 42, 86, 1, 1.345734, 5.474680e-21},
+ {358, 116, 3, 4, 32, 84, 1, 1.345734, 5.297010e-21},
+ {359, 120, 3, 4, 38, 38, 1, 1.345734, 5.273960e-21},
+ {360, 124, 3, 4, 38, 38, 1, 1.345734, 4.669160e-21},
+ {361, 120, 3, 4, 36, 84, 1, 1.345734, 3.349800e-21},
+ {362, 124, 3, 4, 36, 88, 1, 1.345734, 2.903950e-21},
+ {363, 128, 3, 4, 42, 42, 1, 1.345734, 2.737340e-21},
+ {364, 116, 3, 4, 32, 32, 1, 1.345734, 2.648510e-21},
+ {365, 128, 3, 4, 40, 88, 1, 1.345734, 1.798290e-21},
+ {366, 120, 3, 4, 36, 36, 1, 1.345734, 1.674900e-21},
+ {367, 124, 3, 4, 36, 36, 1, 1.345734, 1.451970e-21},
+ {368, 120, 3, 4, 34, 86, 1, 1.345734, 1.027330e-21},
+ {369, 128, 3, 4, 40, 40, 1, 1.345734, 8.991430e-22},
+ {370, 124, 3, 4, 34, 90, 1, 1.345734, 8.779540e-22},
+ {371, 128, 3, 4, 38, 90, 1, 1.345734, 5.674390e-22},
+ {372, 120, 3, 4, 34, 34, 1, 1.345734, 5.136640e-22},
+ {373, 124, 3, 4, 34, 34, 1, 1.345734, 4.389770e-22},
+ {374, 120, 3, 4, 32, 88, 1, 1.345734, 3.073590e-22},
+ {375, 128, 3, 4, 38, 38, 1, 1.345734, 2.837200e-22},
+ {376, 128, 3, 4, 36, 92, 1, 1.345734, 1.735640e-22},
+ {377, 120, 3, 4, 32, 32, 1, 1.345734, 1.536800e-22},
+ {378, 128, 3, 4, 36, 36, 1, 1.345734, 8.678180e-23},
+ {379, 128, 3, 4, 34, 94, 1, 1.345734, 5.192020e-23},
+ {380, 128, 3, 4, 34, 34, 1, 1.345734, 2.600000e-23},
+
+}
+
+/*
+// Table is difficulty table slice
+var Table = []difficulty{
+ {0, 32, 3, 4, 8, 24, 2, 0.329111, 3.077970e-05},
+ {1, 36, 3, 4, 9, 27, 2, 0.329111, 3.077970e-05},
+ {2, 40, 3, 4, 10, 30, 2, 0.329111, 2.023220e-05},
+ {3, 44, 3, 4, 11, 33, 1, 0.329111, 9.684650e-06},
+ {4, 48, 3, 4, 12, 36, 1, 0.329111, 6.784080e-06},
+ {5, 52, 3, 4, 13, 39, 2, 0.329111, 4.830240e-06},
+ {6, 56, 3, 4, 14, 42, 2, 0.369449, 3.125970e-06},
+ {7, 60, 3, 4, 15, 45, 1, 0.369449, 2.862890e-06},
+ {8, 64, 3, 4, 16, 48, 2, 0.369449, 1.637790e-06},
+ {9, 68, 3, 4, 17, 51, 1, 0.369449, 1.421700e-06},
+ {10, 72, 3, 4, 18, 54, 1, 0.369449, 1.051350e-06},
+ {11, 76, 3, 4, 19, 57, 2, 0.411046, 1.029740e-06},
+ {12, 80, 3, 4, 20, 60, 2, 0.411046, 7.570880e-07},
+ {13, 84, 3, 4, 21, 63, 1, 0.411046, 4.865630e-07},
+ {14, 88, 3, 4, 22, 66, 2, 0.411046, 4.813320e-07},
+ {15, 92, 3, 4, 23, 69, 1, 0.411046, 4.216920e-07},
+ {16, 96, 3, 4, 24, 72, 1, 0.411046, 3.350070e-07},
+ {17, 100, 3, 4, 25, 75, 2, 0.452453, 2.677070e-07},
+ {18, 104, 3, 4, 26, 78, 1, 0.452453, 2.055750e-07},
+ {19, 108, 3, 4, 27, 81, 1, 0.452453, 1.788400e-07},
+ {20, 112, 3, 4, 28, 84, 2, 0.452453, 1.664080e-07},
+ {21, 116, 3, 4, 29, 87, 1, 0.452453, 1.583110e-07},
+ {22, 120, 3, 4, 30, 90, 1, 0.452453, 7.917230e-08},
+ {23, 124, 3, 4, 31, 93, 1, 0.498513, 7.103820e-08},
+ {24, 128, 3, 4, 32, 96, 1, 0.498513, 6.510890e-08},
+ {25, 132, 3, 4, 33, 99, 1, 0.498513, 5.300760e-08},
+ {26, 136, 3, 4, 34, 102, 2, 0.498513, 4.266600e-08},
+ {27, 140, 3, 4, 35, 105, 1, 0.498513, 2.990510e-08},
+ {28, 144, 3, 4, 36, 108, 1, 0.498513, 2.927380e-08},
+ {29, 148, 3, 4, 37, 111, 2, 0.498513, 2.626790e-08},
+ {30, 152, 3, 4, 38, 114, 2, 0.498513, 1.485240e-08},
+ {31, 156, 3, 4, 39, 117, 1, 0.546238, 1.267290e-08},
+ {32, 160, 3, 4, 40, 120, 1, 0.546238, 9.891110e-09},
+ {33, 164, 3, 4, 41, 123, 2, 0.546238, 9.019200e-09},
+ {34, 168, 3, 4, 42, 126, 1, 0.546238, 8.762650e-09},
+ {35, 172, 3, 4, 43, 129, 1, 0.546238, 8.213140e-09},
+ {36, 176, 3, 4, 44, 132, 2, 0.546238, 6.658250e-09},
+ {37, 180, 3, 4, 45, 135, 1, 0.546238, 4.856960e-09},
+ {38, 184, 3, 4, 46, 138, 1, 0.546238, 4.381330e-09},
+ {39, 188, 3, 4, 47, 141, 2, 0.546238, 4.068000e-09},
+ {40, 192, 3, 4, 48, 144, 1, 0.546238, 3.186040e-09},
+ {41, 196, 3, 4, 49, 147, 1, 0.578290, 2.725470e-09},
+ {42, 200, 3, 4, 50, 150, 2, 0.578290, 2.410890e-09},
+ {43, 204, 3, 4, 51, 153, 1, 0.578290, 2.181360e-09},
+ {44, 208, 3, 4, 52, 156, 1, 0.578290, 1.737940e-09},
+ {45, 212, 3, 4, 53, 159, 1, 0.578290, 1.595330e-09},
+ {46, 216, 3, 4, 54, 162, 1, 0.578290, 1.481830e-09},
+ {47, 220, 3, 4, 55, 165, 2, 0.578290, 1.454780e-09},
+ {48, 224, 3, 4, 56, 168, 1, 0.578290, 1.250550e-09},
+ {49, 228, 3, 4, 57, 171, 1, 0.578290, 8.614860e-10},
+ {50, 232, 3, 4, 58, 174, 1, 0.578290, 7.976650e-10},
+ {51, 236, 3, 4, 59, 177, 1, 0.628015, 7.700380e-10},
+ {52, 240, 3, 4, 60, 180, 1, 0.628015, 6.978800e-10},
+ {53, 244, 3, 4, 61, 183, 1, 0.628015, 5.069080e-10},
+ {54, 248, 3, 4, 62, 186, 1, 0.628015, 4.986660e-10},
+ {55, 252, 3, 4, 63, 189, 1, 0.628015, 4.315180e-10},
+ {56, 256, 3, 4, 64, 192, 2, 0.628015, 3.848530e-10},
+}*/
+
diff --git a/consensus/eccbeta/LDPC_utils.go b/consensus/eccbeta/LDPC_utils.go
new file mode 100644
index 000000000000..56409d7ca11b
--- /dev/null
+++ b/consensus/eccbeta/LDPC_utils.go
@@ -0,0 +1,202 @@
+package eccbeta
+
+import (
+ crand "crypto/rand"
+ "math"
+ "math/big"
+ "math/rand"
+
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+//Parameters for matrix and seed
+const (
+ BigInfinity = 1000000.0
+ Inf = 64.0
+ MaxNonce = 1<<32 - 1
+
+ // These parameters are only used for the decoding function.
+ maxIter = 20 // The maximum number of iteration in the decoder
+ crossErr = 0.01 // A transisient error probability. This is also fixed as a small value
+)
+
+type Parameters struct {
+ n int
+ m int
+ wc int
+ wr int
+ seed int
+}
+
+// setParameters sets n, wc, wr, m, seed return parameters and difficulty level
+func setParameters(header *types.Header) (Parameters, int) {
+ //level := SearchLevel(header.Difficulty)
+ level := SearchLevel(header.Difficulty)
+
+ parameters := Parameters{
+ n: Table[level].n,
+ wc: Table[level].wc,
+ wr: Table[level].wr,
+ }
+ parameters.m = int(parameters.n * parameters.wc / parameters.wr)
+ parameters.seed = generateSeed(header.ParentHash)
+
+ return parameters, level
+}
+
+// setParameters sets n, wc, wr, m, seed return parameters and difficulty level
+func setParameters_Seoul(header *types.Header) (Parameters, int) {
+ //level := SearchLevel(header.Difficulty)
+ level := SearchLevel_Seoul(header.Difficulty)
+ table := getTable(level)
+ parameters := Parameters{
+ n: table.n,
+ wc: table.wc,
+ wr: table.wr,
+ }
+ parameters.m = int(parameters.n * parameters.wc / parameters.wr)
+ parameters.seed = generateSeed(header.ParentHash)
+
+ return parameters, level
+}
+
+
+//generateRandomNonce generate 64bit random nonce with similar way of ethereum block nonce
+func generateRandomNonce() uint64 {
+ seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
+ source := rand.New(rand.NewSource(seed.Int64()))
+
+ return uint64(source.Int63())
+}
+
+func funcF(x float64) float64 {
+ if x >= BigInfinity {
+ return 1.0 / BigInfinity
+ } else if x <= (1.0 / BigInfinity) {
+ return BigInfinity
+ } else {
+ return math.Log((math.Exp(x) + 1) / (math.Exp(x) - 1))
+ }
+}
+
+func infinityTest(x float64) float64 {
+ if x >= Inf {
+ return Inf
+ } else if x <= -Inf {
+ return -Inf
+ } else {
+ return x
+ }
+}
+
+//generateSeed generate seed using previous hash vector
+func generateSeed(phv [32]byte) int {
+ sum := 0
+ for i := 0; i < len(phv); i++ {
+ sum += int(phv[i])
+ }
+ return sum
+}
+
+//generateH generate H matrix using parameters
+//generateH Cannot be sure rand is same with original implementation of C++
+func generateH(parameters Parameters) [][]int {
+ var H [][]int
+ var hSeed int64
+ var colOrder []int
+
+ hSeed = int64(parameters.seed)
+ k := parameters.m / parameters.wc
+
+ H = make([][]int, parameters.m)
+ for i := range H {
+ H[i] = make([]int, parameters.n)
+ }
+
+ for i := 0; i < k; i++ {
+ for j := i * parameters.wr; j < (i+1)*parameters.wr; j++ {
+ H[i][j] = 1
+ }
+ }
+
+ for i := 1; i < parameters.wc; i++ {
+ colOrder = nil
+ for j := 0; j < parameters.n; j++ {
+ colOrder = append(colOrder, j)
+ }
+
+ src := rand.NewSource(hSeed)
+ rnd := rand.New(src)
+ rnd.Seed(hSeed)
+ rnd.Shuffle(len(colOrder), func(i, j int) {
+ colOrder[i],colOrder[j] = colOrder[j], colOrder[i]
+ })
+ hSeed--
+
+ for j := 0; j < parameters.n; j++ {
+ index := (colOrder[j]/parameters.wr + k*i)
+ H[index][j] = 1
+ }
+ }
+
+ return H
+}
+
+//generateQ generate colInRow and rowInCol matrix using H matrix
+func generateQ(parameters Parameters, H [][]int) ([][]int, [][]int) {
+ colInRow := make([][]int, parameters.wr)
+ for i := 0; i < parameters.wr; i++ {
+ colInRow[i] = make([]int, parameters.m)
+ }
+
+ rowInCol := make([][]int, parameters.wc)
+ for i := 0; i < parameters.wc; i++ {
+ rowInCol[i] = make([]int, parameters.n)
+ }
+
+ rowIndex := 0
+ colIndex := 0
+
+ for i := 0; i < parameters.m; i++ {
+ for j := 0; j < parameters.n; j++ {
+ if H[i][j] == 1 {
+ colInRow[colIndex%parameters.wr][i] = j
+ colIndex++
+
+ rowInCol[rowIndex/parameters.n][j] = i
+ rowIndex++
+ }
+ }
+ }
+
+ return colInRow, rowInCol
+}
+
+//generateHv generate hashvector
+//It needs to compare with origin C++ implementation Especially when sha256 function is used
+func generateHv(parameters Parameters, encryptedHeaderWithNonce []byte) []int {
+ hashVector := make([]int, parameters.n)
+
+ /*
+ if parameters.n <= 256 {
+ tmpHashVector = sha256.Sum256(headerWithNonce)
+ } else {
+ /*
+ This section is for a case in which the size of a hash vector is larger than 256.
+ This section will be implemented soon.
+ }
+ transform the constructed hexadecimal array into an binary array
+ ex) FE01 => 11111110000 0001
+ */
+
+ for i := 0; i < parameters.n/8; i++ {
+ decimal := int(encryptedHeaderWithNonce[i])
+ for j := 7; j >= 0; j-- {
+ hashVector[j+8*(i)] = decimal % 2
+ decimal /= 2
+ }
+ }
+
+ //outputWord := hashVector[:parameters.n]
+ return hashVector
+}
diff --git a/consensus/eccbeta/algorithm.go b/consensus/eccbeta/algorithm.go
new file mode 100644
index 000000000000..e734289ce403
--- /dev/null
+++ b/consensus/eccbeta/algorithm.go
@@ -0,0 +1,516 @@
+package eccbeta
+
+import (
+ "encoding/binary"
+ "hash"
+ "math/big"
+ "math/rand"
+ "sync"
+ "time"
+
+ "github.com/cryptoecc/WorldLand/consensus"
+ "github.com/cryptoecc/WorldLand/core/types"
+ "github.com/cryptoecc/WorldLand/crypto"
+ "github.com/cryptoecc/WorldLand/log"
+ "github.com/cryptoecc/WorldLand/metrics"
+ "github.com/cryptoecc/WorldLand/rpc"
+ "golang.org/x/crypto/sha3"
+)
+
+type ECC struct {
+ config Config
+
+ // Mining related fields
+ rand *rand.Rand // Properly seeded random source for nonces
+ threads int // Number of threads to mine on if mining
+ update chan struct{} // Notification channel to update mining parameters
+ hashrate metrics.Meter // Meter tracking the average hashrate
+ remote *remoteSealer
+
+ // Remote sealer related fields
+ workCh chan *sealTask // Notification channel to push new work and relative result channel to remote sealer
+ fetchWorkCh chan *sealWork // Channel used for remote sealer to fetch mining work
+ submitWorkCh chan *mineResult // Channel used for remote sealer to submit their mining result
+ fetchRateCh chan chan uint64 // Channel used to gather submitted hash rate for local or remote sealer.
+ submitRateCh chan *hashrate // Channel used for remote sealer to submit their mining hashrate
+
+ shared *ECC // Shared PoW verifier to avoid cache regeneration
+ fakeFail uint64 // Block number which fails PoW check even in fake mode
+ fakeDelay time.Duration // Time delay to sleep for before returning from verify
+
+ lock sync.Mutex // Ensures thread safety for the in-memory caches and mining fields
+ closeOnce sync.Once // Ensures exit channel will not be closed twice.
+}
+
+type Mode uint
+
+const (
+ epochLength = 30000 // Blocks per epoch
+ ModeNormal Mode = iota
+ ModeShared
+ ModeTest
+ ModeFake
+ ModeFullFake
+)
+
+// Config are the configuration parameters of the ethash.
+type Config struct {
+ PowMode Mode
+ // When set, notifications sent by the remote sealer will
+ // be block header JSON objects instead of work package arrays.
+ NotifyFull bool
+ Log log.Logger `toml:"-"`
+}
+
+// hasher is a repetitive hasher allowing the same hash data structures to be
+// reused between hash runs instead of requiring new ones to be created.
+//var hasher func(dest []byte, data []byte)
+
+var (
+ two256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
+
+ // sharedECC is a full instance that can be shared between multiple users.
+ sharedECC *ECC
+
+ // algorithmRevision is the data structure version used for file naming.
+ algorithmRevision = 2
+)
+
+func init() {
+ sharedConfig := Config{
+ PowMode: ModeNormal,
+ }
+ sharedECC = New(sharedConfig, nil, false)
+}
+
+type verifyParameters struct {
+ n uint64
+ m uint64
+ wc uint64
+ wr uint64
+ seed uint64
+ outputWord []uint64
+}
+
+//const cross_err = 0.01
+
+//type (
+// intMatrix [][]int
+// floatMatrix [][]float64
+//)
+
+//RunOptimizedConcurrencyLDPC use goroutine for mining block
+func RunOptimizedConcurrencyLDPC(header *types.Header, hash []byte) (bool, []int, []int, uint64, []byte) {
+ //Need to set difficulty before running LDPC
+ // Number of goroutines : 500, Number of attempts : 50000 Not bad
+
+ var LDPCNonce uint64
+ var hashVector []int
+ var outputWord []int
+ var digest []byte
+ var flag bool
+
+ //var wg sync.WaitGroup
+ //var outerLoopSignal = make(chan struct{})
+ //var innerLoopSignal = make(chan struct{})
+ //var goRoutineSignal = make(chan struct{})
+
+ parameters, _ := setParameters(header)
+ H := generateH(parameters)
+ colInRow, rowInCol := generateQ(parameters, H)
+
+ for i := 0; i < 64; i++ {
+ var goRoutineHashVector []int
+ var goRoutineOutputWord []int
+ goRoutineNonce := generateRandomNonce()
+ seed := make([]byte, 40)
+ copy(seed, hash)
+ binary.LittleEndian.PutUint64(seed[32:], goRoutineNonce)
+ seed = crypto.Keccak512(seed)
+ //fmt.Printf("nonce: %v\n", seed)
+
+ goRoutineHashVector = generateHv(parameters, seed)
+ goRoutineHashVector, goRoutineOutputWord, _ = OptimizedDecoding(parameters, goRoutineHashVector, H, rowInCol, colInRow)
+
+ flag, _ = MakeDecision(header, colInRow, goRoutineOutputWord)
+
+ if flag {
+ hashVector = goRoutineHashVector
+ outputWord = goRoutineOutputWord
+ LDPCNonce = goRoutineNonce
+ digest = seed
+ break
+ }
+ }
+ return flag, hashVector, outputWord, LDPCNonce, digest
+}
+
+func RunOptimizedConcurrencyLDPC_Seoul(header *types.Header, hash []byte) (bool, []int, []int, uint64, []byte) {
+ //Need to set difficulty before running LDPC
+ // Number of goroutines : 500, Number of attempts : 50000 Not bad
+
+ var LDPCNonce uint64
+ var hashVector []int
+ var outputWord []int
+ var digest []byte
+ var flag bool
+
+ //var wg sync.WaitGroup
+ //var outerLoopSignal = make(chan struct{})
+ //var innerLoopSignal = make(chan struct{})
+ //var goRoutineSignal = make(chan struct{})
+
+ parameters, _ := setParameters_Seoul(header)
+ H := generateH(parameters)
+ colInRow, rowInCol := generateQ(parameters, H)
+
+ for i := 0; i < 64; i++ {
+ var goRoutineHashVector []int
+ var goRoutineOutputWord []int
+ goRoutineNonce := generateRandomNonce()
+ seed := make([]byte, 40)
+ copy(seed, hash)
+ binary.LittleEndian.PutUint64(seed[32:], goRoutineNonce)
+ seed = crypto.Keccak512(seed)
+ //fmt.Printf("nonce: %v\n", seed)
+
+ goRoutineHashVector = generateHv(parameters, seed)
+ goRoutineHashVector, goRoutineOutputWord, _ = OptimizedDecodingSeoul(parameters, goRoutineHashVector, H, rowInCol, colInRow)
+
+ flag, _ = MakeDecision_Seoul(header, colInRow, goRoutineOutputWord)
+
+ if flag {
+ hashVector = goRoutineHashVector
+ outputWord = goRoutineOutputWord
+ LDPCNonce = goRoutineNonce
+ digest = seed
+ break
+ }
+ }
+ return flag, hashVector, outputWord, LDPCNonce, digest
+}
+
+//MakeDecision check outputWord is valid or not using colInRow
+func MakeDecision(header *types.Header, colInRow [][]int, outputWord []int) (bool, int) {
+ parameters, difficultyLevel := setParameters(header)
+ for i := 0; i < parameters.m; i++ {
+ sum := 0
+ for j := 0; j < parameters.wr; j++ {
+ // fmt.Printf("i : %d, j : %d, m : %d, wr : %d \n", i, j, m, wr)
+ sum = sum + outputWord[colInRow[j][i]]
+ }
+ if sum%2 == 1 {
+ return false, -1
+ }
+ }
+
+ var numOfOnes int
+ for _, val := range outputWord {
+ numOfOnes += val
+ }
+
+ if numOfOnes >= Table[difficultyLevel].decisionFrom &&
+ numOfOnes <= Table[difficultyLevel].decisionTo &&
+ numOfOnes%Table[difficultyLevel].decisionStep == 0 {
+ //fmt.Printf("hamming weight: %v\n", numOfOnes)
+ return true, numOfOnes
+ }
+
+ return false, numOfOnes
+}
+
+//MakeDecision check outputWord is valid or not using colInRow
+func MakeDecision_Seoul(header *types.Header, colInRow [][]int, outputWord []int) (bool, int) {
+ parameters, _ := setParameters_Seoul(header)
+ for i := 0; i < parameters.m; i++ {
+ sum := 0
+ for j := 0; j < parameters.wr; j++ {
+ // fmt.Printf("i : %d, j : %d, m : %d, wr : %d \n", i, j, m, wr)
+ sum = sum + outputWord[colInRow[j][i]]
+ }
+ if sum%2 == 1 {
+ return false, -1
+ }
+ }
+
+ var numOfOnes int
+ for _, val := range outputWord {
+ numOfOnes += val
+ }
+
+ if numOfOnes >= parameters.n/4 &&
+ numOfOnes <= parameters.n/4 * 3 {
+ //fmt.Printf("hamming weight: %v\n", numOfOnes)
+ return true, numOfOnes
+ }
+
+ return false, numOfOnes
+}
+
+//func isRegular(nSize, wCol, wRow int) bool {
+// res := float64(nSize*wCol) / float64(wRow)
+// m := math.Round(res)
+//
+// if int(m)*wRow == nSize*wCol {
+// return true
+// }
+//
+// return false
+//}
+
+//func SetDifficulty(nSize, wCol, wRow int) bool {
+// if isRegular(nSize, wCol, wRow) {
+// n = nSize
+// wc = wCol
+// wr = wRow
+// m = int(n * wc / wr)
+// return true
+// }
+// return false
+//}
+
+//func newIntMatrix(rows, cols int) intMatrix {
+// m := intMatrix(make([][]int, rows))
+// for i := range m {
+// m[i] = make([]int, cols)
+// }
+// return m
+//}
+//
+//func newFloatMatrix(rows, cols int) floatMatrix {
+// m := floatMatrix(make([][]float64, rows))
+// for i := range m {
+// m[i] = make([]float64, cols)
+// }
+// return m
+//}
+
+// New creates a full sized ethash PoW scheme and starts a background thread for
+// remote mining, also optionally notifying a batch of remote services of new work
+// packages.
+
+func New(config Config, notify []string, noverify bool) *ECC {
+ if config.Log == nil {
+ config.Log = log.Root()
+ }
+ ecc := &ECC{
+ config: config,
+ update: make(chan struct{}),
+ hashrate: metrics.NewMeterForced(),
+ workCh: make(chan *sealTask),
+ fetchWorkCh: make(chan *sealWork),
+ submitWorkCh: make(chan *mineResult),
+ fetchRateCh: make(chan chan uint64),
+ submitRateCh: make(chan *hashrate),
+ }
+ if config.PowMode == ModeShared {
+ ecc.shared = sharedECC
+ }
+ ecc.remote = startRemoteSealer(ecc, notify, noverify)
+ return ecc
+}
+
+func NewTester(notify []string, noverify bool) *ECC {
+ ecc := &ECC{
+ config: Config{PowMode: ModeTest},
+ update: make(chan struct{}),
+ hashrate: metrics.NewMeterForced(),
+ workCh: make(chan *sealTask),
+ fetchWorkCh: make(chan *sealWork),
+ submitWorkCh: make(chan *mineResult),
+ fetchRateCh: make(chan chan uint64),
+ submitRateCh: make(chan *hashrate),
+ }
+ ecc.remote = startRemoteSealer(ecc, notify, noverify)
+ return ecc
+}
+
+// NewFaker creates a ethash consensus engine with a fake PoW scheme that accepts
+// all blocks' seal as valid, though they still have to conform to the Ethereum
+// consensus rules.
+func NewFaker() *ECC {
+ return &ECC{
+ config: Config{
+ PowMode: ModeFake,
+ Log: log.Root(),
+ },
+ }
+}
+
+// NewFakeFailer creates a ethash consensus engine with a fake PoW scheme that
+// accepts all blocks as valid apart from the single one specified, though they
+// still have to conform to the Ethereum consensus rules.
+func NewFakeFailer(fail uint64) *ECC {
+ return &ECC{
+ config: Config{
+ PowMode: ModeFake,
+ Log: log.Root(),
+ },
+ fakeFail: fail,
+ }
+}
+
+// NewFakeDelayer creates a ethash consensus engine with a fake PoW scheme that
+// accepts all blocks as valid, but delays verifications by some time, though
+// they still have to conform to the Ethereum consensus rules.
+func NewFakeDelayer(delay time.Duration) *ECC {
+ return &ECC{
+ config: Config{
+ PowMode: ModeFake,
+ Log: log.Root(),
+ },
+ fakeDelay: delay,
+ }
+}
+
+// NewFullFaker creates an ethash consensus engine with a full fake scheme that
+// accepts all blocks as valid, without checking any consensus rules whatsoever.
+func NewFullFaker() *ECC {
+ return &ECC{
+ config: Config{
+ PowMode: ModeFullFake,
+ Log: log.Root(),
+ },
+ }
+}
+
+// NewShared creates a full sized ethash PoW shared between all requesters running
+// in the same process.
+//func NewShared() *ECC {
+// return &ECC{shared: sharedECC}
+//}
+
+// Close closes the exit channel to notify all backend threads exiting.
+func (ecc *ECC) Close() error {
+ return ecc.StopRemoteSealer()
+}
+
+// StopRemoteSealer stops the remote sealer
+func (ecc *ECC) StopRemoteSealer() error {
+ ecc.closeOnce.Do(func() {
+ // Short circuit if the exit channel is not allocated.
+ if ecc.remote == nil {
+ return
+ }
+ close(ecc.remote.requestExit)
+ <-ecc.remote.exitCh
+ })
+ return nil
+}
+
+// Threads returns the number of mining threads currently enabled. This doesn't
+// necessarily mean that mining is running!
+func (ecc *ECC) Threads() int {
+ ecc.lock.Lock()
+ defer ecc.lock.Unlock()
+
+ return ecc.threads
+}
+
+// SetThreads updates the number of mining threads currently enabled. Calling
+// this method does not start mining, only sets the thread count. If zero is
+// specified, the miner will use all cores of the machine. Setting a thread
+// count below zero is allowed and will cause the miner to idle, without any
+// work being done.
+func (ecc *ECC) SetThreads(threads int) {
+ ecc.lock.Lock()
+ defer ecc.lock.Unlock()
+
+ // If we're running a shared PoW, set the thread count on that instead
+ if ecc.shared != nil {
+ ecc.shared.SetThreads(threads)
+ return
+ }
+ // Update the threads and ping any running seal to pull in any changes
+ ecc.threads = threads
+ select {
+ case ecc.update <- struct{}{}:
+ default:
+ }
+}
+
+// Hashrate implements PoW, returning the measured rate of the search invocations
+// per second over the last minute.
+// Note the returned hashrate includes local hashrate, but also includes the total
+// hashrate of all remote miner.
+func (ecc *ECC) Hashrate() float64 {
+ // Short circuit if we are run the ecc in normal/test mode.
+
+ var res = make(chan uint64, 1)
+
+ select {
+ case ecc.remote.fetchRateCh <- res:
+ case <-ecc.remote.exitCh:
+ // Return local hashrate only if ecc is stopped.
+ return ecc.hashrate.Rate1()
+ }
+
+ // Gather total submitted hash rate of remote sealers.
+ return ecc.hashrate.Rate1() + float64(<-res)
+}
+
+// APIs implements consensus.Engine, returning the user facing RPC APIs.
+func (ecc *ECC) APIs(chain consensus.ChainHeaderReader) []rpc.API {
+ // In order to ensure backward compatibility, we exposes ecc RPC APIs
+ // to both eth and ecc namespaces.
+ return []rpc.API{
+ {
+ Namespace: "eth",
+ Version: "1.0",
+ Service: &API{ecc},
+ Public: true,
+ },
+ {
+ Namespace: "ecc",
+ Version: "1.0",
+ Service: &API{ecc},
+ Public: true,
+ },
+ }
+}
+
+// hasher is a repetitive hasher allowing the same hash data structures to be
+// reused between hash runs instead of requiring new ones to be created.
+type hasher func(dest []byte, data []byte)
+
+// makeHasher creates a repetitive hasher, allowing the same hash data structures to
+// be reused between hash runs instead of requiring new ones to be created. The returned
+// function is not thread safe!
+func makeHasher(h hash.Hash) hasher {
+ // sha3.state supports Read to get the sum, use it to avoid the overhead of Sum.
+ // Read alters the state but we reset the hash before every operation.
+ type readerHash interface {
+ hash.Hash
+ Read([]byte) (int, error)
+ }
+ rh, ok := h.(readerHash)
+ if !ok {
+ panic("can't find Read method on hash")
+ }
+ outputLen := rh.Size()
+ return func(dest []byte, data []byte) {
+ rh.Reset()
+ rh.Write(data)
+ rh.Read(dest[:outputLen])
+ }
+}
+
+// seedHash is the seed to use for generating a verification cache and the mining
+// dataset.
+func seedHash(block uint64) []byte {
+ seed := make([]byte, 32)
+ if block < epochLength {
+ return seed
+ }
+ keccak256 := makeHasher(sha3.NewLegacyKeccak256())
+ for i := 0; i < int(block/epochLength); i++ {
+ keccak256(seed, seed)
+ }
+ return seed
+}
+
+//// SeedHash is the seed to use for generating a verification cache and the mining
+//// dataset.
+func SeedHash(block uint64) []byte {
+ return seedHash(block)
+}
diff --git a/consensus/eccbeta/algorithm_test.go b/consensus/eccbeta/algorithm_test.go
new file mode 100644
index 000000000000..4a93257857cd
--- /dev/null
+++ b/consensus/eccbeta/algorithm_test.go
@@ -0,0 +1,90 @@
+package eccbeta
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/common/hexutil"
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+func TestRandomSeed(t *testing.T) {
+ header := new(types.Header)
+ header.Difficulty = ProbToDifficulty(Table[0].miningProb)
+ parameters, _ := setParameters(header)
+
+ a := generateH(parameters)
+ b := generateH(parameters)
+
+ if !reflect.DeepEqual(a, b) {
+ t.Error("Wrong matrix")
+ } else {
+ t.Log("Pass")
+ }
+}
+
+func TestLDPC(t *testing.T) {
+ /*
+ prevHash := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000")
+ curHash := hexutil.MustDecode("0xca2ff06caae7c94dc968be7d76d0fbf60dd2e1989ee9bf0d5931e48564d5143b")
+ nonce, mixDigest := RunLDPC(prevHash, curHash)
+
+ wantDigest := hexutil.MustDecode("0x535306ee4b42c92aecd0e71fca98572064f049c2babb2769faa3bbd87d67ec2d")
+
+ if !bytes.Equal(mixDigest, wantDigest) {
+ t.Errorf("light hashimoto digest mismatch: have %x, want %x", mixDigest, wantDigest)
+ }
+
+ t.Log(nonce)
+ */
+ header := new(types.Header)
+ //t.Log(hexutil.Encode(header.ParentHash))
+ header.Difficulty = ProbToDifficulty(Table[0].miningProb)
+ var hash []byte
+ _, hashVector, outputWord, LDPCNonce, digest := RunOptimizedConcurrencyLDPC(header, hash)
+
+ t.Logf("Hash vector : %v\n", hashVector)
+ t.Logf("Outputword : %v\n", outputWord)
+ t.Logf("LDPC Nonce : %v\n", LDPCNonce)
+ t.Logf("Digest : %v\n", digest)
+}
+
+func BenchmarkECCPoW(b *testing.B) {
+ //prevHash := hexutil.MustDecode("0xd783efa4d392943503f28438ad5830b2d5964696ffc285f338585e9fe0a37a05")
+ //curHash := hexutil.MustDecode("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
+
+ header := new(types.Header)
+ header.Difficulty = ProbToDifficulty(Table[0].miningProb)
+ var hash []byte
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ RunOptimizedConcurrencyLDPC(header, hash)
+ }
+}
+
+
+func TestHashRate(t *testing.T) {
+ var (
+ hashrate = []hexutil.Uint64{100, 200, 300}
+ expect uint64
+ ids = []common.Hash{common.HexToHash("a"), common.HexToHash("b"), common.HexToHash("c")}
+ )
+ ecc := NewTester(nil, false)
+ defer ecc.Close()
+
+ if tot := ecc.Hashrate(); tot != 0 {
+ t.Error("expect the result should be zero")
+ }
+
+ api := &API{ecc}
+ for i := 0; i < len(hashrate); i++ {
+ if res := api.SubmitHashRate(hashrate[i], ids[i]); !res {
+ t.Error("remote miner submit hashrate failed")
+ }
+ expect += uint64(hashrate[i])
+ }
+ if tot := ecc.Hashrate(); tot != float64(expect) {
+ t.Error("expect total hashrate should be same")
+ }
+}
diff --git a/consensus/eccbeta/api.go b/consensus/eccbeta/api.go
new file mode 100644
index 000000000000..05f98333f6dd
--- /dev/null
+++ b/consensus/eccbeta/api.go
@@ -0,0 +1,116 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package eccbeta
+
+import (
+ "errors"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/common/hexutil"
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+var erreccStopped = errors.New("ecc stopped")
+
+// API exposes ecc related methods for the RPC interface.
+type API struct {
+ ecc *ECC // Make sure the mode of ecc is normal.
+}
+
+// GetWork returns a work package for external miner.
+//
+// The work package consists of 3 strings:
+// result[0] - 32 bytes hex encoded current block header pow-hash
+// result[1] - 32 bytes hex encoded seed hash used for DAG
+// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
+// result[3] - hex encoded block number
+func (api *API) GetWork() ([4]string, error) {
+ //if api.ecc.config.PowMode != ModeNormal && api.ecc.config.PowMode != ModeTest {
+ // return [4]string{}, errors.New("not supported")
+ //}
+
+ var (
+ workCh = make(chan [4]string, 1)
+ errc = make(chan error, 1)
+ )
+
+ select {
+ case api.ecc.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
+ case <-api.ecc.remote.exitCh:
+ return [4]string{}, erreccStopped
+ }
+
+ select {
+ case work := <-workCh:
+ return work, nil
+ case err := <-errc:
+ return [4]string{}, err
+ }
+}
+
+// SubmitWork can be used by external miner to submit their POW solution.
+// It returns an indication if the work was accepted.
+// Note either an invalid solution, a stale work a non-existent work will return false.
+func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) bool {
+ //if api.ecc.config.PowMode != ModeNormal && api.ecc.config.PowMode != ModeTest {
+ // return false
+ //}
+
+ var errc = make(chan error, 1)
+
+ select {
+ case api.ecc.submitWorkCh <- &mineResult{
+ nonce: nonce,
+ mixDigest: digest,
+ hash: hash,
+ errc: errc,
+ }:
+ case <-api.ecc.remote.exitCh:
+ return false
+ }
+
+ err := <-errc
+ return err == nil
+}
+
+// SubmitHashrate can be used for remote miners to submit their hash rate.
+// This enables the node to report the combined hash rate of all miners
+// which submit work through this node.
+//
+// It accepts the miner hash rate and an identifier which must be unique
+// between nodes.
+func (api *API) SubmitHashRate(rate hexutil.Uint64, id common.Hash) bool {
+
+ var done = make(chan struct{}, 1)
+
+ select {
+ case api.ecc.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}:
+ case <-api.ecc.remote.exitCh:
+ return false
+ }
+
+ // Block until hash rate submitted successfully.
+ <-done
+
+ return true
+}
+
+// Geccrate returns the current hashrate for local CPU miner and remote miner.
+func (api *API) Geccrate() uint64 {
+
+ return uint64(api.ecc.Hashrate())
+}
diff --git a/consensus/eccbeta/consensus.go b/consensus/eccbeta/consensus.go
new file mode 100644
index 000000000000..a12ce5c4b1ed
--- /dev/null
+++ b/consensus/eccbeta/consensus.go
@@ -0,0 +1,605 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package eccbeta
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math/big"
+ "runtime"
+ "time"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/consensus"
+ "github.com/cryptoecc/WorldLand/consensus/misc"
+ "github.com/cryptoecc/WorldLand/core/state"
+ "github.com/cryptoecc/WorldLand/core/types"
+ "github.com/cryptoecc/WorldLand/params"
+ "github.com/cryptoecc/WorldLand/rlp"
+ "github.com/cryptoecc/WorldLand/trie"
+ mapset "github.com/deckarep/golang-set"
+ "golang.org/x/crypto/sha3"
+)
+
+// eccbeta proof-of-work protocol constants.
+var (
+ // Beta network block reward: 20 tokens per block (20 * 10^18 wei)
+ BetaBlockReward = new(big.Int).Mul(big.NewInt(20), big.NewInt(1e+18))
+
+ // Beta treasury address - receives 20% of block rewards (4 WL per block)
+ BetaTreasuryAddress = common.HexToAddress("0x4C7dE6771DC602176b25fD4E1ae5550A3eAa06dF")
+
+ // Beta halving interval: ~4 years (at 10 sec/block)
+ // 4 years = 4 * 365.25 * 24 * 60 * 60 / 10 ≈ 12,614,400 blocks
+ BETA_HALVING_INTERVAL = uint64(12614400) // Blocks per 4 years
+ BETA_MATURITY_INTERVAL = uint64(3153600) // Blocks per year (for post-halving maturity phase)
+
+ BetaSumRewardUntilMaturity = big.NewInt(94608000) // Total supply until maturity (adjusted for Beta)
+
+ BetaMaxHalving = int64(4) // Number of halvings before maturity phase
+
+ // Legacy constants (kept for compatibility with existing code paths)
+ FrontierBlockReward = big.NewInt(5e+18)
+ ByzantiumBlockReward = big.NewInt(3e+18)
+ ConstantinopleBlockReward = big.NewInt(2e+18)
+ WorldLandBlockReward = big.NewInt(4e+18)
+
+ HALVING_INTERVAL = uint64(6307200) // Block per year * 2year (legacy)
+ MATURITY_INTERVAL = uint64(3153600) // Block per year (legacy)
+
+ SumRewardUntilMaturity = big.NewInt(47304000) // Total supply until maturity (legacy)
+
+ MaxHalving = int64(4)
+
+ maxUncles = 2 // Maximum number of uncles allowed in a single block
+ allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
+
+)
+
+// Various error messages to mark blocks invalid. These should be private to
+// prevent engine specific errors from being referenced in the remainder of the
+// codebase, inherently breaking if the engine is swapped out. Please put common
+// error types into the consensus package.
+var (
+ errLargeBlockTime = errors.New("timestamp too big")
+ errZeroBlockTime = errors.New("timestamp equals parent's")
+ errTooManyUncles = errors.New("too many uncles")
+ errDuplicateUncle = errors.New("duplicate uncle")
+ errUncleIsAncestor = errors.New("uncle is ancestor")
+ errDanglingUncle = errors.New("uncle's parent is not ancestor")
+ errInvalidDifficulty = errors.New("non-positive difficulty")
+ errInvalidMixDigest = errors.New("invalid mix digest")
+ errInvalidPoW = errors.New("invalid proof-of-work")
+)
+
+// Author implements consensus.Engine, returning the header's coinbase as the
+// proof-of-work verified author of the block.
+func (ecc *ECC) Author(header *types.Header) (common.Address, error) {
+ return header.Coinbase, nil
+}
+
+// VerifyHeader checks whether a header conforms to the consensus rules of the
+// stock Ethereum ecc engine.
+func (ecc *ECC) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
+ // If we're running a full engine faking, accept any input as valid
+ if ecc.config.PowMode == ModeFullFake {
+ return nil
+ }
+ // Short circuit if the header is known, or it's parent not
+ number := header.Number.Uint64()
+ if chain.GetHeader(header.Hash(), number) != nil {
+ return nil
+ }
+ parent := chain.GetHeader(header.ParentHash, number-1)
+ if parent == nil {
+ return consensus.ErrUnknownAncestor
+ }
+ // Sanity checks passed, do a proper verification
+ return ecc.verifyHeader(chain, header, parent, false, seal, time.Now().Unix())
+}
+
+// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
+// concurrently. The method returns a quit channel to abort the operations and
+// a results channel to retrieve the async verifications.
+func (ecc *ECC) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
+ // If we're running a full engine faking, accept any input as valid
+ if ecc.config.PowMode == ModeFullFake || len(headers) == 0 {
+ abort, results := make(chan struct{}), make(chan error, len(headers))
+ for i := 0; i < len(headers); i++ {
+ results <- nil
+ }
+ return abort, results
+ }
+ // Spawn as many workers as allowed threads
+ workers := runtime.GOMAXPROCS(0)
+ if len(headers) < workers {
+ workers = len(headers)
+ }
+
+ // Create a task channel and spawn the verifiers
+ var (
+ inputs = make(chan int)
+ done = make(chan int, workers)
+ errors = make([]error, len(headers))
+ abort = make(chan struct{})
+ unixNow = time.Now().Unix()
+ )
+ for i := 0; i < workers; i++ {
+ go func() {
+ for index := range inputs {
+ errors[index] = ecc.verifyHeaderWorker(chain, headers, seals, index, unixNow)
+ done <- index
+ }
+ }()
+ }
+
+ errorsOut := make(chan error, len(headers))
+ go func() {
+ defer close(inputs)
+ var (
+ in, out = 0, 0
+ checked = make([]bool, len(headers))
+ inputs = inputs
+ )
+ for {
+ select {
+ case inputs <- in:
+ if in++; in == len(headers) {
+ // Reached end of headers. Stop sending to workers.
+ inputs = nil
+ }
+ case index := <-done:
+ for checked[index] = true; checked[out]; out++ {
+ errorsOut <- errors[out]
+ if out == len(headers)-1 {
+ return
+ }
+ }
+ case <-abort:
+ return
+ }
+ }
+ }()
+ return abort, errorsOut
+}
+
+func (ecc *ECC) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, index int, unixNow int64) error {
+ var parent *types.Header
+ if index == 0 {
+ parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
+ } else if headers[index-1].Hash() == headers[index].ParentHash {
+ parent = headers[index-1]
+ }
+ if parent == nil {
+ return consensus.ErrUnknownAncestor
+ }
+ return ecc.verifyHeader(chain, headers[index], parent, false, seals[index], unixNow)
+}
+
+// VerifyUncles verifies that the given block's uncles conform to the consensus
+// rules of the stock Ethereum ecc engine.
+func (ecc *ECC) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
+ // If we're running a full engine faking, accept any input as valid
+ if ecc.config.PowMode == ModeFullFake {
+ return nil
+ }
+ // Verify that there are at most 2 uncles included in this block
+ if len(block.Uncles()) > maxUncles {
+ return errTooManyUncles
+ }
+ if len(block.Uncles()) == 0 {
+ return nil
+ }
+ // Gather the set of past uncles and ancestors
+ uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header)
+
+ number, parent := block.NumberU64()-1, block.ParentHash()
+
+ for i := 0; i < 7; i++ {
+ ancestorHeader := chain.GetHeader(parent, number)
+ if ancestorHeader == nil {
+ break
+ }
+ ancestors[parent] = ancestorHeader
+ // If the ancestor doesn't have any uncles, we don't have to iterate them
+ if ancestorHeader.UncleHash != types.EmptyUncleHash {
+ // Need to add those uncles to the banned list too
+ ancestor := chain.GetBlock(parent, number)
+ if ancestor == nil {
+ break
+ }
+ for _, uncle := range ancestor.Uncles() {
+ uncles.Add(uncle.Hash())
+ }
+ }
+ parent, number = ancestorHeader.ParentHash, number-1
+ }
+ ancestors[block.Hash()] = block.Header()
+ uncles.Add(block.Hash())
+
+ // Verify each of the uncles that it's recent, but not an ancestor
+ for _, uncle := range block.Uncles() {
+ // Make sure every uncle is rewarded only once
+ hash := uncle.Hash()
+ if uncles.Contains(hash) {
+ return errDuplicateUncle
+ }
+ uncles.Add(hash)
+
+ // Make sure the uncle has a valid ancestry
+ if ancestors[hash] != nil {
+ return errUncleIsAncestor
+ }
+ if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
+ return errDanglingUncle
+ }
+ if err := ecc.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true, time.Now().Unix()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// verifyHeader checks whether a header conforms to the consensus rules of the
+// stock Ethereum ecc engine.
+// See YP section 4.3.4. "Block Header Validity"
+func (ecc *ECC) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, seal bool, unixNow int64) error {
+ // Ensure that the header's extra-data section is of a reasonable size
+ if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
+ return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
+ }
+ // Verify the header's timestamp
+ if !uncle {
+ if header.Time > uint64(unixNow+allowedFutureBlockTimeSeconds) {
+ //log.Println(unixNow)
+ //log.Println(allowedFutureBlockTimeSeconds)
+ //log.Println(header.Time)
+ return consensus.ErrFutureBlock
+ }
+ }
+
+ if header.Time <= parent.Time {
+ return errZeroBlockTime
+ }
+ // Verify the block's difficulty based in it's timestamp and parent's difficulty
+ expectDiff := ecc.CalcDifficulty(chain, header.Time, parent)
+
+ if expectDiff.Cmp(header.Difficulty) != 0 {
+ return fmt.Errorf("invalid ecc difficulty: have %v, want %v", header.Difficulty, expectDiff)
+ }
+
+ // Verify that the gas limit is <= 2^63-1
+ if header.GasLimit > params.MaxGasLimit {
+ return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit)
+ }
+ // Verify that the gasUsed is <= gasLimit
+ if header.GasUsed > header.GasLimit {
+ return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
+ }
+
+ // Verify the block's gas usage and (if applicable) verify the base fee.
+ if !chain.Config().IsLondon(header.Number) {
+ // Verify BaseFee not present before EIP-1559 fork.
+ if header.BaseFee != nil {
+ return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee)
+ }
+ if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
+ return err
+ }
+ } else if err := misc.VerifyEip1559Header(chain.Config(), parent, header); err != nil {
+ // Verify the header's EIP-1559 attributes.
+ return err
+ }
+ // Verify that the block number is parent's +1
+ if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
+ return consensus.ErrInvalidNumber
+ }
+ // Verify the engine specific seal securing the block
+ if seal {
+ if err := ecc.verifySeal(chain, header); err != nil {
+ return err
+ }
+ }
+ // If all checks passed, validate any special fields for hard forks
+ if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil {
+ return err
+ }
+ if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil {
+ return err
+ }
+ return nil
+}
+
+// CalcDifficulty is the difficulty adjustment algorithm. It returns
+// the difficulty that a new block should have when created at time
+// given the parent block's time and difficulty.
+func (ecc *ECC) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
+ next := new(big.Int).Add(parent.Number, big1)
+ switch {
+ case chain.Config().IsAnnapurna(next):
+ return calcDifficultyAnnapurna(chain, time, parent)
+ case chain.Config().IsSeoul(next):
+ return calcDifficultySeoul(chain, time, parent)
+
+ //return calcDifficultyFrontier(time, parent)
+ default:
+ //fmt.Println("frontier")
+ return calcDifficultyFrontier(time, parent)
+ }
+
+ //return CalcDifficulty(chain.Config(), time, parent)
+}
+
+// CalcDifficulty is the difficulty adjustment algorithm. It returns
+// the difficulty that a new block should have when created at time
+// given the parent block's time and difficulty.
+/*func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
+ next := new(big.Int).Add(parent.Number, big1)
+ switch {
+ case config.IsSeoul(next):
+ return calcDifficultySeoul(time, parent)
+ default:
+ //fmt.Println("frontier")
+ return calcDifficultyFrontier(time, parent)
+ }
+}*/
+
+// Some weird constants to avoid constant memory allocs for them.
+var (
+ expDiffPeriod = big.NewInt(100000)
+ big1 = big.NewInt(1)
+ big2 = big.NewInt(2)
+ big9 = big.NewInt(9)
+ big10 = big.NewInt(10)
+ bigMinus99 = big.NewInt(-99)
+)
+
+// makeDifficultyCalculator creates a difficultyCalculator with the given bomb-delay.
+// the difficulty is calculated with Byzantium rules, which differs from Homestead in
+// how uncles affect the calculation
+func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int {
+ return MakeLDPCDifficultyCalculator()
+}
+
+// calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the
+// difficulty that a new block should have when created at time given the parent
+// block's time and difficulty. The calculation uses the Frontier rules.
+func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
+ difficultyCalculator := MakeLDPCDifficultyCalculator()
+ return difficultyCalculator(time, parent)
+}
+
+func calcDifficultySeoul(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
+ difficultyCalculator := MakeLDPCDifficultyCalculator_Seoul()
+ //return difficultyCalculator(chain, time, parent)
+ return difficultyCalculator(time, parent)
+}
+
+func calcDifficultyAnnapurna(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
+ difficultyCalculator := MakeLDPCDifficultyCalculatorAnnapurna()
+ //return difficultyCalculator(chain, time, parent)
+ return difficultyCalculator(time, parent)
+}
+
+// Exported for fuzzing
+var FrontierDifficultyCalculator = calcDifficultyFrontier
+var DynamicDifficultyCalculator = makeDifficultyCalculator
+
+// verifySeal checks whether a block satisfies the PoW difficulty requirements,
+// either using the usual ecc cache for it, or alternatively using a full DAG
+// to make remote mining fast.
+func (ecc *ECC) verifySeal(chain consensus.ChainHeaderReader, header *types.Header) error {
+ // If we're running a fake PoW, accept any seal as valid
+ if ecc.config.PowMode == ModeFake || ecc.config.PowMode == ModeFullFake {
+ time.Sleep(ecc.fakeDelay)
+ if ecc.fakeFail == header.Number.Uint64() {
+ return errInvalidPoW
+ }
+ return nil
+ }
+ // If we're running a shared PoW, delegate verification to it
+ if ecc.shared != nil {
+ return ecc.shared.verifySeal(chain, header)
+ }
+ // Ensure that we have a valid difficulty for the block
+ if header.Difficulty.Sign() <= 0 {
+ return errInvalidDifficulty
+ }
+
+ var (
+ digest []byte
+ flag bool
+ )
+ if chain.Config().IsSeoul(header.Number){
+ //fmt.Println("Seoul")
+ flag, _, _, digest = VerifyOptimizedDecodingSeoul(header, ecc.SealHash(header).Bytes())
+ } else{
+ flag, _, _, digest = VerifyOptimizedDecoding(header, ecc.SealHash(header).Bytes())
+ }
+
+ encodedDigest := common.BytesToHash(digest)
+ if !bytes.Equal(header.MixDigest[:], encodedDigest[:]) {
+ return errInvalidMixDigest
+ }
+
+ if flag == false {
+ return errInvalidPoW
+ }
+
+ return nil
+}
+
+// Prepare implements consensus.Engine, initializing the difficulty field of a
+// header to conform to the ecc protocol. The changes are done inline.
+func (ecc *ECC) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
+ parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
+ if parent == nil {
+ return consensus.ErrUnknownAncestor
+ }
+ header.Difficulty = ecc.CalcDifficulty(chain, header.Time, parent)
+
+ return nil
+}
+
+// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
+// setting the final state and assembling the block.
+func (ecc *ECC) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
+ // Accumulate any block and uncle rewards and commit the final state root
+ accumulateRewards(chain.Config(), state, header, uncles)
+ header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
+}
+
+func (ecc *ECC) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
+ // Accumulate any block and uncle rewards and commit the final state root
+ ecc.Finalize(chain, header, state, txs, uncles)
+
+ // Header seems complete, assemble into a block and return
+ return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil
+}
+
+// SealHash returns the hash of a block prior to it being sealed.
+func (ecc *ECC) SealHash(header *types.Header) (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+
+ enc := []interface{}{
+ header.ParentHash,
+ header.UncleHash,
+ header.Coinbase,
+ header.Root,
+ header.TxHash,
+ header.ReceiptHash,
+ header.Bloom,
+ header.Difficulty,
+ header.Number,
+ header.GasLimit,
+ header.GasUsed,
+ header.Time,
+ header.Extra,
+ }
+ if header.BaseFee != nil {
+ enc = append(enc, header.BaseFee)
+ }
+
+ rlp.Encode(hasher, enc)
+ hasher.Sum(hash[:0])
+ return hash
+}
+
+// Some weird constants to avoid constant memory allocs for them.
+var (
+ big8 = big.NewInt(8)
+ big32 = big.NewInt(32)
+)
+
+// AccumulateRewards credits the coinbase of the given block with the mining
+// reward. The total reward consists of the static block reward and rewards for
+// included uncles. The coinbase of each uncle block is also rewarded.
+func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
+ // Select the correct block reward based on chain progression
+ var blockReward = big.NewInt(FrontierBlockReward.Int64())
+
+ if config.IsByzantium(header.Number) {
+ blockReward = ByzantiumBlockReward
+ }
+ if config.IsConstantinople(header.Number) {
+ blockReward = ConstantinopleBlockReward
+ }
+ if config.IsWorldland(header.Number) {
+ blockReward = big.NewInt(WorldLandBlockReward.Int64())
+
+ if config.IsWorldLandHalving(header.Number) {
+ blockHeight := header.Number.Uint64()
+ HalvingLevel := (blockHeight - 1 - config.WorldlandBlock.Uint64()) / HALVING_INTERVAL
+
+ blockReward.Rsh(blockReward, uint(HalvingLevel))
+
+ } else if config.IsWorldLandMaturity(header.Number) {
+ blockHeight := header.Number.Uint64()
+ blockReward = big.NewInt(1e+18)
+
+ MaturityLevel := (blockHeight - 1 - config.HalvingEndTime.Uint64()) / MATURITY_INTERVAL
+
+ blockReward.Mul(blockReward, SumRewardUntilMaturity)
+ blockReward.Div(blockReward, new(big.Int).SetUint64(MATURITY_INTERVAL))
+
+ blockReward.Mul(blockReward, big.NewInt(4))
+ blockReward.Div(blockReward, big.NewInt(100))
+
+ for i := 0; i < int(MaturityLevel); i++ {
+ blockReward.Mul(blockReward, big.NewInt(104))
+ blockReward.Div(blockReward, big.NewInt(100))
+ }
+ }
+ }
+ // Beta network reward: 20 tokens per block with 4-year halving
+ // 80% to miner, 20% to treasury
+ // No uncle rewards - fixed total per block
+ if config.IsBeta(header.Number) {
+ blockReward = new(big.Int).Set(BetaBlockReward)
+
+ if config.IsBetaHalving(header.Number) {
+ // Halving phase: reward halves every BETA_HALVING_INTERVAL blocks
+ blockHeight := header.Number.Uint64()
+ HalvingLevel := (blockHeight - 1 - config.BetaBlock.Uint64()) / BETA_HALVING_INTERVAL
+
+ blockReward.Rsh(blockReward, uint(HalvingLevel))
+
+ } else if config.IsBetaMaturity(header.Number) {
+ // Maturity phase: 4% annual growth after halvings end
+ blockHeight := header.Number.Uint64()
+ blockReward = big.NewInt(1e+18)
+
+ MaturityLevel := (blockHeight - 1 - config.HalvingEndTime.Uint64()) / BETA_MATURITY_INTERVAL
+
+ blockReward.Mul(blockReward, BetaSumRewardUntilMaturity)
+ blockReward.Div(blockReward, new(big.Int).SetUint64(BETA_MATURITY_INTERVAL))
+
+ blockReward.Mul(blockReward, big.NewInt(4))
+ blockReward.Div(blockReward, big.NewInt(100))
+
+ for i := 0; i < int(MaturityLevel); i++ {
+ blockReward.Mul(blockReward, big.NewInt(104))
+ blockReward.Div(blockReward, big.NewInt(100))
+ }
+ }
+
+ // Calculate treasury share (20%) and miner share (80%)
+ treasuryReward := new(big.Int).Div(blockReward, big.NewInt(5)) // 20% = 1/5
+ minerReward := new(big.Int).Sub(blockReward, treasuryReward) // 80% = remaining
+
+ // Send rewards - no uncle rewards for Beta network
+ state.AddBalance(BetaTreasuryAddress, treasuryReward)
+ state.AddBalance(header.Coinbase, minerReward)
+ return
+ }
+
+ // Accumulate the rewards for the miner and any included uncles (non-Beta networks)
+ reward := new(big.Int).Set(blockReward)
+ r := new(big.Int)
+ for _, uncle := range uncles {
+ r.Add(uncle.Number, big8)
+ r.Sub(r, header.Number)
+ r.Mul(r, blockReward)
+ r.Div(r, big8)
+ state.AddBalance(uncle.Coinbase, r)
+
+ r.Div(blockReward, big32)
+ reward.Add(reward, r)
+ }
+ state.AddBalance(header.Coinbase, reward)
+}
\ No newline at end of file
diff --git a/consensus/eccbeta/consensus_test.go b/consensus/eccbeta/consensus_test.go
new file mode 100644
index 000000000000..4ed859d64325
--- /dev/null
+++ b/consensus/eccbeta/consensus_test.go
@@ -0,0 +1,156 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package eccbeta
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/common/math"
+ "github.com/cryptoecc/WorldLand/core/types"
+ "github.com/cryptoecc/WorldLand/params"
+)
+
+type diffTest struct {
+ ParentTimestamp uint64
+ ParentDifficulty *big.Int
+ CurrentTimestamp uint64
+ CurrentBlocknumber *big.Int
+ CurrentDifficulty *big.Int
+}
+
+func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
+ var ext struct {
+ ParentTimestamp string
+ ParentDifficulty string
+ CurrentTimestamp string
+ CurrentBlocknumber string
+ CurrentDifficulty string
+ }
+ if err := json.Unmarshal(b, &ext); err != nil {
+ return err
+ }
+
+ d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp)
+ d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty)
+ d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp)
+ d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber)
+ d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty)
+
+ return nil
+}
+
+func TestCalcDifficulty(t *testing.T) {
+ file, err := os.Open(filepath.Join("..", "..", "tests", "testdata", "BasicTests", "difficulty.json"))
+ if err != nil {
+ t.Skip(err)
+ }
+ defer file.Close()
+
+ tests := make(map[string]diffTest)
+ err = json.NewDecoder(file).Decode(&tests)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1150000)}
+
+ for name, test := range tests {
+ number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
+ diff := CalcDifficulty(config, test.CurrentTimestamp, &types.Header{
+ Number: number,
+ Time: test.ParentTimestamp,
+ Difficulty: test.ParentDifficulty,
+ })
+ if diff.Cmp(test.CurrentDifficulty) != 0 {
+ t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
+ }
+ }
+}
+
+func TestDecodingVerification(t *testing.T) {
+ for i := 0; i < 8; i++ {
+ ecc := ECC{}
+ header := new(types.Header)
+ header.Difficulty = ProbToDifficulty(Table[0].miningProb)
+ hash := ecc.SealHash(header).Bytes()
+
+ _, hashVector, outputWord, LDPCNonce, digest := RunOptimizedConcurrencyLDPC(header, hash)
+
+ headerForTest := types.CopyHeader(header)
+ headerForTest.MixDigest = common.BytesToHash(digest)
+ headerForTest.Nonce = types.EncodeNonce(LDPCNonce)
+ hashForTest := ecc.SealHash(headerForTest).Bytes()
+
+ flag, hashVectorOfVerification, outputWordOfVerification, digestForValidation := VerifyOptimizedDecoding(headerForTest, hashForTest)
+
+ encodedDigestForValidation := common.BytesToHash(digestForValidation)
+
+ //fmt.Printf("%+v\n", header)
+ //fmt.Printf("Hash : %v\n", hash)
+ //fmt.Println()
+
+ //fmt.Printf("%+v\n", headerForTest)
+ //fmt.Printf("headerForTest : %v\n", headerForTest)
+ //fmt.Println()
+
+ // * means padding for compare easily
+ if flag && bytes.Equal(headerForTest.MixDigest[:], encodedDigestForValidation[:]) {
+ fmt.Printf("Hash vector ** ************ : %v\n", hashVector)
+ fmt.Printf("Hash vector of verification : %v\n", hashVectorOfVerification)
+
+ fmt.Printf("Outputword ** ************ : %v\n", outputWord)
+ fmt.Printf("Outputword of verification : %v\n", outputWordOfVerification)
+
+ fmt.Printf("LDPC Nonce : %v\n", LDPCNonce)
+ fmt.Printf("Digest : %v\n", headerForTest.MixDigest[:])
+ /*
+ t.Logf("Hash vector : %v\n", hashVector)
+ t.Logf("Outputword : %v\n", outputWord)
+ t.Logf("LDPC Nonce : %v\n", LDPCNonce)
+ t.Logf("Digest : %v\n", header.MixDigest[:])
+ */
+ } else {
+ fmt.Printf("Hash vector ** ************ : %v\n", hashVector)
+ fmt.Printf("Hash vector of verification : %v\n", hashVectorOfVerification)
+
+ fmt.Printf("Outputword ** ************ : %v\n", outputWord)
+ fmt.Printf("Outputword of verification : %v\n", outputWordOfVerification)
+
+ fmt.Printf("flag : %v\n", flag)
+ fmt.Printf("Digest compare result : %v\n", bytes.Equal(headerForTest.MixDigest[:], encodedDigestForValidation[:]))
+ fmt.Printf("Digest *** ********** : %v\n", headerForTest.MixDigest[:])
+ fmt.Printf("Digest for validation : %v\n", encodedDigestForValidation)
+
+ t.Errorf("Test Fail")
+ /*
+ t.Errorf("flag : %v\n", flag)
+ t.Errorf("Digest compare result : %v", bytes.Equal(header.MixDigest[:], digestForValidation)
+ t.Errorf("Digest : %v\n", digest)
+ t.Errorf("Digest for validation : %v\n", digestForValidation)
+ */
+ }
+ //t.Logf("\n")
+ fmt.Println()
+ }
+}
diff --git a/consensus/eccbeta/sealer.go b/consensus/eccbeta/sealer.go
new file mode 100644
index 000000000000..d512179ef1dc
--- /dev/null
+++ b/consensus/eccbeta/sealer.go
@@ -0,0 +1,584 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package eccbeta
+
+import (
+ "bytes"
+ "context"
+ crand "crypto/rand"
+ "encoding/binary"
+ "encoding/json"
+ "errors"
+ "math"
+ "math/big"
+ "math/rand"
+ "net/http"
+ "runtime"
+ "sync"
+ "time"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/common/hexutil"
+ "github.com/cryptoecc/WorldLand/consensus"
+ "github.com/cryptoecc/WorldLand/core/types"
+ "github.com/cryptoecc/WorldLand/crypto"
+ "github.com/cryptoecc/WorldLand/log"
+)
+
+const (
+ // staleThreshold is the maximum depth of the acceptable stale but valid ecc solution.
+ staleThreshold = 7
+)
+
+var (
+ errNoMiningWork = errors.New("no mining work available yet")
+ errInvalidSealResult = errors.New("invalid or stale proof-of-work solution")
+)
+
+// Seal implements consensus.Engine, attempting to find a nonce that satisfies
+// the block's difficulty requirements.
+func (ecc *ECC) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
+ // If we're running a fake PoW, simply return a 0 nonce immediately
+ if ecc.config.PowMode == ModeFake || ecc.config.PowMode == ModeFullFake {
+ header := block.Header()
+ header.Nonce, header.MixDigest = types.BlockNonce{}, common.Hash{}
+ select {
+ case results <- block.WithSeal(header):
+ default:
+ log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ecc.SealHash(block.Header()))
+ }
+ return nil
+ }
+ // If we're running a shared PoW, delegate sealing to it
+ if ecc.shared != nil {
+ return ecc.shared.Seal(chain, block, results, stop)
+ }
+ // Create a runner and the multiple search threads it directs
+ abort := make(chan struct{})
+
+ ecc.lock.Lock()
+ threads := ecc.threads
+ if ecc.rand == nil {
+ seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
+ if err != nil {
+ ecc.lock.Unlock()
+ return err
+ }
+ ecc.rand = rand.New(rand.NewSource(seed.Int64()))
+ }
+ ecc.lock.Unlock()
+ if threads == 0 {
+ threads = runtime.NumCPU()
+ }
+ if threads < 0 {
+ threads = 0 // Allows disabling local mining without extra logic around local/remote
+ }
+ // Push new work to remote sealer
+ if ecc.remote != nil {
+ ecc.remote.workCh <- &sealTask{block: block, results: results}
+ }
+ var (
+ pend sync.WaitGroup
+ locals = make(chan *types.Block)
+ )
+
+ for i := 0; i < threads; i++ {
+ pend.Add(1)
+ go func(id int, nonce uint64) {
+ defer pend.Done()
+ //ecc.mine(block, id, nonce, abort, locals)
+ if chain.Config().IsSeoul(block.Header().Number){
+ ecc.mine_seoul(block, id, nonce, abort, locals)
+ } else{
+ ecc.mine(block, id, nonce, abort, locals)
+ }
+ }(i, uint64(ecc.rand.Int63()))
+ }
+
+ // Wait until sealing is terminated or a nonce is found
+ go func() {
+ var result *types.Block
+ select {
+ case <-stop:
+ // Outside abort, stop all miner threads
+ close(abort)
+ case result = <-locals:
+ // One of the threads found a block, abort all others
+ select {
+ case results <- result:
+ default:
+ ecc.config.Log.Warn("Sealing result is not read by miner", "mode", "local", "sealhash", ecc.SealHash(block.Header()))
+ }
+ close(abort)
+ case <-ecc.update:
+ // Thread count was changed on user request, restart
+ close(abort)
+ if err := ecc.Seal(chain, block, results, stop); err != nil {
+ ecc.config.Log.Error("Failed to restart sealing after update", "err", err)
+ }
+ }
+ // Wait for all miners to terminate and return the block
+ pend.Wait()
+ }()
+
+ return nil
+}
+
+// mine is the actual proof-of-work miner that searches for a nonce starting from
+// seed that results in correct final block difficulty.
+func (ecc *ECC) mine(block *types.Block, id int, seed uint64, abort chan struct{}, found chan *types.Block) {
+ // Extract some data from the header
+ var (
+ header = block.Header()
+ hash = ecc.SealHash(header).Bytes()
+ )
+ // Start generating random nonces until we abort or find a good one
+ var (
+ total_attempts = int64(0)
+ attempts = int64(0)
+ nonce = seed
+ )
+ logger := log.New("miner", id)
+ logger.Trace("Started ecc search for new nonces", "seed", seed)
+search:
+ for {
+ select {
+ case <-abort:
+ // Mining terminated, update stats and abort
+ logger.Trace("ecc nonce search aborted", "attempts", nonce-seed)
+ ecc.hashrate.Mark(attempts)
+ break search
+
+ default:
+ // We don't have to update hash rate on every nonce, so update after after 2^X nonces
+ total_attempts = total_attempts + 64
+ attempts = attempts + 64
+ if (attempts % (1 << 15)) == 0 {
+ ecc.hashrate.Mark(attempts)
+ attempts = 0
+ }
+ // Compute the PoW value of this nonce
+
+ flag, _, outputWord, LDPCNonce, digest := RunOptimizedConcurrencyLDPC(header, hash)
+
+ // Correct nonce found, create a new header with it
+ if flag == true {
+ //level := SearchLevel_Seoul(header.Difficulty)
+ //fmt.Printf("level: %v\n", level)
+ //fmt.Printf("total attempts: %v\n", total_attempts)
+ //fmt.Printf("hashrate: %v\n", ecc.Hashrate())
+ //fmt.Printf("Codeword found with nonce = %d\n", LDPCNonce)
+ //fmt.Printf("Codeword : %d\n", outputWord)
+
+ header = types.CopyHeader(header)
+ header.MixDigest = common.BytesToHash(digest)
+ header.Nonce = types.EncodeNonce(LDPCNonce)
+
+ //convert codeword
+ var codeword []byte
+ var codeVal byte
+ for i, v := range outputWord {
+ codeVal |= byte(v) << (7 - i%8)
+ if i%8 == 7 {
+ codeword = append(codeword, codeVal)
+ codeVal = 0
+ }
+ }
+ if len(outputWord)%8 != 0 {
+ codeword = append(codeword, codeVal)
+ }
+ header.Codeword = make([]byte, len(codeword))
+ copy(header.Codeword, codeword)
+ //fmt.Printf("header: %v\n", header)
+ //fmt.Printf("header Codeword : %v\n", header.Codeword)
+
+ // Seal and return a block (if still needed)
+ select {
+ case found <- block.WithSeal(header):
+ logger.Trace("ecc nonce found and reported", "LDPCNonce", LDPCNonce)
+ case <-abort:
+ logger.Trace("ecc nonce found but discarded", "LDPCNonce", LDPCNonce)
+ }
+ break search
+ }
+ }
+ }
+}
+
+func (ecc *ECC) mine_seoul(block *types.Block, id int, seed uint64, abort chan struct{}, found chan *types.Block) {
+ // Extract some data from the header
+ var (
+ header = block.Header()
+ hash = ecc.SealHash(header).Bytes()
+ )
+ // Start generating random nonces until we abort or find a good one
+ var (
+ total_attempts = int64(0)
+ attempts = int64(0)
+ nonce = seed
+ )
+ logger := log.New("miner", id)
+ logger.Trace("Started ecc search for new nonces", "seed", seed)
+
+ parameters, _ := setParameters_Seoul(header)
+ //fmt.Println(parameters)
+ H := generateH(parameters)
+ colInRow, rowInCol := generateQ(parameters, H)
+
+search:
+ for {
+ select {
+ case <-abort:
+ // Mining terminated, update stats and abort
+ logger.Trace("ecc nonce search aborted", "attempts", nonce-seed)
+ ecc.hashrate.Mark(attempts)
+ break search
+
+ default:
+ // We don't have to update hash rate on every nonce, so update after after 2^X nonces
+ total_attempts = total_attempts + 1
+ attempts = attempts + 1
+ if (attempts % (1 << 15)) == 0 {
+ ecc.hashrate.Mark(attempts)
+ attempts = 0
+ }
+
+ digest := make([]byte, 40)
+ copy(digest, hash)
+ binary.LittleEndian.PutUint64(digest[32:], nonce)
+ digest = crypto.Keccak512(digest)
+ //fmt.Printf("nonce: %v\n", digest)
+
+ goRoutineHashVector := generateHv(parameters, digest)
+ goRoutineHashVector, goRoutineOutputWord, _ := OptimizedDecodingSeoul(parameters, goRoutineHashVector, H, rowInCol, colInRow)
+
+ flag, _ := MakeDecision_Seoul(header, colInRow, goRoutineOutputWord)
+ //fmt.Printf("nonce: %v\n", nonce)
+ //fmt.Printf("nonce: %v\n", weight)
+
+ if flag == true {
+ //hashVector := goRoutineHashVector
+ outputWord := goRoutineOutputWord
+
+ //level := SearchLevel_Seoul(header.Difficulty)
+ /*fmt.Printf("level: %v\n", level)
+ fmt.Printf("total attempts: %v\n", total_attempts)
+ fmt.Printf("hashrate: %v\n", ecc.Hashrate())
+ fmt.Printf("Codeword found with nonce = %d\n", nonce)
+ fmt.Printf("Codeword : %d\n", outputWord)*/
+
+ header = types.CopyHeader(header)
+ header.CodeLength = uint64(parameters.n)
+ header.MixDigest = common.BytesToHash(digest)
+ header.Nonce = types.EncodeNonce(nonce)
+
+ //convert codeword
+ var codeword []byte
+ var codeVal byte
+ for i, v := range outputWord {
+ codeVal |= byte(v) << (7 - i%8)
+ if i%8 == 7 {
+ codeword = append(codeword, codeVal)
+ codeVal = 0
+ }
+ }
+ if len(outputWord)%8 != 0 {
+ codeword = append(codeword, codeVal)
+ }
+ header.Codeword = make([]byte, len(codeword))
+ copy(header.Codeword, codeword)
+ //fmt.Printf("header: %v\n", header)
+ //fmt.Printf("header Codeword : %v\n", header.Codeword)
+
+ // Seal and return a block (if still needed)
+ select {
+ case found <- block.WithSeal(header):
+ logger.Trace("ecc nonce found and reported", "LDPCNonce", nonce)
+ case <-abort:
+ logger.Trace("ecc nonce found but discarded", "LDPCNonce", nonce)
+ }
+ break search
+ }
+ nonce++
+ }
+ }
+}
+
+
+//GPU MINING... NEED TO UPDTAE
+// This is the timeout for HTTP requests to notify external miners.
+const remoteSealerTimeout = 1 * time.Second
+
+type remoteSealer struct {
+ works map[common.Hash]*types.Block
+ rates map[common.Hash]hashrate
+ currentBlock *types.Block
+ currentWork [4]string
+ notifyCtx context.Context
+ cancelNotify context.CancelFunc // cancels all notification requests
+ reqWG sync.WaitGroup // tracks notification request goroutines
+
+ ecc *ECC
+ noverify bool
+ notifyURLs []string
+ results chan<- *types.Block
+ workCh chan *sealTask // Notification channel to push new work and relative result channel to remote sealer
+ fetchWorkCh chan *sealWork // Channel used for remote sealer to fetch mining work
+ submitWorkCh chan *mineResult // Channel used for remote sealer to submit their mining result
+ fetchRateCh chan chan uint64 // Channel used to gather submitted hash rate for local or remote sealer.
+ submitRateCh chan *hashrate // Channel used for remote sealer to submit their mining hashrate
+ requestExit chan struct{}
+ exitCh chan struct{}
+}
+
+// sealTask wraps a seal block with relative result channel for remote sealer thread.
+type sealTask struct {
+ block *types.Block
+ results chan<- *types.Block
+}
+
+// mineResult wraps the pow solution parameters for the specified block.
+type mineResult struct {
+ nonce types.BlockNonce
+ mixDigest common.Hash
+ hash common.Hash
+
+ errc chan error
+}
+
+// hashrate wraps the hash rate submitted by the remote sealer.
+type hashrate struct {
+ id common.Hash
+ ping time.Time
+ rate uint64
+
+ done chan struct{}
+}
+
+// sealWork wraps a seal work package for remote sealer.
+type sealWork struct {
+ errc chan error
+ res chan [4]string
+}
+
+func startRemoteSealer(ecc *ECC, urls []string, noverify bool) *remoteSealer {
+ ctx, cancel := context.WithCancel(context.Background())
+ s := &remoteSealer{
+ ecc: ecc,
+ noverify: noverify,
+ notifyURLs: urls,
+ notifyCtx: ctx,
+ cancelNotify: cancel,
+ works: make(map[common.Hash]*types.Block),
+ rates: make(map[common.Hash]hashrate),
+ workCh: make(chan *sealTask),
+ fetchWorkCh: make(chan *sealWork),
+ submitWorkCh: make(chan *mineResult),
+ fetchRateCh: make(chan chan uint64),
+ submitRateCh: make(chan *hashrate),
+ requestExit: make(chan struct{}),
+ exitCh: make(chan struct{}),
+ }
+ go s.loop()
+ return s
+}
+
+func (s *remoteSealer) loop() {
+ defer func() {
+ s.ecc.config.Log.Trace("ECC remote sealer is exiting")
+ s.cancelNotify()
+ s.reqWG.Wait()
+ close(s.exitCh)
+ }()
+
+ ticker := time.NewTicker(5 * time.Second)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case work := <-s.workCh:
+ // Update current work with new received block.
+ // Note same work can be past twice, happens when changing CPU threads.
+ s.results = work.results
+ s.makeWork(work.block)
+ s.notifyWork()
+
+ case work := <-s.fetchWorkCh:
+ // Return current mining work to remote miner.
+ if s.currentBlock == nil {
+ work.errc <- errNoMiningWork
+ } else {
+ work.res <- s.currentWork
+ }
+
+ case result := <-s.submitWorkCh:
+ // Verify submitted PoW solution based on maintained mining blocks.
+ if s.submitWork(result.nonce, result.mixDigest, result.hash) {
+ result.errc <- nil
+ } else {
+ result.errc <- errInvalidSealResult
+ }
+
+ case result := <-s.submitRateCh:
+ // Trace remote sealer's hash rate by submitted value.
+ s.rates[result.id] = hashrate{rate: result.rate, ping: time.Now()}
+ close(result.done)
+
+ case req := <-s.fetchRateCh:
+ // Gather all hash rate submitted by remote sealer.
+ var total uint64
+ for _, rate := range s.rates {
+ // this could overflow
+ total += rate.rate
+ }
+ req <- total
+
+ case <-ticker.C:
+ // Clear stale submitted hash rate.
+ for id, rate := range s.rates {
+ if time.Since(rate.ping) > 10*time.Second {
+ delete(s.rates, id)
+ }
+ }
+ // Clear stale pending blocks
+ if s.currentBlock != nil {
+ for hash, block := range s.works {
+ if block.NumberU64()+staleThreshold <= s.currentBlock.NumberU64() {
+ delete(s.works, hash)
+ }
+ }
+ }
+
+ case <-s.requestExit:
+ return
+ }
+ }
+}
+
+// makeWork creates a work package for external miner.
+//
+// The work package consists of 3 strings:
+// result[0], 32 bytes hex encoded current block header pow-hash
+// result[1], 32 bytes hex encoded seed hash used for DAG
+// result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
+// result[3], hex encoded block number
+func (s *remoteSealer) makeWork(block *types.Block) {
+ hash := s.ecc.SealHash(block.Header())
+ s.currentWork[0] = hash.Hex()
+ s.currentWork[1] = common.BytesToHash(SeedHash(block.NumberU64())).Hex()
+ s.currentWork[2] = common.BytesToHash(new(big.Int).Div(two256, block.Difficulty()).Bytes()).Hex()
+ s.currentWork[3] = hexutil.EncodeBig(block.Number())
+
+ // Trace the seal work fetched by remote sealer.
+ s.currentBlock = block
+ s.works[hash] = block
+}
+
+// notifyWork notifies all the specified mining endpoints of the availability of
+// new work to be processed.
+func (s *remoteSealer) notifyWork() {
+ work := s.currentWork
+
+ // Encode the JSON payload of the notification. When NotifyFull is set,
+ // this is the complete block header, otherwise it is a JSON array.
+ var blob []byte
+ if s.ecc.config.NotifyFull {
+ blob, _ = json.Marshal(s.currentBlock.Header())
+ } else {
+ blob, _ = json.Marshal(work)
+ }
+
+ s.reqWG.Add(len(s.notifyURLs))
+ for _, url := range s.notifyURLs {
+ go s.sendNotification(s.notifyCtx, url, blob, work)
+ }
+}
+
+func (s *remoteSealer) sendNotification(ctx context.Context, url string, json []byte, work [4]string) {
+ defer s.reqWG.Done()
+
+ req, err := http.NewRequest("POST", url, bytes.NewReader(json))
+ if err != nil {
+ s.ecc.config.Log.Warn("Can't create remote miner notification", "err", err)
+ return
+ }
+ ctx, cancel := context.WithTimeout(ctx, remoteSealerTimeout)
+ defer cancel()
+ req = req.WithContext(ctx)
+ req.Header.Set("Content-Type", "application/json")
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ s.ecc.config.Log.Warn("Failed to notify remote miner", "err", err)
+ } else {
+ s.ecc.config.Log.Trace("Notified remote miner", "miner", url, "hash", work[0], "target", work[2])
+ resp.Body.Close()
+ }
+}
+
+// submitWork verifies the submitted pow solution, returning
+// whether the solution was accepted or not (not can be both a bad pow as well as
+// any other error, like no pending work or stale mining result).
+func (s *remoteSealer) submitWork(nonce types.BlockNonce, mixDigest common.Hash, sealhash common.Hash) bool {
+ if s.currentBlock == nil {
+ s.ecc.config.Log.Error("Pending work without block", "sealhash", sealhash)
+ return false
+ }
+ // Make sure the work submitted is present
+ block := s.works[sealhash]
+ if block == nil {
+ s.ecc.config.Log.Warn("Work submitted but none pending", "sealhash", sealhash, "curnumber", s.currentBlock.NumberU64())
+ return false
+ }
+ // Verify the correctness of submitted result.
+ header := block.Header()
+ header.Nonce = nonce
+ header.MixDigest = mixDigest
+
+ start := time.Now()
+ if !s.noverify {
+ if err := s.ecc.verifySeal(nil, header); err != nil {
+ s.ecc.config.Log.Warn("Invalid proof-of-work submitted", "sealhash", sealhash, "elapsed", common.PrettyDuration(time.Since(start)), "err", err)
+ return false
+ }
+ }
+ // Make sure the result channel is assigned.
+ if s.results == nil {
+ s.ecc.config.Log.Warn("Eccresult channel is empty, submitted mining result is rejected")
+ return false
+ }
+ s.ecc.config.Log.Trace("Verified correct proof-of-work", "sealhash", sealhash, "elapsed", common.PrettyDuration(time.Since(start)))
+
+ // Solutions seems to be valid, return to the miner and notify acceptance.
+ solution := block.WithSeal(header)
+
+ // The submitted solution is within the scope of acceptance.
+ if solution.NumberU64()+staleThreshold > s.currentBlock.NumberU64() {
+ select {
+ case s.results <- solution:
+ s.ecc.config.Log.Debug("Work submitted is acceptable", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash())
+ return true
+ default:
+ s.ecc.config.Log.Warn("Sealing result is not read by miner", "mode", "remote", "sealhash", sealhash)
+ return false
+ }
+ }
+ // The submitted block is too old to accept, drop it.
+ s.ecc.config.Log.Warn("Work submitted is too old", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash())
+ return false
+}
+
diff --git a/consensus/eccbeta/sealer_test.go b/consensus/eccbeta/sealer_test.go
new file mode 100644
index 000000000000..be434bdbcb19
--- /dev/null
+++ b/consensus/eccbeta/sealer_test.go
@@ -0,0 +1,214 @@
+package eccbeta
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "math/big"
+ "net"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/cryptoecc/WorldLand/common"
+ "github.com/cryptoecc/WorldLand/core/types"
+)
+
+// Tests whether remote HTTP servers are correctly notified of new work.
+func TestRemoteNotify(t *testing.T) {
+ // Start a simple webserver to capture notifications
+ sink := make(chan [3]string)
+
+ server := &http.Server{
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ blob, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ t.Fatalf("failed to read miner notification: %v", err)
+ }
+ var work [3]string
+ if err := json.Unmarshal(blob, &work); err != nil {
+ t.Fatalf("failed to unmarshal miner notification: %v", err)
+ }
+ sink <- work
+ }),
+ }
+ // Open a custom listener to extract its local address
+ listener, err := net.Listen("tcp", "localhost:0")
+ if err != nil {
+ t.Fatalf("failed to open notification server: %v", err)
+ }
+ defer listener.Close()
+
+ go server.Serve(listener)
+
+ // Wait for server to start listening
+ var tries int
+ for tries = 0; tries < 10; tries++ {
+ conn, _ := net.DialTimeout("tcp", listener.Addr().String(), 1*time.Second)
+ if conn != nil {
+ break
+ }
+ }
+ if tries == 10 {
+ t.Fatal("tcp listener not ready for more than 10 seconds")
+ }
+
+ // Create the custom ecc engine
+ ecc := NewTester([]string{"http://" + listener.Addr().String()}, false)
+ defer ecc.Close()
+
+ // Stream a work task and ensure the notification bubbles out
+ header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)}
+ block := types.NewBlockWithHeader(header)
+
+ ecc.Seal(nil, block, nil, nil)
+ select {
+ case work := <-sink:
+ if want := ecc.SealHash(header).Hex(); work[0] != want {
+ t.Errorf("work packet hash mismatch: have %s, want %s", work[0], want)
+ }
+ //if want := common.BytesToHash(SeedHash(header.Number.Uint64())).Hex(); work[1] != want {
+ if want := header.ParentHash.Hex(); work[1] != want {
+ t.Errorf("work packet seed mismatch: have %s, want %s", work[1], want)
+ }
+ //target := new(big.Int).Div(new(big.Int).Lsh(big.NewInt(1), 256), header.Difficulty)
+ //if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want {
+ // t.Errorf("work packet target mismatch: have %s, want %s", work[2], want)
+ //}
+ case <-time.After(3 * time.Second):
+ t.Fatalf("notification timed out")
+ }
+}
+
+// Tests that pushing work packages fast to the miner doesn't cause any data race
+// issues in the notifications.
+func TestRemoteMultiNotify(t *testing.T) {
+ // Start a simple webserver to capture notifications
+ sink := make(chan [3]string, 64)
+
+ server := &http.Server{
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ blob, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ t.Fatalf("failed to read miner notification: %v", err)
+ }
+ var work [3]string
+ if err := json.Unmarshal(blob, &work); err != nil {
+ t.Fatalf("failed to unmarshal miner notification: %v", err)
+ }
+ sink <- work
+ }),
+ }
+ // Open a custom listener to extract its local address
+ listener, err := net.Listen("tcp", "localhost:0")
+ if err != nil {
+ t.Fatalf("failed to open notification server: %v", err)
+ }
+ defer listener.Close()
+
+ go server.Serve(listener)
+
+ // Create the custom ecc engine
+ ecc := NewTester([]string{"http://" + listener.Addr().String()}, false)
+ defer ecc.Close()
+
+ // Stream a lot of work task and ensure all the notifications bubble out
+ for i := 0; i < cap(sink); i++ {
+ header := &types.Header{Number: big.NewInt(int64(i)), Difficulty: big.NewInt(100)}
+ block := types.NewBlockWithHeader(header)
+
+ ecc.Seal(nil, block, nil, nil)
+ }
+ /*
+ for i := 0; i < cap(sink); i++ {
+ select {
+ case <-sink:
+ case <-time.After(3 * time.Second):
+ t.Fatalf("notification %d timed out", i)
+ }
+ }
+ */
+}
+
+// Tests whether stale solutions are correctly processed.
+func TestStaleSubmission(t *testing.T) {
+ ecc := NewTester(nil, true)
+ defer ecc.Close()
+ api := &API{ecc}
+
+ fakeNonce, fakeDigest := types.BlockNonce{0x01, 0x02, 0x03}, common.HexToHash("deadbeef")
+
+ testcases := []struct {
+ headers []*types.Header
+ submitIndex int
+ submitRes bool
+ }{
+ // Case1: submit solution for the latest mining package
+ {
+ []*types.Header{
+ {ParentHash: common.BytesToHash([]byte{0xa}), Number: big.NewInt(1), Difficulty: big.NewInt(100000000)},
+ },
+ 0,
+ true,
+ },
+ // Case2: submit solution for the previous package but have same parent.
+ {
+ []*types.Header{
+ {ParentHash: common.BytesToHash([]byte{0xb}), Number: big.NewInt(2), Difficulty: big.NewInt(100000000)},
+ {ParentHash: common.BytesToHash([]byte{0xb}), Number: big.NewInt(2), Difficulty: big.NewInt(100000001)},
+ },
+ 0,
+ true,
+ },
+ // Case3: submit stale but acceptable solution
+ {
+ []*types.Header{
+ {ParentHash: common.BytesToHash([]byte{0xc}), Number: big.NewInt(3), Difficulty: big.NewInt(100000000)},
+ {ParentHash: common.BytesToHash([]byte{0xd}), Number: big.NewInt(9), Difficulty: big.NewInt(100000000)},
+ },
+ 0,
+ true,
+ },
+ // Case4: submit very old solution
+ {
+ []*types.Header{
+ {ParentHash: common.BytesToHash([]byte{0xe}), Number: big.NewInt(10), Difficulty: big.NewInt(100000000)},
+ {ParentHash: common.BytesToHash([]byte{0xf}), Number: big.NewInt(17), Difficulty: big.NewInt(100000000)},
+ },
+ 0,
+ false,
+ },
+ }
+ results := make(chan *types.Block, 16)
+
+ for id, c := range testcases {
+ for _, h := range c.headers {
+ ecc.Seal(nil, types.NewBlockWithHeader(h), results, nil)
+ }
+ if res := api.SubmitWork(fakeNonce, ecc.SealHash(c.headers[c.submitIndex]), fakeDigest); res != c.submitRes {
+ t.Errorf("case %d submit result mismatch, want %t, get %t", id+1, c.submitRes, res)
+ }
+ if !c.submitRes {
+ continue
+ }
+ select {
+ case res := <-results:
+ if res.Header().Nonce != fakeNonce {
+ t.Errorf("case %d block nonce mismatch, want %s, get %s", id+1, fakeNonce, res.Header().Nonce)
+ }
+ if res.Header().MixDigest != fakeDigest {
+ t.Errorf("case %d block digest mismatch, want %s, get %s", id+1, fakeDigest, res.Header().MixDigest)
+ }
+ if res.Header().Difficulty.Uint64() != c.headers[c.submitIndex].Difficulty.Uint64() {
+ t.Errorf("case %d block difficulty mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].Difficulty, res.Header().Difficulty)
+ }
+ if res.Header().Number.Uint64() != c.headers[c.submitIndex].Number.Uint64() {
+ t.Errorf("case %d block number mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].Number.Uint64(), res.Header().Number.Uint64())
+ }
+ if res.Header().ParentHash != c.headers[c.submitIndex].ParentHash {
+ t.Errorf("case %d block parent hash mismatch, want %s, get %s", id+1, c.headers[c.submitIndex].ParentHash.Hex(), res.Header().ParentHash.Hex())
+ }
+ case <-time.NewTimer(time.Second).C:
+ t.Errorf("case %d fetch ecc result timeout", id+1)
+ }
+ }
+}
diff --git a/core/genesis.go b/core/genesis.go
index 780a94874f0f..776b6c8f36b9 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -450,6 +450,38 @@ func LoadKaijuConfig(db ethdb.Database, genesis *Genesis) (*params.KaijuConfig,
return nil, nil
}
+func LoadEccbetaConfig(db ethdb.Database, genesis *Genesis) (*params.EccbetaConfig, error) {
+ // Load the stored chain config from the database. It can be nil
+ // in case the database is empty. Notably, we only care about the
+ // chain config corresponds to the canonical chain.
+ stored := rawdb.ReadCanonicalHash(db, 0)
+ if stored != (common.Hash{}) {
+ storedcfg := rawdb.ReadChainConfig(db, stored)
+ if storedcfg != nil {
+ return storedcfg.Eccbeta, nil
+ }
+ }
+ // Load the eccbeta config from the provided genesis specification.
+ if genesis != nil {
+ // Reject invalid genesis spec without valid chain config
+ if genesis.Config == nil {
+ return nil, errGenesisNoConfig
+ }
+ // If the canonical genesis header is present, but the chain
+ // config is missing(initialize the empty leveldb with an
+ // external ancient chain segment), ensure the provided genesis
+ // is matched.
+ if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored {
+ return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
+ }
+ return genesis.Config.Eccbeta, nil
+ }
+ // There is no stored chain config and no new config provided,
+ // In this case the default chain config(mainnet) will be used,
+ // namely ethash is the specified consensus engine, return nil.
+ return nil, nil
+}
+
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
switch {
case g != nil:
@@ -472,6 +504,8 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
return params.GwangjuChainConfig
case ghash == params.MioGenesisHash:
return params.MioChainConfig
+ case ghash == params.BetaGenesisHash:
+ return params.BetaChainConfig
default:
return params.AllEthashProtocolChanges
}
@@ -676,6 +710,23 @@ func DefaultMioGenesisBlock() *Genesis {
}
}
+// DefaultBetaGenesisBlock returns the Beta network genesis block.
+func DefaultBetaGenesisBlock() *Genesis {
+ // Initial allocation for Beta network
+ balanceStr := "40996800000000000000000000"
+ balance, _ := new(big.Int).SetString(balanceStr, 10)
+ return &Genesis{
+ Config: params.BetaChainConfig,
+ Nonce: 91510,
+ Timestamp: 1709568000, // Placeholder: Update with actual launch timestamp
+ ExtraData: []byte("Worldland Beta"),
+ GasLimit: 30000000,
+ Difficulty: big.NewInt(1023),
+ Alloc: map[common.Address]GenesisAccount{
+ common.HexToAddress("0x8C98EAeA19F1B9B36af58e7d7E78e0F1df8138f0"): {Balance: balance},
+ },
+ }
+}
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis {
diff --git a/eth/backend.go b/eth/backend.go
index 1c2f2dc041f4..e6ebc0342169 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -148,12 +148,17 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
return nil, err
}
+ eccbetaConfig, err := core.LoadEccbetaConfig(chainDb, config.Genesis)
+ if err != nil {
+ return nil, err
+ }
+
cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis)
if err != nil {
return nil, err
}
- engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, eccpowConfig, kaijuConfig, config.Miner.Notify, config.Miner.Noverify, chainDb)
+ engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, eccpowConfig, kaijuConfig, eccbetaConfig, config.Miner.Notify, config.Miner.Noverify, chainDb)
eth := &Ethereum{
config: config,
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 856ee5311cb4..42f64913022c 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -29,6 +29,7 @@ import (
"github.com/cryptoecc/WorldLand/consensus"
"github.com/cryptoecc/WorldLand/consensus/beacon"
"github.com/cryptoecc/WorldLand/consensus/clique"
+ "github.com/cryptoecc/WorldLand/consensus/eccbeta"
"github.com/cryptoecc/WorldLand/consensus/eccpow"
"github.com/cryptoecc/WorldLand/consensus/ethash"
"github.com/cryptoecc/WorldLand/consensus/kaiju"
@@ -224,11 +225,14 @@ type Config struct {
}
// CreateConsensusEngine creates a consensus engine for the given chain configuration.
-func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, cliqueConfig *params.CliqueConfig, eccpowConfig *params.EccpowConfig, kaijuConfig *params.KaijuConfig, notify []string, noverify bool, db ethdb.Database) consensus.Engine {
+func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, cliqueConfig *params.CliqueConfig, eccpowConfig *params.EccpowConfig, kaijuConfig *params.KaijuConfig, eccbetaConfig *params.EccbetaConfig, notify []string, noverify bool, db ethdb.Database) consensus.Engine {
// If proof-of-authority is requested, set it up
var engine consensus.Engine
if cliqueConfig != nil {
engine = clique.New(cliqueConfig, db)
+ } else if eccbetaConfig != nil {
+ engine = eccbeta.New(eccbeta.Config{}, notify, noverify)
+ log.Info("Creating ECCBeta consensus engine")
} else if kaijuConfig != nil {
engine = kaiju.New(kaiju.Config{}, notify, noverify)
log.Info("Creating Kaiju consensus engine")
diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js
index 6c530503286d..92a840c870d1 100644
--- a/internal/jsre/deps/web3.js
+++ b/internal/jsre/deps/web3.js
@@ -1885,32 +1885,43 @@ var utf8 = require('utf8');
var unitMap = {
'nowlc': '0',
+ 'nowl': '0',
'wei': '1',
'kwei': '1000',
'Kwei': '1000',
'babbage': '1000',
'femtowlc': '1000',
+ 'femtowl': '1000',
'mwei': '1000000',
'Mwei': '1000000',
'lovelace': '1000000',
'picowlc': '1000000',
+ 'picowl': '1000000',
'gwei': '1000000000',
'Gwei': '1000000000',
'shannon': '1000000000',
'nanowlc': '1000000000',
+ 'nanowl': '1000000000',
'nano': '1000000000',
'szabo': '1000000000000',
'microwlc': '1000000000000',
+ 'microwl': '1000000000000',
'micro': '1000000000000',
'finney': '1000000000000000',
'milliwlc': '1000000000000000',
+ 'milliwl': '1000000000000000',
'milli': '1000000000000000',
'wlc': '1000000000000000000',
+ 'wl': '1000000000000000000',
'kwlc': '1000000000000000000000',
+ 'kwl': '1000000000000000000000',
'grand': '1000000000000000000000',
'mwlc': '1000000000000000000000000',
+ 'mwl': '1000000000000000000000000',
'gwlc': '1000000000000000000000000000',
- 'twlc': '1000000000000000000000000000000'
+ 'gwl': '1000000000000000000000000000',
+ 'twlc': '1000000000000000000000000000000',
+ 'twl': '1000000000000000000000000000000'
};
/**
diff --git a/les/client.go b/les/client.go
index 0ac32763e3ff..9b1b361e43e7 100644
--- a/les/client.go
+++ b/les/client.go
@@ -128,7 +128,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
reqDist: newRequestDistributor(peers, &mclock.System{}),
accountManager: stack.AccountManager(),
merger: merger,
- engine: ethconfig.CreateConsensusEngine(stack, &config.Ethash, chainConfig.Clique, chainConfig.Eccpow, chainConfig.Kaiju, nil, false, chainDb),
+ engine: ethconfig.CreateConsensusEngine(stack, &config.Ethash, chainConfig.Clique, chainConfig.Eccpow, chainConfig.Kaiju, chainConfig.Eccbeta, nil, false, chainDb),
bloomRequests: make(chan chan *bloombits.Retrieval),
bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
p2pServer: stack.Server(),
diff --git a/params/bootnodes.go b/params/bootnodes.go
index 5466eb2fc83e..22900313b177 100644
--- a/params/bootnodes.go
+++ b/params/bootnodes.go
@@ -104,6 +104,12 @@ var MioBootnodes = []string{
"enode://a7ce7263293907cd317a24ba912bdd1302656d4c7e51260ea67ae159658214ea34a74dfbab647cd199a26b116a2c10be5c8ccbfb267d17449f74f088470e47a9@3.34.200.40:30303",
}
+// BetaBootnodes are the enode URLs of the P2P bootstrap nodes running on the
+// Beta network.
+var BetaBootnodes = []string{
+ // Add your Beta network bootnodes here
+}
+
// GoerliBootnodes are the enode URLs of the P2P bootstrap nodes running on the
// Görli test network.
var GoerliBootnodes = []string{
@@ -160,6 +166,8 @@ func KnownDNSNetwork(genesis common.Hash, protocol string) string {
net = "mio"
case SeoulGenesisHash:
net = "seoul"
+ case BetaGenesisHash:
+ net = "beta"
default:
return "seoul"
}
diff --git a/params/config.go b/params/config.go
index f7b6609dab89..a7f71538f8d7 100644
--- a/params/config.go
+++ b/params/config.go
@@ -37,6 +37,7 @@ var (
SeoulGenesisHash = common.HexToHash("0x5bd83be2a4c3a01b45e48fe181de1e6173d92cf5b54790fe64962dd2a7f25abb")
GwangjuGenesisHash = common.HexToHash("0x64130a2624d46bda6aacf0c1ec34ab3d926e31b8438141a10e7412070064f0bf")
MioGenesisHash = common.HexToHash("")
+ BetaGenesisHash = common.HexToHash("") // To be filled after genesis block creation
)
// TrustedCheckpoints associates each known checkpoint with the genesis hash of
@@ -362,6 +363,28 @@ var (
Kaiju: new(KaijuConfig),
}
+ BetaChainConfig = &ChainConfig{
+ ChainID: big.NewInt(91510),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ WorldlandBlock: big.NewInt(0),
+ SeoulBlock: big.NewInt(0),
+ AnnapurnaBlock: big.NewInt(0),
+ BetaBlock: big.NewInt(0),
+ HalvingEndTime: big.NewInt(50457600), // 4 halvings * 4 years
+ Eccbeta: new(EccbetaConfig),
+ }
+
/* SeoulTrustedCheckpoint contains the light client trusted checkpoint for the Gwangju test network.
SeoulTrustedCheckpoint = &TrustedCheckpoint{
SectionIndex: 32,
@@ -434,16 +457,16 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil, nil, nil}
+ AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil, nil, nil, nil}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, nil}
+ AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, nil, nil}
- TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil, nil, nil}
+ TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil, nil, nil, nil}
//NonActivatedConfig = &ChainConfig{big.NewInt(1), nil, nil, false, nil, common.Hash{}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil, nil}
TestRules = TestChainConfig.Rules(new(big.Int), false)
)
@@ -457,7 +480,8 @@ var NetworkNames = map[string]string{
SepoliaChainConfig.ChainID.String(): "sepolia",
SeoulChainConfig.ChainID.String(): "seoul",
GwangjuChainConfig.ChainID.String(): "gwangju",
- MioChainConfig.ChainID.String(): "mio",
+ MioChainConfig.ChainID.String(): "mio",
+ BetaChainConfig.ChainID.String(): "beta",
}
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
@@ -546,6 +570,7 @@ type ChainConfig struct {
SeoulBlock *big.Int `json:"seoulBlock,omitempty"`
AnnapurnaBlock *big.Int `json:"AnnapurnaBlock,omitempty"`
MioBlock *big.Int `json:"MioBlock,omitempty"`
+ BetaBlock *big.Int `json:"betaBlock,omitempty"` // Beta switch block (nil = no fork, 0 = already on beta)
// TerminalTotalDifficulty is the amount of total difficulty reached by
// the network that triggers the consensus upgrade.
@@ -557,11 +582,11 @@ type ChainConfig struct {
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
// Various consensus engines
- Ethash *EthashConfig `json:"ethash,omitempty"`
- Clique *CliqueConfig `json:"clique,omitempty"`
- Eccpow *EccpowConfig `json:"eccpow,omitempty"`
- Kaiju *KaijuConfig `json:"kaiju,omitempty"`
-
+ Ethash *EthashConfig `json:"ethash,omitempty"`
+ Clique *CliqueConfig `json:"clique,omitempty"`
+ Eccpow *EccpowConfig `json:"eccpow,omitempty"`
+ Kaiju *KaijuConfig `json:"kaiju,omitempty"`
+ Eccbeta *EccbetaConfig `json:"eccbeta,omitempty"`
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
@@ -570,9 +595,12 @@ type EthashConfig struct{}
// EccpowConfig is the consensus engine configs for proof-of-work based sealing.
type EccpowConfig struct{}
-// AbcdkConfig is the consensus engine configs for proof-of-work based sealing.
+// KaijuConfig is the consensus engine configs for proof-of-work based sealing.
type KaijuConfig struct{}
+// EccbetaConfig is the consensus engine configs for Beta network proof-of-work.
+type EccbetaConfig struct{}
+
// String implements the stringer interface, returning the consensus engine details.
func (c *EthashConfig) String() string {
@@ -588,6 +616,10 @@ func (c *KaijuConfig) String() string {
return "Kaiju"
}
+func (c *EccbetaConfig) String() string {
+ return "eccbeta"
+}
+
// CliqueConfig is the consensus engine configs for proof-of-authority based sealing.
type CliqueConfig struct {
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
@@ -642,6 +674,14 @@ func (c *ChainConfig) String() string {
} else {
banner += "Consensus: Kaiju (proof-of-work with VRF sortition)\n"
}
+ case c.Eccbeta != nil:
+ if c.TerminalTotalDifficulty == nil {
+ banner += "Consensus: ECCBeta (proof-of-work)\n"
+ } else if !c.TerminalTotalDifficultyPassed {
+ banner += "Consensus: Beacon (proof-of-stake), merging from ECCBeta (proof-of-work)\n"
+ } else {
+ banner += "Consensus: Beacon (proof-of-stake), merged from ECCBeta (proof-of-work)\n"
+ }
default:
banner += "Consensus: unknown\n"
}
@@ -689,6 +729,9 @@ func (c *ChainConfig) String() string {
if c.AnnapurnaBlock != nil {
banner += fmt.Sprintf(" - Annapurna: %-8v\n", c.AnnapurnaBlock)
}
+ if c.BetaBlock != nil {
+ banner += fmt.Sprintf(" - Beta: %-8v\n", c.BetaBlock)
+ }
banner += "\n"
// Add a special section for the merge as it's non-obvious
@@ -827,6 +870,21 @@ func (c *ChainConfig) IsMio(num *big.Int) bool {
return isForked(c.MioBlock, num)
}
+// IsBeta returns whether num is either equal to the Beta fork block or greater.
+func (c *ChainConfig) IsBeta(num *big.Int) bool {
+ return isForked(c.BetaBlock, num)
+}
+
+// IsBetaHalving returns whether num is in the Beta halving period.
+func (c *ChainConfig) IsBetaHalving(num *big.Int) bool {
+ return isHalving(c.HalvingEndTime, num)
+}
+
+// IsBetaMaturity returns whether num is past the Beta halving period (maturity phase).
+func (c *ChainConfig) IsBetaMaturity(num *big.Int) bool {
+ return isMatured(c.HalvingEndTime, num)
+}
+
// CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration.
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError {