From 4ef2a8147e67c383db9da0694a2fc2241fed6bbf Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 18:24:40 +0000 Subject: [PATCH 01/45] Iniital Hypra support --- consensus/ethashb3/algorithm.go | 1177 +++++++++++++++++++++++++ consensus/ethashb3/api.go | 113 +++ consensus/ethashb3/consensus.go | 513 +++++++++++ consensus/ethashb3/difficulty.go | 191 ++++ consensus/ethashb3/ethash.go | 854 ++++++++++++++++++ consensus/ethashb3/mmap_help_linux.go | 35 + consensus/ethashb3/mmap_help_other.go | 36 + consensus/ethashb3/sealer.go | 499 +++++++++++ go.mod | 2 + go.sum | 4 + params/config_hypra.go | 110 +++ params/genesis_hypra.go | 40 + params/types/coregeth/chain_config.go | 11 +- params/types/ctypes/types.go | 15 + 14 files changed, 3596 insertions(+), 4 deletions(-) create mode 100644 consensus/ethashb3/algorithm.go create mode 100644 consensus/ethashb3/api.go create mode 100644 consensus/ethashb3/consensus.go create mode 100644 consensus/ethashb3/difficulty.go create mode 100644 consensus/ethashb3/ethash.go create mode 100644 consensus/ethashb3/mmap_help_linux.go create mode 100644 consensus/ethashb3/mmap_help_other.go create mode 100644 consensus/ethashb3/sealer.go create mode 100644 params/config_hypra.go create mode 100644 params/genesis_hypra.go diff --git a/consensus/ethashb3/algorithm.go b/consensus/ethashb3/algorithm.go new file mode 100644 index 0000000000..c61c9232e0 --- /dev/null +++ b/consensus/ethashb3/algorithm.go @@ -0,0 +1,1177 @@ +// 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 ethashb3 + +import ( + "encoding/binary" + "hash" + "math/big" + "reflect" + "runtime" + "sync" + "sync/atomic" + "time" + "unsafe" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/bitutil" + "github.com/ethereum/go-ethereum/log" + "golang.org/x/crypto/sha3" + "lukechampine.com/blake3" +) + +const ( + datasetInitBytes = 1 << 30 // Bytes in dataset at genesis + datasetGrowthBytes = 1 << 23 // Dataset growth per epoch + cacheInitBytes = 1 << 24 // Bytes in cache at genesis + cacheGrowthBytes = 1 << 17 // Cache growth per epoch + epochLengthDefault = 32000 // Default epoch length (blocks per epoch) + epochLengthECIP1099 = 60000 // Blocks per epoch if ECIP-1099 is activated + mixBytes = 128 // Width of mix + hashBytes = 64 // Hash length in bytes + hashWords = 16 // Number of 32 bit ints in a hash + datasetParents = 256 // Number of parents of each dataset element + cacheRounds = 3 // Number of rounds in cache production + loopAccesses = 64 // Number of accesses in hashimoto loop + maxEpoch = 2048 // Max Epoch for included tables +) + +// calcEpochLength returns the epoch length for a given block number (ECIP-1099) +func calcEpochLength(block uint64, ecip1099FBlock *uint64) uint64 { + if ecip1099FBlock != nil { + if block >= *ecip1099FBlock { + return epochLengthECIP1099 + } + } + return epochLengthDefault +} + +// calcEpoch returns the epoch for a given block number (ECIP-1099) +func calcEpoch(block uint64, epochLength uint64) uint64 { + epoch := block / epochLength + return epoch +} + +// calcEpochBlock returns the epoch start block for a given epoch (ECIP-1099) +func calcEpochBlock(epoch uint64, epochLength uint64) uint64 { + return epoch*epochLength + 1 +} + +// cacheSize returns the size of the ethash verification cache that belongs to a certain +// block number. +func cacheSize(epoch uint64) uint64 { + if epoch < maxEpoch { + return cacheSizes[int(epoch)] + } + return calcCacheSize(epoch) +} + +// calcCacheSize calculates the cache size for epoch. The cache size grows linearly, +// however, we always take the highest prime below the linearly growing threshold in order +// to reduce the risk of accidental regularities leading to cyclic behavior. +func calcCacheSize(epoch uint64) uint64 { + size := cacheInitBytes + cacheGrowthBytes*epoch - hashBytes + for !new(big.Int).SetUint64(size / hashBytes).ProbablyPrime(1) { // Always accurate for n < 2^64 + size -= 2 * hashBytes + } + return size +} + +// datasetSize returns the size of the ethash mining dataset that belongs to a certain +// block number. +func datasetSize(epoch uint64) uint64 { + if epoch < maxEpoch { + return datasetSizes[int(epoch)] + } + return calcDatasetSize(epoch) +} + +// calcDatasetSize calculates the dataset size for epoch. The dataset size grows linearly, +// however, we always take the highest prime below the linearly growing threshold in order +// to reduce the risk of accidental regularities leading to cyclic behavior. +func calcDatasetSize(epoch uint64) uint64 { + size := datasetInitBytes + datasetGrowthBytes*epoch - mixBytes + for !new(big.Int).SetUint64(size / mixBytes).ProbablyPrime(1) { // Always accurate for n < 2^64 + size -= 2 * mixBytes + } + return size +} + +// 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. The block number passed should be pre-rounded to an epoch boundary + 1 +// e.g: seedHash(calcEpochBlock(epoch, epochLength)) +func seedHash(epoch uint64, epochLength uint64) []byte { + block := calcEpochBlock(epoch, epochLength) + + seed := make([]byte, 32) + if block < epochLengthDefault { + return seed + } + + keccak256 := makeHasher(sha3.NewLegacyKeccak256()) + for i := 0; i < int(block/epochLengthDefault); i++ { + keccak256(seed, seed) + } + return seed +} + +// generateCache creates a verification cache of a given size for an input seed. +// The cache production process involves first sequentially filling up 32 MB of +// memory, then performing two passes of Sergio Demian Lerner's RandMemoHash +// algorithm from Strict Memory Hard Hashing Functions (2014). The output is a +// set of 524288 64-byte values. +// This method places the result into dest in machine byte order. +func generateCache(dest []uint32, epoch uint64, epochLength uint64, seed []byte) { + // Print some debug logs to allow analysis on low end devices + logger := log.New("epoch", epoch) + + start := time.Now() + defer func() { + elapsed := time.Since(start) + + logFn := logger.Debug + if elapsed > 3*time.Second { + logFn = logger.Info + } + logFn("Generated ethashb3 verification cache", "epochLength", epochLength, "elapsed", common.PrettyDuration(elapsed)) + }() + // Convert our destination slice to a byte buffer + var cache []byte + cacheHdr := (*reflect.SliceHeader)(unsafe.Pointer(&cache)) + dstHdr := (*reflect.SliceHeader)(unsafe.Pointer(&dest)) + cacheHdr.Data = dstHdr.Data + cacheHdr.Len = dstHdr.Len * 4 + cacheHdr.Cap = dstHdr.Cap * 4 + + // Calculate the number of theoretical rows (we'll store in one buffer nonetheless) + size := uint64(len(cache)) + rows := int(size) / hashBytes + + // Start a monitoring goroutine to report progress on low end devices + var progress atomic.Uint32 + + done := make(chan struct{}) + defer close(done) + + go func() { + for { + select { + case <-done: + return + case <-time.After(3 * time.Second): + logger.Info("Generating ethashb3 verification cache", "epochLength", epochLength, "percentage", progress.Load()*100/uint32(rows)/(cacheRounds+1), "elapsed", common.PrettyDuration(time.Since(start))) + } + } + }() + // Create a hasher to reuse between invocations + keccak512 := makeHasher(sha3.NewLegacyKeccak512()) + + // Sequentially produce the initial dataset + keccak512(cache, seed) + for offset := uint64(hashBytes); offset < size; offset += hashBytes { + keccak512(cache[offset:], cache[offset-hashBytes:offset]) + progress.Add(1) + } + // Use a low-round version of randmemohash + temp := make([]byte, hashBytes) + + for i := 0; i < cacheRounds; i++ { + for j := 0; j < rows; j++ { + var ( + srcOff = ((j - 1 + rows) % rows) * hashBytes + dstOff = j * hashBytes + xorOff = (binary.LittleEndian.Uint32(cache[dstOff:]) % uint32(rows)) * hashBytes + ) + bitutil.XORBytes(temp, cache[srcOff:srcOff+hashBytes], cache[xorOff:xorOff+hashBytes]) + keccak512(cache[dstOff:], temp) + + progress.Add(1) + } + } + // Swap the byte order on big endian systems and return + if !isLittleEndian() { + swap(cache) + } +} + +// swap changes the byte order of the buffer assuming a uint32 representation. +func swap(buffer []byte) { + for i := 0; i < len(buffer); i += 4 { + binary.BigEndian.PutUint32(buffer[i:], binary.LittleEndian.Uint32(buffer[i:])) + } +} + +// fnv is an algorithm inspired by the FNV hash, which in some cases is used as +// a non-associative substitute for XOR. Note that we multiply the prime with +// the full 32-bit input, in contrast with the FNV-1 spec which multiplies the +// prime with one byte (octet) in turn. +func fnv(a, b uint32) uint32 { + return a*0x01000193 ^ b +} + +// fnvHash mixes in data into mix using the ethash fnv method. +func fnvHash(mix []uint32, data []uint32) { + for i := 0; i < len(mix); i++ { + mix[i] = mix[i]*0x01000193 ^ data[i] + } +} + +// generateDatasetItem combines data from 256 pseudorandomly selected cache nodes, +// and hashes that to compute a single dataset node. +func generateDatasetItem(cache []uint32, index uint32, keccak512 hasher) []byte { + // Calculate the number of theoretical rows (we use one buffer nonetheless) + rows := uint32(len(cache) / hashWords) + + // Initialize the mix + mix := make([]byte, hashBytes) + + binary.LittleEndian.PutUint32(mix, cache[(index%rows)*hashWords]^index) + for i := 1; i < hashWords; i++ { + binary.LittleEndian.PutUint32(mix[i*4:], cache[(index%rows)*hashWords+uint32(i)]) + } + keccak512(mix, mix) + + // Convert the mix to uint32s to avoid constant bit shifting + intMix := make([]uint32, hashWords) + for i := 0; i < len(intMix); i++ { + intMix[i] = binary.LittleEndian.Uint32(mix[i*4:]) + } + // fnv it with a lot of random cache nodes based on index + for i := uint32(0); i < datasetParents; i++ { + parent := fnv(index^i, intMix[i%16]) % rows + fnvHash(intMix, cache[parent*hashWords:]) + } + // Flatten the uint32 mix into a binary one and return + for i, val := range intMix { + binary.LittleEndian.PutUint32(mix[i*4:], val) + } + keccak512(mix, mix) + return mix +} + +// generateDataset generates the entire ethash dataset for mining. +// This method places the result into dest in machine byte order. +func generateDataset(dest []uint32, epoch uint64, epochLength uint64, cache []uint32) { + // Print some debug logs to allow analysis on low end devices + logger := log.New("epoch", epoch) + + start := time.Now() + defer func() { + elapsed := time.Since(start) + + logFn := logger.Debug + if elapsed > 3*time.Second { + logFn = logger.Info + } + logFn("Generated ethashb3 verification dataset", "epochLength", epochLength, "elapsed", common.PrettyDuration(elapsed)) + }() + + // Figure out whether the bytes need to be swapped for the machine + swapped := !isLittleEndian() + + // Convert our destination slice to a byte buffer + var dataset []byte + datasetHdr := (*reflect.SliceHeader)(unsafe.Pointer(&dataset)) + destHdr := (*reflect.SliceHeader)(unsafe.Pointer(&dest)) + datasetHdr.Data = destHdr.Data + datasetHdr.Len = destHdr.Len * 4 + datasetHdr.Cap = destHdr.Cap * 4 + + // Generate the dataset on many goroutines since it takes a while + threads := runtime.NumCPU() + size := uint64(len(dataset)) + + var pend sync.WaitGroup + pend.Add(threads) + + var progress atomic.Uint64 + for i := 0; i < threads; i++ { + go func(id int) { + defer pend.Done() + + // Create a hasher to reuse between invocations + keccak512 := makeHasher(sha3.NewLegacyKeccak512()) + + // Calculate the data segment this thread should generate + batch := (size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads)) + first := uint64(id) * batch + limit := first + batch + if limit > size/hashBytes { + limit = size / hashBytes + } + // Calculate the dataset segment + percent := size / hashBytes / 100 + for index := first; index < limit; index++ { + item := generateDatasetItem(cache, uint32(index), keccak512) + if swapped { + swap(item) + } + copy(dataset[index*hashBytes:], item) + + if status := progress.Add(1); status%percent == 0 { + logger.Info("Generating DAG in progress", "epochLength", epochLength, "percentage", (status*100)/(size/hashBytes), "elapsed", common.PrettyDuration(time.Since(start))) + } + } + }(i) + } + // Wait for all the generators to finish and return + pend.Wait() +} + +// hashimoto aggregates data from the full dataset in order to produce our final +// value for a particular header hash and nonce. +func hashimoto(hash []byte, nonce uint64, size uint64, lookup func(index uint32) []uint32) ([]byte, []byte) { + // Calculate the number of theoretical rows (we use one buffer nonetheless) + rows := uint32(size / mixBytes) + + // Combine header+nonce into a 40 byte seed + seed := make([]byte, 40) + copy(seed, hash) + binary.LittleEndian.PutUint64(seed[32:], nonce) + + b64 := blake3.Sum512(seed) + seed = b64[:] + seedHead := binary.LittleEndian.Uint32(seed) + + // Start the mix with replicated seed + mix := make([]uint32, mixBytes/4) + for i := 0; i < len(mix); i++ { + mix[i] = binary.LittleEndian.Uint32(seed[i%16*4:]) + } + // Mix in random dataset nodes + temp := make([]uint32, len(mix)) + + for i := 0; i < loopAccesses; i++ { + parent := fnv(uint32(i)^seedHead, mix[i%len(mix)]) % rows + for j := uint32(0); j < mixBytes/hashBytes; j++ { + copy(temp[j*hashWords:], lookup(2*parent+j)) + } + fnvHash(mix, temp) + } + // Compress mix + for i := 0; i < len(mix); i += 4 { + mix[i/4] = fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]) + } + mix = mix[:len(mix)/4] + + digest := make([]byte, common.HashLength) + for i, val := range mix { + binary.LittleEndian.PutUint32(digest[i*4:], val) + } + b32 := blake3.Sum256(append(seed, digest...)) + return digest, b32[:] +} + +// hashimotoLight aggregates data from the full dataset (using only a small +// in-memory cache) in order to produce our final value for a particular header +// hash and nonce. +func hashimotoLight(size uint64, cache []uint32, hash []byte, nonce uint64) ([]byte, []byte) { + keccak512 := makeHasher(sha3.NewLegacyKeccak512()) + + lookup := func(index uint32) []uint32 { + rawData := generateDatasetItem(cache, index, keccak512) + + data := make([]uint32, len(rawData)/4) + for i := 0; i < len(data); i++ { + data[i] = binary.LittleEndian.Uint32(rawData[i*4:]) + } + return data + } + return hashimoto(hash, nonce, size, lookup) +} + +// hashimotoFull aggregates data from the full dataset (using the full in-memory +// dataset) in order to produce our final value for a particular header hash and +// nonce. +func hashimotoFull(dataset []uint32, hash []byte, nonce uint64) ([]byte, []byte) { + lookup := func(index uint32) []uint32 { + offset := index * hashWords + return dataset[offset : offset+hashWords] + } + return hashimoto(hash, nonce, uint64(len(dataset))*4, lookup) +} + +// datasetSizes is a lookup table for the ethash dataset size for the first 2048 +// epochs (i.e. 61440000 blocks). +var datasetSizes = [maxEpoch]uint64{ + 1073739904, 1082130304, 1090514816, 1098906752, 1107293056, + 1115684224, 1124070016, 1132461952, 1140849536, 1149232768, + 1157627776, 1166013824, 1174404736, 1182786944, 1191180416, + 1199568512, 1207958912, 1216345216, 1224732032, 1233124736, + 1241513344, 1249902464, 1258290304, 1266673792, 1275067264, + 1283453312, 1291844992, 1300234112, 1308619904, 1317010048, + 1325397376, 1333787776, 1342176128, 1350561664, 1358954368, + 1367339392, 1375731584, 1384118144, 1392507008, 1400897408, + 1409284736, 1417673344, 1426062464, 1434451072, 1442839168, + 1451229056, 1459615616, 1468006016, 1476394112, 1484782976, + 1493171584, 1501559168, 1509948032, 1518337664, 1526726528, + 1535114624, 1543503488, 1551892096, 1560278656, 1568669056, + 1577056384, 1585446272, 1593831296, 1602219392, 1610610304, + 1619000192, 1627386752, 1635773824, 1644164224, 1652555648, + 1660943488, 1669332608, 1677721216, 1686109312, 1694497664, + 1702886272, 1711274624, 1719661184, 1728047744, 1736434816, + 1744829056, 1753218944, 1761606272, 1769995904, 1778382464, + 1786772864, 1795157888, 1803550592, 1811937664, 1820327552, + 1828711552, 1837102976, 1845488768, 1853879936, 1862269312, + 1870656896, 1879048064, 1887431552, 1895825024, 1904212096, + 1912601216, 1920988544, 1929379456, 1937765504, 1946156672, + 1954543232, 1962932096, 1971321728, 1979707264, 1988093056, + 1996487552, 2004874624, 2013262208, 2021653888, 2030039936, + 2038430848, 2046819968, 2055208576, 2063596672, 2071981952, + 2080373632, 2088762752, 2097149056, 2105539712, 2113928576, + 2122315136, 2130700672, 2139092608, 2147483264, 2155872128, + 2164257664, 2172642176, 2181035392, 2189426048, 2197814912, + 2206203008, 2214587264, 2222979712, 2231367808, 2239758208, + 2248145024, 2256527744, 2264922752, 2273312128, 2281701248, + 2290086272, 2298476672, 2306867072, 2315251072, 2323639168, + 2332032128, 2340420224, 2348808064, 2357196416, 2365580416, + 2373966976, 2382363008, 2390748544, 2399139968, 2407530368, + 2415918976, 2424307328, 2432695424, 2441084288, 2449472384, + 2457861248, 2466247808, 2474637184, 2483026816, 2491414144, + 2499803776, 2508191872, 2516582272, 2524970368, 2533359232, + 2541743488, 2550134144, 2558525056, 2566913408, 2575301504, + 2583686528, 2592073856, 2600467328, 2608856192, 2617240448, + 2625631616, 2634022016, 2642407552, 2650796416, 2659188352, + 2667574912, 2675965312, 2684352896, 2692738688, 2701130624, + 2709518464, 2717907328, 2726293376, 2734685056, 2743073152, + 2751462016, 2759851648, 2768232832, 2776625536, 2785017728, + 2793401984, 2801794432, 2810182016, 2818571648, 2826959488, + 2835349376, 2843734144, 2852121472, 2860514432, 2868900992, + 2877286784, 2885676928, 2894069632, 2902451584, 2910843008, + 2919234688, 2927622784, 2936011648, 2944400768, 2952789376, + 2961177728, 2969565568, 2977951616, 2986338944, 2994731392, + 3003120256, 3011508352, 3019895936, 3028287104, 3036675968, + 3045063808, 3053452928, 3061837696, 3070228352, 3078615424, + 3087003776, 3095394944, 3103782272, 3112173184, 3120562048, + 3128944768, 3137339264, 3145725056, 3154109312, 3162505088, + 3170893184, 3179280256, 3187669376, 3196056704, 3204445568, + 3212836736, 3221224064, 3229612928, 3238002304, 3246391168, + 3254778496, 3263165824, 3271556224, 3279944576, 3288332416, + 3296719232, 3305110912, 3313500032, 3321887104, 3330273152, + 3338658944, 3347053184, 3355440512, 3363827072, 3372220288, + 3380608384, 3388997504, 3397384576, 3405774208, 3414163072, + 3422551936, 3430937984, 3439328384, 3447714176, 3456104576, + 3464493952, 3472883584, 3481268864, 3489655168, 3498048896, + 3506434432, 3514826368, 3523213952, 3531603584, 3539987072, + 3548380288, 3556763264, 3565157248, 3573545344, 3581934464, + 3590324096, 3598712704, 3607098752, 3615488384, 3623877248, + 3632265856, 3640646528, 3649043584, 3657430144, 3665821568, + 3674207872, 3682597504, 3690984832, 3699367808, 3707764352, + 3716152448, 3724541056, 3732925568, 3741318016, 3749706368, + 3758091136, 3766481536, 3774872704, 3783260032, 3791650432, + 3800036224, 3808427648, 3816815488, 3825204608, 3833592704, + 3841981568, 3850370432, 3858755968, 3867147904, 3875536256, + 3883920512, 3892313728, 3900702592, 3909087872, 3917478784, + 3925868416, 3934256512, 3942645376, 3951032192, 3959422336, + 3967809152, 3976200064, 3984588416, 3992974976, 4001363584, + 4009751168, 4018141312, 4026530432, 4034911616, 4043308928, + 4051695488, 4060084352, 4068472448, 4076862848, 4085249408, + 4093640576, 4102028416, 4110413696, 4118805632, 4127194496, + 4135583104, 4143971968, 4152360832, 4160746112, 4169135744, + 4177525888, 4185912704, 4194303616, 4202691968, 4211076736, + 4219463552, 4227855488, 4236246656, 4244633728, 4253022848, + 4261412224, 4269799808, 4278184832, 4286578048, 4294962304, + 4303349632, 4311743104, 4320130432, 4328521088, 4336909184, + 4345295488, 4353687424, 4362073472, 4370458496, 4378852736, + 4387238528, 4395630208, 4404019072, 4412407424, 4420790656, + 4429182848, 4437571456, 4445962112, 4454344064, 4462738048, + 4471119232, 4479516544, 4487904128, 4496289664, 4504682368, + 4513068416, 4521459584, 4529846144, 4538232704, 4546619776, + 4555010176, 4563402112, 4571790208, 4580174464, 4588567936, + 4596957056, 4605344896, 4613734016, 4622119808, 4630511488, + 4638898816, 4647287936, 4655675264, 4664065664, 4672451968, + 4680842624, 4689231488, 4697620352, 4706007424, 4714397056, + 4722786176, 4731173248, 4739562368, 4747951744, 4756340608, + 4764727936, 4773114496, 4781504384, 4789894784, 4798283648, + 4806667648, 4815059584, 4823449472, 4831835776, 4840226176, + 4848612224, 4857003392, 4865391488, 4873780096, 4882169728, + 4890557312, 4898946944, 4907333248, 4915722368, 4924110976, + 4932499328, 4940889728, 4949276032, 4957666432, 4966054784, + 4974438016, 4982831488, 4991221376, 4999607168, 5007998848, + 5016386432, 5024763776, 5033164672, 5041544576, 5049941888, + 5058329728, 5066717056, 5075107456, 5083494272, 5091883904, + 5100273536, 5108662144, 5117048192, 5125436032, 5133827456, + 5142215296, 5150605184, 5158993024, 5167382144, 5175769472, + 5184157568, 5192543872, 5200936064, 5209324928, 5217711232, + 5226102656, 5234490496, 5242877312, 5251263872, 5259654016, + 5268040832, 5276434304, 5284819328, 5293209728, 5301598592, + 5309986688, 5318374784, 5326764416, 5335151488, 5343542144, + 5351929472, 5360319872, 5368706944, 5377096576, 5385484928, + 5393871232, 5402263424, 5410650496, 5419040384, 5427426944, + 5435816576, 5444205952, 5452594816, 5460981376, 5469367936, + 5477760896, 5486148736, 5494536832, 5502925952, 5511315328, + 5519703424, 5528089984, 5536481152, 5544869504, 5553256064, + 5561645696, 5570032768, 5578423936, 5586811264, 5595193216, + 5603585408, 5611972736, 5620366208, 5628750464, 5637143936, + 5645528192, 5653921408, 5662310272, 5670694784, 5679082624, + 5687474048, 5695864448, 5704251008, 5712641408, 5721030272, + 5729416832, 5737806208, 5746194304, 5754583936, 5762969984, + 5771358592, 5779748224, 5788137856, 5796527488, 5804911232, + 5813300608, 5821692544, 5830082176, 5838468992, 5846855552, + 5855247488, 5863636096, 5872024448, 5880411008, 5888799872, + 5897186432, 5905576832, 5913966976, 5922352768, 5930744704, + 5939132288, 5947522432, 5955911296, 5964299392, 5972688256, + 5981074304, 5989465472, 5997851008, 6006241408, 6014627968, + 6023015552, 6031408256, 6039796096, 6048185216, 6056574848, + 6064963456, 6073351808, 6081736064, 6090128768, 6098517632, + 6106906496, 6115289216, 6123680896, 6132070016, 6140459648, + 6148849024, 6157237376, 6165624704, 6174009728, 6182403712, + 6190792064, 6199176064, 6207569792, 6215952256, 6224345216, + 6232732544, 6241124224, 6249510272, 6257899136, 6266287744, + 6274676864, 6283065728, 6291454336, 6299843456, 6308232064, + 6316620928, 6325006208, 6333395584, 6341784704, 6350174848, + 6358562176, 6366951296, 6375337856, 6383729536, 6392119168, + 6400504192, 6408895616, 6417283456, 6425673344, 6434059136, + 6442444672, 6450837376, 6459223424, 6467613056, 6476004224, + 6484393088, 6492781952, 6501170048, 6509555072, 6517947008, + 6526336384, 6534725504, 6543112832, 6551500672, 6559888768, + 6568278656, 6576662912, 6585055616, 6593443456, 6601834112, + 6610219648, 6618610304, 6626999168, 6635385472, 6643777408, + 6652164224, 6660552832, 6668941952, 6677330048, 6685719424, + 6694107776, 6702493568, 6710882176, 6719274112, 6727662976, + 6736052096, 6744437632, 6752825984, 6761213824, 6769604224, + 6777993856, 6786383488, 6794770816, 6803158144, 6811549312, + 6819937664, 6828326528, 6836706176, 6845101696, 6853491328, + 6861880448, 6870269312, 6878655104, 6887046272, 6895433344, + 6903822208, 6912212864, 6920596864, 6928988288, 6937377152, + 6945764992, 6954149248, 6962544256, 6970928768, 6979317376, + 6987709312, 6996093824, 7004487296, 7012875392, 7021258624, + 7029652352, 7038038912, 7046427776, 7054818944, 7063207808, + 7071595136, 7079980928, 7088372608, 7096759424, 7105149824, + 7113536896, 7121928064, 7130315392, 7138699648, 7147092352, + 7155479168, 7163865728, 7172249984, 7180648064, 7189036672, + 7197424768, 7205810816, 7214196608, 7222589824, 7230975104, + 7239367552, 7247755904, 7256145536, 7264533376, 7272921472, + 7281308032, 7289694848, 7298088832, 7306471808, 7314864512, + 7323253888, 7331643008, 7340029568, 7348419712, 7356808832, + 7365196672, 7373585792, 7381973888, 7390362752, 7398750592, + 7407138944, 7415528576, 7423915648, 7432302208, 7440690304, + 7449080192, 7457472128, 7465860992, 7474249088, 7482635648, + 7491023744, 7499412608, 7507803008, 7516192384, 7524579968, + 7532967296, 7541358464, 7549745792, 7558134656, 7566524032, + 7574912896, 7583300992, 7591690112, 7600075136, 7608466816, + 7616854912, 7625244544, 7633629824, 7642020992, 7650410368, + 7658794112, 7667187328, 7675574912, 7683961984, 7692349568, + 7700739712, 7709130368, 7717519232, 7725905536, 7734295424, + 7742683264, 7751069056, 7759457408, 7767849088, 7776238208, + 7784626816, 7793014912, 7801405312, 7809792128, 7818179968, + 7826571136, 7834957184, 7843347328, 7851732352, 7860124544, + 7868512384, 7876902016, 7885287808, 7893679744, 7902067072, + 7910455936, 7918844288, 7927230848, 7935622784, 7944009344, + 7952400256, 7960786048, 7969176704, 7977565312, 7985953408, + 7994339968, 8002730368, 8011119488, 8019508096, 8027896192, + 8036285056, 8044674688, 8053062272, 8061448832, 8069838464, + 8078227328, 8086616704, 8095006592, 8103393664, 8111783552, + 8120171392, 8128560256, 8136949376, 8145336704, 8153726848, + 8162114944, 8170503296, 8178891904, 8187280768, 8195669632, + 8204058496, 8212444544, 8220834176, 8229222272, 8237612672, + 8246000768, 8254389376, 8262775168, 8271167104, 8279553664, + 8287944064, 8296333184, 8304715136, 8313108352, 8321497984, + 8329885568, 8338274432, 8346663296, 8355052928, 8363441536, + 8371828352, 8380217984, 8388606592, 8396996224, 8405384576, + 8413772672, 8422161536, 8430549376, 8438939008, 8447326592, + 8455715456, 8464104832, 8472492928, 8480882048, 8489270656, + 8497659776, 8506045312, 8514434944, 8522823808, 8531208832, + 8539602304, 8547990656, 8556378752, 8564768384, 8573154176, + 8581542784, 8589933952, 8598322816, 8606705024, 8615099264, + 8623487872, 8631876992, 8640264064, 8648653952, 8657040256, + 8665430656, 8673820544, 8682209152, 8690592128, 8698977152, + 8707374464, 8715763328, 8724151424, 8732540032, 8740928384, + 8749315712, 8757704576, 8766089344, 8774480768, 8782871936, + 8791260032, 8799645824, 8808034432, 8816426368, 8824812928, + 8833199488, 8841591424, 8849976448, 8858366336, 8866757248, + 8875147136, 8883532928, 8891923328, 8900306816, 8908700288, + 8917088384, 8925478784, 8933867392, 8942250368, 8950644608, + 8959032704, 8967420544, 8975809664, 8984197504, 8992584064, + 9000976256, 9009362048, 9017752448, 9026141312, 9034530688, + 9042917504, 9051307904, 9059694208, 9068084864, 9076471424, + 9084861824, 9093250688, 9101638528, 9110027648, 9118416512, + 9126803584, 9135188096, 9143581312, 9151969664, 9160356224, + 9168747136, 9177134464, 9185525632, 9193910144, 9202302848, + 9210690688, 9219079552, 9227465344, 9235854464, 9244244864, + 9252633472, 9261021824, 9269411456, 9277799296, 9286188928, + 9294574208, 9302965888, 9311351936, 9319740032, 9328131968, + 9336516736, 9344907392, 9353296768, 9361685888, 9370074752, + 9378463616, 9386849408, 9395239808, 9403629184, 9412016512, + 9420405376, 9428795008, 9437181568, 9445570688, 9453960832, + 9462346624, 9470738048, 9479121536, 9487515008, 9495903616, + 9504289664, 9512678528, 9521067904, 9529456256, 9537843584, + 9546233728, 9554621312, 9563011456, 9571398784, 9579788672, + 9588178304, 9596567168, 9604954496, 9613343104, 9621732992, + 9630121856, 9638508416, 9646898816, 9655283584, 9663675776, + 9672061312, 9680449664, 9688840064, 9697230464, 9705617536, + 9714003584, 9722393984, 9730772608, 9739172224, 9747561088, + 9755945344, 9764338816, 9772726144, 9781116544, 9789503872, + 9797892992, 9806282624, 9814670464, 9823056512, 9831439232, + 9839833984, 9848224384, 9856613504, 9865000576, 9873391232, + 9881772416, 9890162816, 9898556288, 9906940544, 9915333248, + 9923721088, 9932108672, 9940496512, 9948888448, 9957276544, + 9965666176, 9974048384, 9982441088, 9990830464, 9999219584, + 10007602816, 10015996544, 10024385152, 10032774016, 10041163648, + 10049548928, 10057940096, 10066329472, 10074717824, 10083105152, + 10091495296, 10099878784, 10108272256, 10116660608, 10125049216, + 10133437312, 10141825664, 10150213504, 10158601088, 10166991232, + 10175378816, 10183766144, 10192157312, 10200545408, 10208935552, + 10217322112, 10225712768, 10234099328, 10242489472, 10250876032, + 10259264896, 10267656064, 10276042624, 10284429184, 10292820352, + 10301209472, 10309598848, 10317987712, 10326375296, 10334763392, + 10343153536, 10351541632, 10359930752, 10368318592, 10376707456, + 10385096576, 10393484672, 10401867136, 10410262144, 10418647424, + 10427039104, 10435425664, 10443810176, 10452203648, 10460589952, + 10468982144, 10477369472, 10485759104, 10494147712, 10502533504, + 10510923392, 10519313536, 10527702656, 10536091264, 10544478592, + 10552867712, 10561255808, 10569642368, 10578032768, 10586423168, + 10594805632, 10603200128, 10611588992, 10619976064, 10628361344, + 10636754048, 10645143424, 10653531776, 10661920384, 10670307968, + 10678696832, 10687086464, 10695475072, 10703863168, 10712246144, + 10720639616, 10729026688, 10737414784, 10745806208, 10754190976, + 10762581376, 10770971264, 10779356288, 10787747456, 10796135552, + 10804525184, 10812915584, 10821301888, 10829692288, 10838078336, + 10846469248, 10854858368, 10863247232, 10871631488, 10880023424, + 10888412032, 10896799616, 10905188992, 10913574016, 10921964672, + 10930352768, 10938742912, 10947132544, 10955518592, 10963909504, + 10972298368, 10980687488, 10989074816, 10997462912, 11005851776, + 11014241152, 11022627712, 11031017344, 11039403904, 11047793024, + 11056184704, 11064570752, 11072960896, 11081343872, 11089737856, + 11098128256, 11106514816, 11114904448, 11123293568, 11131680128, + 11140065152, 11148458368, 11156845696, 11165236864, 11173624192, + 11182013824, 11190402688, 11198790784, 11207179136, 11215568768, + 11223957376, 11232345728, 11240734592, 11249122688, 11257511296, + 11265899648, 11274285952, 11282675584, 11291065472, 11299452544, + 11307842432, 11316231296, 11324616832, 11333009024, 11341395584, + 11349782656, 11358172288, 11366560384, 11374950016, 11383339648, + 11391721856, 11400117376, 11408504192, 11416893568, 11425283456, + 11433671552, 11442061184, 11450444672, 11458837888, 11467226752, + 11475611776, 11484003968, 11492392064, 11500780672, 11509169024, + 11517550976, 11525944448, 11534335616, 11542724224, 11551111808, + 11559500672, 11567890304, 11576277376, 11584667008, 11593056128, + 11601443456, 11609830016, 11618221952, 11626607488, 11634995072, + 11643387776, 11651775104, 11660161664, 11668552576, 11676940928, + 11685330304, 11693718656, 11702106496, 11710496128, 11718882688, + 11727273088, 11735660416, 11744050048, 11752437376, 11760824704, + 11769216128, 11777604736, 11785991296, 11794381952, 11802770048, + 11811157888, 11819548544, 11827932544, 11836324736, 11844713344, + 11853100928, 11861486464, 11869879936, 11878268032, 11886656896, + 11895044992, 11903433088, 11911822976, 11920210816, 11928600448, + 11936987264, 11945375872, 11953761152, 11962151296, 11970543488, + 11978928512, 11987320448, 11995708288, 12004095104, 12012486272, + 12020875136, 12029255552, 12037652096, 12046039168, 12054429568, + 12062813824, 12071206528, 12079594624, 12087983744, 12096371072, + 12104759936, 12113147264, 12121534592, 12129924992, 12138314624, + 12146703232, 12155091584, 12163481216, 12171864704, 12180255872, + 12188643968, 12197034112, 12205424512, 12213811328, 12222199424, + 12230590336, 12238977664, 12247365248, 12255755392, 12264143488, + 12272531584, 12280920448, 12289309568, 12297694592, 12306086528, + 12314475392, 12322865024, 12331253632, 12339640448, 12348029312, + 12356418944, 12364805248, 12373196672, 12381580928, 12389969024, + 12398357632, 12406750592, 12415138432, 12423527552, 12431916416, + 12440304512, 12448692352, 12457081216, 12465467776, 12473859968, + 12482245504, 12490636672, 12499025536, 12507411584, 12515801728, + 12524190592, 12532577152, 12540966272, 12549354368, 12557743232, + 12566129536, 12574523264, 12582911872, 12591299456, 12599688064, + 12608074624, 12616463488, 12624845696, 12633239936, 12641631616, + 12650019968, 12658407296, 12666795136, 12675183232, 12683574656, + 12691960192, 12700350592, 12708740224, 12717128576, 12725515904, + 12733906816, 12742295168, 12750680192, 12759071872, 12767460736, + 12775848832, 12784236928, 12792626816, 12801014656, 12809404288, + 12817789312, 12826181504, 12834568832, 12842954624, 12851345792, + 12859732352, 12868122496, 12876512128, 12884901248, 12893289088, + 12901672832, 12910067584, 12918455168, 12926842496, 12935232896, + 12943620736, 12952009856, 12960396928, 12968786816, 12977176192, + 12985563776, 12993951104, 13002341504, 13010730368, 13019115392, + 13027506304, 13035895168, 13044272512, 13052673152, 13061062528, + 13069446272, 13077838976, 13086227072, 13094613632, 13103000192, + 13111393664, 13119782528, 13128157568, 13136559232, 13144945024, + 13153329536, 13161724288, 13170111872, 13178502784, 13186884736, + 13195279744, 13203667072, 13212057472, 13220445824, 13228832128, + 13237221248, 13245610624, 13254000512, 13262388352, 13270777472, + 13279166336, 13287553408, 13295943296, 13304331904, 13312719488, + 13321108096, 13329494656, 13337885824, 13346274944, 13354663808, + 13363051136, 13371439232, 13379825024, 13388210816, 13396605056, + 13404995456, 13413380224, 13421771392, 13430159744, 13438546048, + 13446937216, 13455326848, 13463708288, 13472103808, 13480492672, + 13488875648, 13497269888, 13505657728, 13514045312, 13522435712, + 13530824576, 13539210112, 13547599232, 13555989376, 13564379008, + 13572766336, 13581154432, 13589544832, 13597932928, 13606320512, + 13614710656, 13623097472, 13631477632, 13639874944, 13648264064, + 13656652928, 13665041792, 13673430656, 13681818496, 13690207616, + 13698595712, 13706982272, 13715373184, 13723762048, 13732150144, + 13740536704, 13748926592, 13757316224, 13765700992, 13774090112, + 13782477952, 13790869376, 13799259008, 13807647872, 13816036736, + 13824425344, 13832814208, 13841202304, 13849591424, 13857978752, + 13866368896, 13874754688, 13883145344, 13891533184, 13899919232, + 13908311168, 13916692096, 13925085056, 13933473152, 13941866368, + 13950253696, 13958643584, 13967032192, 13975417216, 13983807616, + 13992197504, 14000582272, 14008973696, 14017363072, 14025752192, + 14034137984, 14042528384, 14050918016, 14059301504, 14067691648, + 14076083584, 14084470144, 14092852352, 14101249664, 14109635968, + 14118024832, 14126407552, 14134804352, 14143188608, 14151577984, + 14159968384, 14168357248, 14176741504, 14185127296, 14193521024, + 14201911424, 14210301824, 14218685056, 14227067264, 14235467392, + 14243855488, 14252243072, 14260630144, 14269021568, 14277409408, + 14285799296, 14294187904, 14302571392, 14310961792, 14319353728, + 14327738752, 14336130944, 14344518784, 14352906368, 14361296512, + 14369685376, 14378071424, 14386462592, 14394848128, 14403230848, + 14411627392, 14420013952, 14428402304, 14436793472, 14445181568, + 14453569664, 14461959808, 14470347904, 14478737024, 14487122816, + 14495511424, 14503901824, 14512291712, 14520677504, 14529064832, + 14537456768, 14545845632, 14554234496, 14562618496, 14571011456, + 14579398784, 14587789184, 14596172672, 14604564608, 14612953984, + 14621341312, 14629724288, 14638120832, 14646503296, 14654897536, + 14663284864, 14671675264, 14680061056, 14688447616, 14696835968, + 14705228416, 14713616768, 14722003328, 14730392192, 14738784128, + 14747172736, 14755561088, 14763947648, 14772336512, 14780725376, + 14789110144, 14797499776, 14805892736, 14814276992, 14822670208, + 14831056256, 14839444352, 14847836032, 14856222848, 14864612992, + 14872997504, 14881388672, 14889775744, 14898165376, 14906553472, + 14914944896, 14923329664, 14931721856, 14940109696, 14948497024, + 14956887424, 14965276544, 14973663616, 14982053248, 14990439808, + 14998830976, 15007216768, 15015605888, 15023995264, 15032385152, + 15040768384, 15049154944, 15057549184, 15065939072, 15074328448, + 15082715008, 15091104128, 15099493504, 15107879296, 15116269184, + 15124659584, 15133042304, 15141431936, 15149824384, 15158214272, + 15166602368, 15174991232, 15183378304, 15191760512, 15200154496, + 15208542592, 15216931712, 15225323392, 15233708416, 15242098048, + 15250489216, 15258875264, 15267265408, 15275654528, 15284043136, + 15292431488, 15300819584, 15309208192, 15317596544, 15325986176, + 15334374784, 15342763648, 15351151744, 15359540608, 15367929728, + 15376318336, 15384706432, 15393092992, 15401481856, 15409869952, + 15418258816, 15426649984, 15435037568, 15443425664, 15451815296, + 15460203392, 15468589184, 15476979328, 15485369216, 15493755776, + 15502146944, 15510534272, 15518924416, 15527311232, 15535699072, + 15544089472, 15552478336, 15560866688, 15569254528, 15577642624, + 15586031488, 15594419072, 15602809472, 15611199104, 15619586432, + 15627975296, 15636364928, 15644753792, 15653141888, 15661529216, + 15669918848, 15678305152, 15686696576, 15695083136, 15703474048, + 15711861632, 15720251264, 15728636288, 15737027456, 15745417088, + 15753804928, 15762194048, 15770582656, 15778971008, 15787358336, + 15795747712, 15804132224, 15812523392, 15820909696, 15829300096, + 15837691264, 15846071936, 15854466944, 15862855808, 15871244672, + 15879634816, 15888020608, 15896409728, 15904799104, 15913185152, + 15921577088, 15929966464, 15938354816, 15946743424, 15955129472, + 15963519872, 15971907968, 15980296064, 15988684928, 15997073024, + 16005460864, 16013851264, 16022241152, 16030629248, 16039012736, + 16047406976, 16055794816, 16064181376, 16072571264, 16080957824, + 16089346688, 16097737856, 16106125184, 16114514816, 16122904192, + 16131292544, 16139678848, 16148066944, 16156453504, 16164839552, + 16173236096, 16181623424, 16190012032, 16198401152, 16206790528, + 16215177344, 16223567744, 16231956352, 16240344704, 16248731008, + 16257117824, 16265504384, 16273898624, 16282281856, 16290668672, + 16299064192, 16307449216, 16315842176, 16324230016, 16332613504, + 16341006464, 16349394304, 16357783168, 16366172288, 16374561664, + 16382951296, 16391337856, 16399726208, 16408116352, 16416505472, + 16424892032, 16433282176, 16441668224, 16450058624, 16458448768, + 16466836864, 16475224448, 16483613056, 16492001408, 16500391808, + 16508779648, 16517166976, 16525555328, 16533944192, 16542330752, + 16550719616, 16559110528, 16567497088, 16575888512, 16584274816, + 16592665472, 16601051008, 16609442944, 16617832064, 16626218624, + 16634607488, 16642996096, 16651385728, 16659773824, 16668163712, + 16676552576, 16684938112, 16693328768, 16701718144, 16710095488, + 16718492288, 16726883968, 16735272832, 16743661184, 16752049792, + 16760436608, 16768827008, 16777214336, 16785599104, 16793992832, + 16802381696, 16810768768, 16819151744, 16827542656, 16835934848, + 16844323712, 16852711552, 16861101952, 16869489536, 16877876864, + 16886265728, 16894653056, 16903044736, 16911431296, 16919821696, + 16928207488, 16936592768, 16944987776, 16953375616, 16961763968, + 16970152832, 16978540928, 16986929536, 16995319168, 17003704448, + 17012096896, 17020481152, 17028870784, 17037262208, 17045649536, + 17054039936, 17062426496, 17070814336, 17079205504, 17087592064, + 17095978112, 17104369024, 17112759424, 17121147776, 17129536384, + 17137926016, 17146314368, 17154700928, 17163089792, 17171480192, + 17179864192, 17188256896, 17196644992, 17205033856, 17213423488, + 17221811072, 17230198912, 17238588032, 17246976896, 17255360384, + 17263754624, 17272143232, 17280530048, 17288918912, 17297309312, + 17305696384, 17314085504, 17322475136, 17330863744, 17339252096, + 17347640192, 17356026496, 17364413824, 17372796544, 17381190016, + 17389583488, 17397972608, 17406360704, 17414748544, 17423135872, + 17431527296, 17439915904, 17448303232, 17456691584, 17465081728, + 17473468288, 17481857408, 17490247552, 17498635904, 17507022464, + 17515409024, 17523801728, 17532189824, 17540577664, 17548966016, + 17557353344, 17565741184, 17574131584, 17582519168, 17590907008, + 17599296128, 17607687808, 17616076672, 17624455808, 17632852352, + 17641238656, 17649630848, 17658018944, 17666403968, 17674794112, + 17683178368, 17691573376, 17699962496, 17708350592, 17716739968, + 17725126528, 17733517184, 17741898112, 17750293888, 17758673024, + 17767070336, 17775458432, 17783848832, 17792236928, 17800625536, + 17809012352, 17817402752, 17825785984, 17834178944, 17842563968, + 17850955648, 17859344512, 17867732864, 17876119424, 17884511872, + 17892900224, 17901287296, 17909677696, 17918058112, 17926451072, + 17934843776, 17943230848, 17951609216, 17960008576, 17968397696, + 17976784256, 17985175424, 17993564032, 18001952128, 18010339712, + 18018728576, 18027116672, 18035503232, 18043894144, 18052283264, + 18060672128, 18069056384, 18077449856, 18085837184, 18094225792, + 18102613376, 18111004544, 18119388544, 18127781248, 18136170368, + 18144558976, 18152947328, 18161336192, 18169724288, 18178108544, + 18186498944, 18194886784, 18203275648, 18211666048, 18220048768, + 18228444544, 18236833408, 18245220736} + +// cacheSizes is a lookup table for the ethash verification cache size for the +// first 2048 epochs (i.e. 61440000 blocks). +var cacheSizes = [maxEpoch]uint64{ + 16776896, 16907456, 17039296, 17170112, 17301056, 17432512, 17563072, + 17693888, 17824192, 17955904, 18087488, 18218176, 18349504, 18481088, + 18611392, 18742336, 18874304, 19004224, 19135936, 19267264, 19398208, + 19529408, 19660096, 19791424, 19922752, 20053952, 20184896, 20315968, + 20446912, 20576576, 20709184, 20840384, 20971072, 21102272, 21233216, + 21364544, 21494848, 21626816, 21757376, 21887552, 22019392, 22151104, + 22281536, 22412224, 22543936, 22675264, 22806464, 22935872, 23068096, + 23198272, 23330752, 23459008, 23592512, 23723968, 23854912, 23986112, + 24116672, 24247616, 24378688, 24509504, 24640832, 24772544, 24903488, + 25034432, 25165376, 25296704, 25427392, 25558592, 25690048, 25820096, + 25951936, 26081728, 26214208, 26345024, 26476096, 26606656, 26737472, + 26869184, 26998208, 27131584, 27262528, 27393728, 27523904, 27655744, + 27786688, 27917888, 28049344, 28179904, 28311488, 28441792, 28573504, + 28700864, 28835648, 28966208, 29096768, 29228608, 29359808, 29490752, + 29621824, 29752256, 29882816, 30014912, 30144448, 30273728, 30406976, + 30538432, 30670784, 30799936, 30932672, 31063744, 31195072, 31325248, + 31456192, 31588288, 31719232, 31850432, 31981504, 32110784, 32243392, + 32372672, 32505664, 32636608, 32767808, 32897344, 33029824, 33160768, + 33289664, 33423296, 33554368, 33683648, 33816512, 33947456, 34076992, + 34208704, 34340032, 34471744, 34600256, 34734016, 34864576, 34993984, + 35127104, 35258176, 35386688, 35518528, 35650624, 35782336, 35910976, + 36044608, 36175808, 36305728, 36436672, 36568384, 36699968, 36830656, + 36961984, 37093312, 37223488, 37355072, 37486528, 37617472, 37747904, + 37879232, 38009792, 38141888, 38272448, 38403392, 38535104, 38660672, + 38795584, 38925632, 39059264, 39190336, 39320768, 39452096, 39581632, + 39713984, 39844928, 39974848, 40107968, 40238144, 40367168, 40500032, + 40631744, 40762816, 40894144, 41023552, 41155904, 41286208, 41418304, + 41547712, 41680448, 41811904, 41942848, 42073792, 42204992, 42334912, + 42467008, 42597824, 42729152, 42860096, 42991552, 43122368, 43253696, + 43382848, 43515712, 43646912, 43777088, 43907648, 44039104, 44170432, + 44302144, 44433344, 44564288, 44694976, 44825152, 44956864, 45088448, + 45219008, 45350464, 45481024, 45612608, 45744064, 45874496, 46006208, + 46136768, 46267712, 46399424, 46529344, 46660672, 46791488, 46923328, + 47053504, 47185856, 47316928, 47447872, 47579072, 47710144, 47839936, + 47971648, 48103232, 48234176, 48365248, 48496192, 48627136, 48757312, + 48889664, 49020736, 49149248, 49283008, 49413824, 49545152, 49675712, + 49807168, 49938368, 50069056, 50200256, 50331584, 50462656, 50593472, + 50724032, 50853952, 50986048, 51117632, 51248576, 51379904, 51510848, + 51641792, 51773248, 51903296, 52035136, 52164032, 52297664, 52427968, + 52557376, 52690112, 52821952, 52952896, 53081536, 53213504, 53344576, + 53475776, 53608384, 53738816, 53870528, 54000832, 54131776, 54263744, + 54394688, 54525248, 54655936, 54787904, 54918592, 55049152, 55181248, + 55312064, 55442752, 55574336, 55705024, 55836224, 55967168, 56097856, + 56228672, 56358592, 56490176, 56621888, 56753728, 56884928, 57015488, + 57146816, 57278272, 57409216, 57540416, 57671104, 57802432, 57933632, + 58064576, 58195264, 58326976, 58457408, 58588864, 58720192, 58849984, + 58981696, 59113024, 59243456, 59375552, 59506624, 59637568, 59768512, + 59897792, 60030016, 60161984, 60293056, 60423872, 60554432, 60683968, + 60817216, 60948032, 61079488, 61209664, 61341376, 61471936, 61602752, + 61733696, 61865792, 61996736, 62127808, 62259136, 62389568, 62520512, + 62651584, 62781632, 62910784, 63045056, 63176128, 63307072, 63438656, + 63569216, 63700928, 63831616, 63960896, 64093888, 64225088, 64355392, + 64486976, 64617664, 64748608, 64879424, 65009216, 65142464, 65273792, + 65402816, 65535424, 65666752, 65797696, 65927744, 66060224, 66191296, + 66321344, 66453056, 66584384, 66715328, 66846656, 66977728, 67108672, + 67239104, 67370432, 67501888, 67631296, 67763776, 67895104, 68026304, + 68157248, 68287936, 68419264, 68548288, 68681408, 68811968, 68942912, + 69074624, 69205568, 69337024, 69467584, 69599168, 69729472, 69861184, + 69989824, 70122944, 70253888, 70385344, 70515904, 70647232, 70778816, + 70907968, 71040832, 71171648, 71303104, 71432512, 71564992, 71695168, + 71826368, 71958464, 72089536, 72219712, 72350144, 72482624, 72613568, + 72744512, 72875584, 73006144, 73138112, 73268672, 73400128, 73530944, + 73662272, 73793344, 73924544, 74055104, 74185792, 74316992, 74448832, + 74579392, 74710976, 74841664, 74972864, 75102784, 75233344, 75364544, + 75497024, 75627584, 75759296, 75890624, 76021696, 76152256, 76283072, + 76414144, 76545856, 76676672, 76806976, 76937792, 77070016, 77200832, + 77331392, 77462464, 77593664, 77725376, 77856448, 77987776, 78118336, + 78249664, 78380992, 78511424, 78642496, 78773056, 78905152, 79033664, + 79166656, 79297472, 79429568, 79560512, 79690816, 79822784, 79953472, + 80084672, 80214208, 80346944, 80477632, 80608576, 80740288, 80870848, + 81002048, 81133504, 81264448, 81395648, 81525952, 81657536, 81786304, + 81919808, 82050112, 82181312, 82311616, 82443968, 82573376, 82705984, + 82835776, 82967744, 83096768, 83230528, 83359552, 83491264, 83622464, + 83753536, 83886016, 84015296, 84147776, 84277184, 84409792, 84540608, + 84672064, 84803008, 84934336, 85065152, 85193792, 85326784, 85458496, + 85589312, 85721024, 85851968, 85982656, 86112448, 86244416, 86370112, + 86506688, 86637632, 86769344, 86900672, 87031744, 87162304, 87293632, + 87424576, 87555392, 87687104, 87816896, 87947968, 88079168, 88211264, + 88341824, 88473152, 88603712, 88735424, 88862912, 88996672, 89128384, + 89259712, 89390272, 89521984, 89652544, 89783872, 89914816, 90045376, + 90177088, 90307904, 90438848, 90569152, 90700096, 90832832, 90963776, + 91093696, 91223744, 91356992, 91486784, 91618496, 91749824, 91880384, + 92012224, 92143552, 92273344, 92405696, 92536768, 92666432, 92798912, + 92926016, 93060544, 93192128, 93322816, 93453632, 93583936, 93715136, + 93845056, 93977792, 94109504, 94240448, 94371776, 94501184, 94632896, + 94764224, 94895552, 95023424, 95158208, 95287744, 95420224, 95550016, + 95681216, 95811904, 95943872, 96075328, 96203584, 96337856, 96468544, + 96599744, 96731072, 96860992, 96992576, 97124288, 97254848, 97385536, + 97517248, 97647808, 97779392, 97910464, 98041408, 98172608, 98303168, + 98434496, 98565568, 98696768, 98827328, 98958784, 99089728, 99220928, + 99352384, 99482816, 99614272, 99745472, 99876416, 100007104, + 100138048, 100267072, 100401088, 100529984, 100662592, 100791872, + 100925248, 101056064, 101187392, 101317952, 101449408, 101580608, + 101711296, 101841728, 101973824, 102104896, 102235712, 102366016, + 102498112, 102628672, 102760384, 102890432, 103021888, 103153472, + 103284032, 103415744, 103545152, 103677248, 103808576, 103939648, + 104070976, 104201792, 104332736, 104462528, 104594752, 104725952, + 104854592, 104988608, 105118912, 105247808, 105381184, 105511232, + 105643072, 105774784, 105903296, 106037056, 106167872, 106298944, + 106429504, 106561472, 106691392, 106822592, 106954304, 107085376, + 107216576, 107346368, 107478464, 107609792, 107739712, 107872192, + 108003136, 108131392, 108265408, 108396224, 108527168, 108657344, + 108789568, 108920384, 109049792, 109182272, 109312576, 109444928, + 109572928, 109706944, 109837888, 109969088, 110099648, 110230976, + 110362432, 110492992, 110624704, 110755264, 110886208, 111017408, + 111148864, 111279296, 111410752, 111541952, 111673024, 111803456, + 111933632, 112066496, 112196416, 112328512, 112457792, 112590784, + 112715968, 112852672, 112983616, 113114944, 113244224, 113376448, + 113505472, 113639104, 113770304, 113901376, 114031552, 114163264, + 114294592, 114425536, 114556864, 114687424, 114818624, 114948544, + 115080512, 115212224, 115343296, 115473472, 115605184, 115736128, + 115867072, 115997248, 116128576, 116260288, 116391488, 116522944, + 116652992, 116784704, 116915648, 117046208, 117178304, 117308608, + 117440192, 117569728, 117701824, 117833024, 117964096, 118094656, + 118225984, 118357312, 118489024, 118617536, 118749632, 118882112, + 119012416, 119144384, 119275328, 119406016, 119537344, 119668672, + 119798464, 119928896, 120061376, 120192832, 120321728, 120454336, + 120584512, 120716608, 120848192, 120979136, 121109056, 121241408, + 121372352, 121502912, 121634752, 121764416, 121895744, 122027072, + 122157632, 122289088, 122421184, 122550592, 122682944, 122813888, + 122945344, 123075776, 123207488, 123338048, 123468736, 123600704, + 123731264, 123861952, 123993664, 124124608, 124256192, 124386368, + 124518208, 124649024, 124778048, 124911296, 125041088, 125173696, + 125303744, 125432896, 125566912, 125696576, 125829056, 125958592, + 126090304, 126221248, 126352832, 126483776, 126615232, 126746432, + 126876608, 127008704, 127139392, 127270336, 127401152, 127532224, + 127663552, 127794752, 127925696, 128055232, 128188096, 128319424, + 128449856, 128581312, 128712256, 128843584, 128973632, 129103808, + 129236288, 129365696, 129498944, 129629888, 129760832, 129892288, + 130023104, 130154048, 130283968, 130416448, 130547008, 130678336, + 130807616, 130939456, 131071552, 131202112, 131331776, 131464384, + 131594048, 131727296, 131858368, 131987392, 132120256, 132250816, + 132382528, 132513728, 132644672, 132774976, 132905792, 133038016, + 133168832, 133299392, 133429312, 133562048, 133692992, 133823296, + 133954624, 134086336, 134217152, 134348608, 134479808, 134607296, + 134741056, 134872384, 135002944, 135134144, 135265472, 135396544, + 135527872, 135659072, 135787712, 135921472, 136052416, 136182848, + 136313792, 136444864, 136576448, 136707904, 136837952, 136970048, + 137099584, 137232064, 137363392, 137494208, 137625536, 137755712, + 137887424, 138018368, 138149824, 138280256, 138411584, 138539584, + 138672832, 138804928, 138936128, 139066688, 139196864, 139328704, + 139460032, 139590208, 139721024, 139852864, 139984576, 140115776, + 140245696, 140376512, 140508352, 140640064, 140769856, 140902336, + 141032768, 141162688, 141294016, 141426496, 141556544, 141687488, + 141819584, 141949888, 142080448, 142212544, 142342336, 142474432, + 142606144, 142736192, 142868288, 142997824, 143129408, 143258944, + 143392448, 143523136, 143653696, 143785024, 143916992, 144045632, + 144177856, 144309184, 144440768, 144570688, 144701888, 144832448, + 144965056, 145096384, 145227584, 145358656, 145489856, 145620928, + 145751488, 145883072, 146011456, 146144704, 146275264, 146407232, + 146538176, 146668736, 146800448, 146931392, 147062336, 147193664, + 147324224, 147455936, 147586624, 147717056, 147848768, 147979456, + 148110784, 148242368, 148373312, 148503232, 148635584, 148766144, + 148897088, 149028416, 149159488, 149290688, 149420224, 149551552, + 149683136, 149814976, 149943616, 150076352, 150208064, 150338624, + 150470464, 150600256, 150732224, 150862784, 150993088, 151125952, + 151254976, 151388096, 151519168, 151649728, 151778752, 151911104, + 152042944, 152174144, 152304704, 152435648, 152567488, 152698816, + 152828992, 152960576, 153091648, 153222976, 153353792, 153484096, + 153616192, 153747008, 153878336, 154008256, 154139968, 154270912, + 154402624, 154533824, 154663616, 154795712, 154926272, 155057984, + 155188928, 155319872, 155450816, 155580608, 155712064, 155843392, + 155971136, 156106688, 156237376, 156367424, 156499264, 156630976, + 156761536, 156892352, 157024064, 157155008, 157284416, 157415872, + 157545536, 157677248, 157810496, 157938112, 158071744, 158203328, + 158334656, 158464832, 158596288, 158727616, 158858048, 158988992, + 159121216, 159252416, 159381568, 159513152, 159645632, 159776192, + 159906496, 160038464, 160169536, 160300352, 160430656, 160563008, + 160693952, 160822208, 160956352, 161086784, 161217344, 161349184, + 161480512, 161611456, 161742272, 161873216, 162002752, 162135872, + 162266432, 162397888, 162529216, 162660032, 162790976, 162922048, + 163052096, 163184576, 163314752, 163446592, 163577408, 163707968, + 163839296, 163969984, 164100928, 164233024, 164364224, 164494912, + 164625856, 164756672, 164887616, 165019072, 165150016, 165280064, + 165412672, 165543104, 165674944, 165805888, 165936832, 166067648, + 166198336, 166330048, 166461248, 166591552, 166722496, 166854208, + 166985408, 167116736, 167246656, 167378368, 167508416, 167641024, + 167771584, 167903168, 168034112, 168164032, 168295744, 168427456, + 168557632, 168688448, 168819136, 168951616, 169082176, 169213504, + 169344832, 169475648, 169605952, 169738048, 169866304, 169999552, + 170131264, 170262464, 170393536, 170524352, 170655424, 170782016, + 170917696, 171048896, 171179072, 171310784, 171439936, 171573184, + 171702976, 171835072, 171966272, 172097216, 172228288, 172359232, + 172489664, 172621376, 172747712, 172883264, 173014208, 173144512, + 173275072, 173407424, 173539136, 173669696, 173800768, 173931712, + 174063424, 174193472, 174325696, 174455744, 174586816, 174718912, + 174849728, 174977728, 175109696, 175242688, 175374272, 175504832, + 175636288, 175765696, 175898432, 176028992, 176159936, 176291264, + 176422592, 176552512, 176684864, 176815424, 176946496, 177076544, + 177209152, 177340096, 177470528, 177600704, 177731648, 177864256, + 177994816, 178126528, 178257472, 178387648, 178518464, 178650176, + 178781888, 178912064, 179044288, 179174848, 179305024, 179436736, + 179568448, 179698496, 179830208, 179960512, 180092608, 180223808, + 180354752, 180485696, 180617152, 180748096, 180877504, 181009984, + 181139264, 181272512, 181402688, 181532608, 181663168, 181795136, + 181926592, 182057536, 182190016, 182320192, 182451904, 182582336, + 182713792, 182843072, 182976064, 183107264, 183237056, 183368384, + 183494848, 183631424, 183762752, 183893824, 184024768, 184154816, + 184286656, 184417984, 184548928, 184680128, 184810816, 184941248, + 185072704, 185203904, 185335616, 185465408, 185596352, 185727296, + 185859904, 185989696, 186121664, 186252992, 186383552, 186514112, + 186645952, 186777152, 186907328, 187037504, 187170112, 187301824, + 187429184, 187562048, 187693504, 187825472, 187957184, 188087104, + 188218304, 188349376, 188481344, 188609728, 188743616, 188874304, + 189005248, 189136448, 189265088, 189396544, 189528128, 189660992, + 189791936, 189923264, 190054208, 190182848, 190315072, 190447424, + 190577984, 190709312, 190840768, 190971328, 191102656, 191233472, + 191364032, 191495872, 191626816, 191758016, 191888192, 192020288, + 192148928, 192282176, 192413504, 192542528, 192674752, 192805952, + 192937792, 193068608, 193198912, 193330496, 193462208, 193592384, + 193723456, 193854272, 193985984, 194116672, 194247232, 194379712, + 194508352, 194641856, 194772544, 194900672, 195035072, 195166016, + 195296704, 195428032, 195558592, 195690304, 195818176, 195952576, + 196083392, 196214336, 196345792, 196476736, 196607552, 196739008, + 196869952, 197000768, 197130688, 197262784, 197394368, 197523904, + 197656384, 197787584, 197916608, 198049472, 198180544, 198310208, + 198442432, 198573632, 198705088, 198834368, 198967232, 199097792, + 199228352, 199360192, 199491392, 199621696, 199751744, 199883968, + 200014016, 200146624, 200276672, 200408128, 200540096, 200671168, + 200801984, 200933312, 201062464, 201194944, 201326144, 201457472, + 201588544, 201719744, 201850816, 201981632, 202111552, 202244032, + 202374464, 202505152, 202636352, 202767808, 202898368, 203030336, + 203159872, 203292608, 203423296, 203553472, 203685824, 203816896, + 203947712, 204078272, 204208192, 204341056, 204472256, 204603328, + 204733888, 204864448, 204996544, 205125568, 205258304, 205388864, + 205517632, 205650112, 205782208, 205913536, 206044736, 206176192, + 206307008, 206434496, 206569024, 206700224, 206831168, 206961856, + 207093056, 207223616, 207355328, 207486784, 207616832, 207749056, + 207879104, 208010048, 208141888, 208273216, 208404032, 208534336, + 208666048, 208796864, 208927424, 209059264, 209189824, 209321792, + 209451584, 209582656, 209715136, 209845568, 209976896, 210106432, + 210239296, 210370112, 210501568, 210630976, 210763712, 210894272, + 211024832, 211156672, 211287616, 211418176, 211549376, 211679296, + 211812032, 211942592, 212074432, 212204864, 212334016, 212467648, + 212597824, 212727616, 212860352, 212991424, 213120832, 213253952, + 213385024, 213515584, 213645632, 213777728, 213909184, 214040128, + 214170688, 214302656, 214433728, 214564544, 214695232, 214826048, + 214956992, 215089088, 215219776, 215350592, 215482304, 215613248, + 215743552, 215874752, 216005312, 216137024, 216267328, 216399296, + 216530752, 216661696, 216790592, 216923968, 217054528, 217183168, + 217316672, 217448128, 217579072, 217709504, 217838912, 217972672, + 218102848, 218233024, 218364736, 218496832, 218627776, 218759104, + 218888896, 219021248, 219151936, 219281728, 219413056, 219545024, + 219675968, 219807296, 219938624, 220069312, 220200128, 220331456, + 220461632, 220592704, 220725184, 220855744, 220987072, 221117888, + 221249216, 221378368, 221510336, 221642048, 221772736, 221904832, + 222031808, 222166976, 222297536, 222428992, 222559936, 222690368, + 222820672, 222953152, 223083968, 223213376, 223345984, 223476928, + 223608512, 223738688, 223869376, 224001472, 224132672, 224262848, + 224394944, 224524864, 224657344, 224788288, 224919488, 225050432, + 225181504, 225312704, 225443776, 225574592, 225704768, 225834176, + 225966784, 226097216, 226229824, 226360384, 226491712, 226623424, + 226754368, 226885312, 227015104, 227147456, 227278528, 227409472, + 227539904, 227669696, 227802944, 227932352, 228065216, 228196288, + 228326464, 228457792, 228588736, 228720064, 228850112, 228981056, + 229113152, 229243328, 229375936, 229505344, 229636928, 229769152, + 229894976, 230030272, 230162368, 230292416, 230424512, 230553152, + 230684864, 230816704, 230948416, 231079616, 231210944, 231342016, + 231472448, 231603776, 231733952, 231866176, 231996736, 232127296, + 232259392, 232388672, 232521664, 232652608, 232782272, 232914496, + 233043904, 233175616, 233306816, 233438528, 233569984, 233699776, + 233830592, 233962688, 234092224, 234221888, 234353984, 234485312, + 234618304, 234749888, 234880832, 235011776, 235142464, 235274048, + 235403456, 235535936, 235667392, 235797568, 235928768, 236057152, + 236190272, 236322752, 236453312, 236583616, 236715712, 236846528, + 236976448, 237108544, 237239104, 237371072, 237501632, 237630784, + 237764416, 237895232, 238026688, 238157632, 238286912, 238419392, + 238548032, 238681024, 238812608, 238941632, 239075008, 239206336, + 239335232, 239466944, 239599168, 239730496, 239861312, 239992384, + 240122816, 240254656, 240385856, 240516928, 240647872, 240779072, + 240909632, 241040704, 241171904, 241302848, 241433408, 241565248, + 241696192, 241825984, 241958848, 242088256, 242220224, 242352064, + 242481856, 242611648, 242744896, 242876224, 243005632, 243138496, + 243268672, 243400384, 243531712, 243662656, 243793856, 243924544, + 244054592, 244187072, 244316608, 244448704, 244580032, 244710976, + 244841536, 244972864, 245104448, 245233984, 245365312, 245497792, + 245628736, 245759936, 245889856, 246021056, 246152512, 246284224, + 246415168, 246545344, 246675904, 246808384, 246939584, 247070144, + 247199552, 247331648, 247463872, 247593536, 247726016, 247857088, + 247987648, 248116928, 248249536, 248380736, 248512064, 248643008, + 248773312, 248901056, 249036608, 249167552, 249298624, 249429184, + 249560512, 249692096, 249822784, 249954112, 250085312, 250215488, + 250345792, 250478528, 250608704, 250739264, 250870976, 251002816, + 251133632, 251263552, 251395136, 251523904, 251657792, 251789248, + 251919424, 252051392, 252182464, 252313408, 252444224, 252575552, + 252706624, 252836032, 252968512, 253099712, 253227584, 253361728, + 253493056, 253623488, 253754432, 253885504, 254017216, 254148032, + 254279488, 254410432, 254541376, 254672576, 254803264, 254933824, + 255065792, 255196736, 255326528, 255458752, 255589952, 255721408, + 255851072, 255983296, 256114624, 256244416, 256374208, 256507712, + 256636096, 256768832, 256900544, 257031616, 257162176, 257294272, + 257424448, 257555776, 257686976, 257818432, 257949632, 258079552, + 258211136, 258342464, 258473408, 258603712, 258734656, 258867008, + 258996544, 259127744, 259260224, 259391296, 259522112, 259651904, + 259784384, 259915328, 260045888, 260175424, 260308544, 260438336, + 260570944, 260700992, 260832448, 260963776, 261092672, 261226304, + 261356864, 261487936, 261619648, 261750592, 261879872, 262011968, + 262143424, 262274752, 262404416, 262537024, 262667968, 262799296, + 262928704, 263061184, 263191744, 263322944, 263454656, 263585216, + 263716672, 263847872, 263978944, 264108608, 264241088, 264371648, + 264501184, 264632768, 264764096, 264895936, 265024576, 265158464, + 265287488, 265418432, 265550528, 265681216, 265813312, 265943488, + 266075968, 266206144, 266337728, 266468032, 266600384, 266731072, + 266862272, 266993344, 267124288, 267255616, 267386432, 267516992, + 267648704, 267777728, 267910592, 268040512, 268172096, 268302784, + 268435264, 268566208, 268696256, 268828096, 268959296, 269090368, + 269221312, 269352256, 269482688, 269614784, 269745856, 269876416, + 270007616, 270139328, 270270272, 270401216, 270531904, 270663616, + 270791744, 270924736, 271056832, 271186112, 271317184, 271449536, + 271580992, 271711936, 271843136, 271973056, 272105408, 272236352, + 272367296, 272498368, 272629568, 272759488, 272891456, 273022784, + 273153856, 273284672, 273415616, 273547072, 273677632, 273808448, + 273937088, 274071488, 274200896, 274332992, 274463296, 274595392, + 274726208, 274857536, 274988992, 275118656, 275250496, 275382208, + 275513024, 275643968, 275775296, 275906368, 276037184, 276167872, + 276297664, 276429376, 276560576, 276692672, 276822976, 276955072, + 277085632, 277216832, 277347008, 277478848, 277609664, 277740992, + 277868608, 278002624, 278134336, 278265536, 278395328, 278526784, + 278657728, 278789824, 278921152, 279052096, 279182912, 279313088, + 279443776, 279576256, 279706048, 279838528, 279969728, 280099648, + 280230976, 280361408, 280493632, 280622528, 280755392, 280887104, + 281018176, 281147968, 281278912, 281411392, 281542592, 281673152, + 281803712, 281935552, 282066496, 282197312, 282329024, 282458816, + 282590272, 282720832, 282853184, 282983744, 283115072, 283246144, + 283377344, 283508416, 283639744, 283770304, 283901504, 284032576, + 284163136, 284294848, 284426176, 284556992, 284687296, 284819264, + 284950208, 285081536} diff --git a/consensus/ethashb3/api.go b/consensus/ethashb3/api.go new file mode 100644 index 0000000000..aab2d67b84 --- /dev/null +++ b/consensus/ethashb3/api.go @@ -0,0 +1,113 @@ +// 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 ethashb3 + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +) + +var errEthashStopped = errors.New("ethashb3 stopped") + +// API exposes ethash related methods for the RPC interface. +type API struct { + ethash *EthashB3 +} + +// 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.ethash.remote == nil { + return [4]string{}, errors.New("not supported") + } + + var ( + workCh = make(chan [4]string, 1) + errc = make(chan error, 1) + ) + select { + case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}: + case <-api.ethash.remote.exitCh: + return [4]string{}, errEthashStopped + } + 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.ethash.remote == nil { + return false + } + + var errc = make(chan error, 1) + select { + case api.ethash.remote.submitWorkCh <- &mineResult{ + nonce: nonce, + mixDigest: digest, + hash: hash, + errc: errc, + }: + case <-api.ethash.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 { + if api.ethash.remote == nil { + return false + } + + var done = make(chan struct{}, 1) + select { + case api.ethash.remote.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}: + case <-api.ethash.remote.exitCh: + return false + } + + // Block until hash rate submitted successfully. + <-done + return true +} + +// GetHashrate returns the current hashrate for local CPU miner and remote miner. +func (api *API) GetHashrate() uint64 { + return uint64(api.ethash.Hashrate()) +} diff --git a/consensus/ethashb3/consensus.go b/consensus/ethashb3/consensus.go new file mode 100644 index 0000000000..b74f222100 --- /dev/null +++ b/consensus/ethashb3/consensus.go @@ -0,0 +1,513 @@ +// 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 ethashb3 + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "runtime" + "time" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/consensus/misc/eip1559" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params/mutations" + "github.com/ethereum/go-ethereum/params/types/ctypes" + "github.com/ethereum/go-ethereum/params/vars" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "golang.org/x/crypto/sha3" +) + +// EthashB3 proof-of-work protocol constants. +var ( + maxUncles = 2 // Maximum number of uncles allowed in a single block + allowedFutureBlockTime = 7 * time.Second // Max time 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 ( + errOlderBlockTime = errors.New("timestamp older than parent") + 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 (ethash *EthashB3) 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 ethash engine. +func (ethash *EthashB3) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + // If we're running a full engine faking, accept any input as valid + if ethash.config.PowMode == ModeFullFake { + return nil + } + // Short circuit if the header is known, or its 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 ethash.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 (ethash *EthashB3) 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 ethash.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] = ethash.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 (ethash *EthashB3) 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 ethash.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 ethash engine. +func (ethash *EthashB3) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + // If we're running a full engine faking, accept any input as valid + if ethash.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[common.Hash](), 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 := ethash.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 ethash engine. +// See YP section 4.3.4. "Block Header Validity" +func (ethash *EthashB3) 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)) > vars.MaximumExtraDataSize { + return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), vars.MaximumExtraDataSize) + } + // Verify the header's timestamp + if !uncle { + if header.Time > uint64(unixNow+int64(allowedFutureBlockTime.Seconds())) { + return consensus.ErrFutureBlock + } + } + if header.Time <= parent.Time { + return errOlderBlockTime + } + // Verify the block's difficulty based on its timestamp and parent's difficulty + expected := ethash.CalcDifficulty(chain, header.Time, parent) + + if expected.Cmp(header.Difficulty) != 0 { + return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) + } + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > vars.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, vars.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().IsEnabled(chain.Config().GetEIP1559Transition, 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 := eip1559.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 := ethash.verifySeal(chain, header, false); err != nil { + return err + } + } + // If all checks passed, validate any special fields for hard forks + if err := mutations.VerifyDAOHeaderExtraData(chain.Config(), header); 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 (ethash *EthashB3) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + return CalcDifficulty(chain.Config(), time, parent) +} + +// parent_time_delta is a convenience fn for CalcDifficulty +func parent_time_delta(t uint64, p *types.Header) *big.Int { + return new(big.Int).Sub(new(big.Int).SetUint64(t), new(big.Int).SetUint64(p.Time)) +} + +// parent_diff_over_dbd is a convenience fn for CalcDifficulty +func parent_diff_over_dbd(p *types.Header) *big.Int { + return new(big.Int).Div(p.Difficulty, vars.DifficultyBoundDivisor) +} + +// 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 ctypes.ChainConfigurator, time uint64, parent *types.Header) *big.Int { + next := new(big.Int).Add(parent.Number, big1) + out := new(big.Int) + + // TODO (meowbits): do we need this? + // if config.IsEnabled(config.GetEthashTerminalTotalDifficulty, next) { + // return big.NewInt(1) + // } + + // ADJUSTMENT algorithms + if config.IsEnabled(config.GetEthashEIP100BTransition, next) { + // https://github.com/ethereum/EIPs/issues/100 + // algorithm: + // diff = (parent_diff + + // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) + // ) + 2^(periodCount - 2) + out.Div(parent_time_delta(time, parent), big.NewInt(6)) + + if parent.UncleHash == types.EmptyUncleHash { + out.Sub(big1, out) + } else { + out.Sub(big2, out) + } + out.Set(math.BigMax(out, bigMinus99)) + out.Mul(parent_diff_over_dbd(parent), out) + out.Add(out, parent.Difficulty) + } else if config.IsEnabled(config.GetEIP2Transition, next) { + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md + // algorithm: + // diff = (parent_diff + + // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) + // ) + out.Div(parent_time_delta(time, parent), big.NewInt(5)) + out.Sub(big1, out) + out.Set(math.BigMax(out, bigMinus99)) + out.Mul(parent_diff_over_dbd(parent), out) + out.Add(out, parent.Difficulty) + } else { + // FRONTIER + // algorithm: + // diff = + // if parent_block_time_delta < params.DurationLimit + // parent_diff + (parent_diff // 2048) + // else + // parent_diff - (parent_diff // 2048) + out.Set(parent.Difficulty) + if parent_time_delta(time, parent).Cmp(vars.DurationLimit) < 0 { + out.Add(out, parent_diff_over_dbd(parent)) + } else { + out.Sub(out, parent_diff_over_dbd(parent)) + } + } + + // after adjustment and before bomb + out.Set(math.BigMax(out, vars.MinimumDifficulty)) + + return out +} + +// Some weird constants to avoid constant memory allocs for them. +var ( + big1 = big.NewInt(1) + big2 = big.NewInt(2) + bigMinus99 = big.NewInt(-99) +) + +// Exported for fuzzing +var FrontierDifficultyCalculator = CalcDifficultyFrontierU256 +var HomesteadDifficultyCalculator = CalcDifficultyHomesteadU256 +var DynamicDifficultyCalculator = MakeDifficultyCalculatorU256 + +// verifySeal checks whether a block satisfies the PoW difficulty requirements, +// either using the usual ethash cache for it, or alternatively using a full DAG +// to make remote mining fast. +func (ethash *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error { + // If we're running a fake PoW, accept any seal as valid + if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModePoissonFake || ethash.config.PowMode == ModeFullFake { + time.Sleep(ethash.fakeDelay) + if ethash.fakeFail == header.Number.Uint64() { + return errInvalidPoW + } + return nil + } + // If we're running a shared PoW, delegate verification to it + if ethash.shared != nil { + return ethash.shared.verifySeal(chain, header, fulldag) + } + // Ensure that we have a valid difficulty for the block + if header.Difficulty.Sign() <= 0 { + return errInvalidDifficulty + } + // Recompute the digest and PoW values + number := header.Number.Uint64() + + var ( + digest []byte + result []byte + ) + // If fast-but-heavy PoW verification was requested, use an ethash dataset + if fulldag { + dataset := ethash.dataset(number, true) + if dataset.generated() { + digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) + + // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive + // until after the call to hashimotoFull so it's not unmapped while being used. + runtime.KeepAlive(dataset) + } else { + // Dataset not yet generated, don't hang, use a cache instead + fulldag = false + } + } + // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache + if !fulldag { + cache := ethash.cache(number) + epochLength := calcEpochLength(number, ethash.config.ECIP1099Block) + epoch := calcEpoch(number, epochLength) + size := datasetSize(epoch) + if ethash.config.PowMode == ModeTest { + size = 32 * 1024 + } + digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) + + // Caches are unmapped in a finalizer. Ensure that the cache stays alive + // until after the call to hashimotoLight so it's not unmapped while being used. + runtime.KeepAlive(cache) + } + // Verify the calculated values against the ones provided in the header + if !bytes.Equal(header.MixDigest[:], digest) { + return errInvalidMixDigest + } + target := new(big.Int).Div(two256, header.Difficulty) + if new(big.Int).SetBytes(result).Cmp(target) > 0 { + return errInvalidPoW + } + return nil +} + +// Prepare implements consensus.Engine, initializing the difficulty field of a +// header to conform to the ethash protocol. The changes are done inline. +func (ethash *EthashB3) 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 = ethash.CalcDifficulty(chain, header.Time, parent) + return nil +} + +// Finalize implements consensus.Engine, accumulating the block and uncle rewards. +func (ethash *EthashB3) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { + // Accumulate any block and uncle rewards and commit the final state root + mutations.AccumulateRewards(chain.Config(), state, header, uncles) +} + +// FinalizeAndAssemble implements consensus.Engine, accumulating the block and +// uncle rewards, setting the final state and assembling the block. +func (ethash *EthashB3) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { + if len(withdrawals) > 0 { + return nil, errors.New("ethashb3 does not support withdrawals") + } + // Finalize block + ethash.Finalize(chain, header, state, txs, uncles, nil) + + // Assign the final state root to header. + header.Root = state.IntermediateRoot(chain.Config().IsEnabled(chain.Config().GetEIP161dTransition, header.Number)) + + // 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 (ethash *EthashB3) 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) + } + if header.WithdrawalsHash != nil { + panic("withdrawal hash set on ethashb3") + } + rlp.Encode(hasher, enc) + hasher.Sum(hash[:0]) + return hash +} diff --git a/consensus/ethashb3/difficulty.go b/consensus/ethashb3/difficulty.go new file mode 100644 index 0000000000..eb272e94ce --- /dev/null +++ b/consensus/ethashb3/difficulty.go @@ -0,0 +1,191 @@ +// Copyright 2020 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 ethashb3 + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" +) + +const ( + // frontierDurationLimit is for Frontier: + // The decision boundary on the blocktime duration used to determine + // whether difficulty should go up or down. + frontierDurationLimit = 7 + // minimumDifficulty The minimum that the difficulty may ever be. + minimumDifficulty = 5_100_077 + // 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 +) + +// CalcDifficultyFrontierU256 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 CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int { + /* + Algorithm + block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2)) + + Where: + - pdiff = parent.difficulty + - ptime = parent.time + - time = block.timestamp + - num = block.number + */ + + pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff + adjust := pDiff.Clone() + adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 + + if time-parent.Time < frontierDurationLimit { + pDiff.Add(pDiff, adjust) + } else { + pDiff.Sub(pDiff, adjust) + } + if pDiff.LtUint64(minimumDifficulty) { + pDiff.SetUint64(minimumDifficulty) + } + // 'pdiff' now contains: + // pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + + if periodCount := (parent.Number.Uint64() + 1) / expDiffPeriodUint; periodCount > 1 { + // diff = diff + 2^(periodCount - 2) + expDiff := adjust.SetOne() + expDiff.Lsh(expDiff, uint(periodCount-2)) // expdiff: 2 ^ (periodCount -2) + pDiff.Add(pDiff, expDiff) + } + return pDiff.ToBig() +} + +// CalcDifficultyHomesteadU256 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 Homestead rules. +func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int { + /* + https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md + Algorithm: + block_diff = pdiff + pdiff / 2048 * max(1 - (time - ptime) / 10, -99) + 2 ^ int((num / 100000) - 2)) + + Our modification, to use unsigned ints: + block_diff = pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + 2 ^ int((num / 100000) - 2)) + + Where: + - pdiff = parent.difficulty + - ptime = parent.time + - time = block.timestamp + - num = block.number + */ + + pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff + adjust := pDiff.Clone() + adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 + + x := (time - parent.Time) / 10 // (time - ptime) / 10) + var neg = true + if x == 0 { + x = 1 + neg = false + } else if x >= 100 { + x = 99 + } else { + x = x - 1 + } + z := new(uint256.Int).SetUint64(x) + adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99) + if neg { + pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + } else { + pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + } + if pDiff.LtUint64(minimumDifficulty) { + pDiff.SetUint64(minimumDifficulty) + } + // for the exponential factor, a.k.a "the bomb" + // diff = diff + 2^(periodCount - 2) + if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 { + expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2)) + pDiff.Add(pDiff, expFactor) + } + return pDiff.ToBig() +} + +// MakeDifficultyCalculatorU256 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 MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { + // Note, the calculations below looks at the parent number, which is 1 below + // the block number. Thus we remove one from the delay given + bombDelayFromParent := bombDelay.Uint64() - 1 + return func(time uint64, parent *types.Header) *big.Int { + /* + https://github.com/ethereum/EIPs/issues/100 + pDiff = parent.difficulty + BLOCK_DIFF_FACTOR = 9 + a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor + b = min(parent.difficulty, MIN_DIFF) + child_diff = max(a,b ) + */ + x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9 + c := uint64(1) // if parent.unclehash == emptyUncleHashHash + if parent.UncleHash != types.EmptyUncleHash { + c = 2 + } + xNeg := x >= c + if xNeg { + // x is now _negative_ adjustment factor + x = x - c // - ( (t-p)/p -( 2 or 1) ) + } else { + x = c - x // (2 or 1) - (t-p)/9 + } + if x > 99 { + x = 99 // max(x, 99) + } + // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) + y := new(uint256.Int) + y.SetFromBig(parent.Difficulty) // y: p_diff + pDiff := y.Clone() // pdiff: p_diff + z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative) + y.Rsh(y, difficultyBoundDivisor) // y: p__diff / 2048 + z.Mul(y, z) // z: (p_diff / 2048 ) * (+- adj_factor) + + if xNeg { + y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor + } else { + y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor + } + // minimum difficulty can ever be (before exponential factor) + if y.LtUint64(minimumDifficulty) { + y.SetUint64(minimumDifficulty) + } + // calculate a fake block number for the ice-age delay + // Specification: https://eips.ethereum.org/EIPS/eip-1234 + var pNum = parent.Number.Uint64() + if pNum >= bombDelayFromParent { + if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { + z.SetOne() + z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) + y.Add(z, y) + } + } + return y.ToBig() + } +} diff --git a/consensus/ethashb3/ethash.go b/consensus/ethashb3/ethash.go new file mode 100644 index 0000000000..e3f1eaf786 --- /dev/null +++ b/consensus/ethashb3/ethash.go @@ -0,0 +1,854 @@ +// 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 ethashb3 implements the ethashb3 proof-of-work consensus engine. +package ethashb3 + +import ( + "encoding/binary" + "errors" + "fmt" + "math" + "math/big" + "math/rand" + "os" + "path/filepath" + "reflect" + "runtime" + "strconv" + "sync" + "sync/atomic" + "time" + "unsafe" + + "github.com/edsrzf/mmap-go" + "github.com/ethereum/go-ethereum/common/hexutil" + lrupkg "github.com/ethereum/go-ethereum/common/lru" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/rpc" +) + +var ErrInvalidDumpMagic = errors.New("invalid dump magic") + +var ( + // two256 is a big integer representing 2^256 + two256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) + + // sharedEthash is a full instance that can be shared between multiple users. + sharedEthash *EthashB3 + + // algorithmRevision is the data structure version used for file naming. + algorithmRevision = 23 + + // dumpMagic is a dataset dump header to sanity check a data dump. + dumpMagic = []uint32{0xbaddcafe, 0xfee1dead} +) + +func init() { + sharedConfig := Config{ + PowMode: ModeNormal, + CachesInMem: 3, + DatasetsInMem: 1, + } + sharedEthash = New(sharedConfig, nil, false) +} + +// isLittleEndian returns whether the local system is running in little or big +// endian byte order. +func isLittleEndian() bool { + n := uint32(0x01020304) + return *(*byte)(unsafe.Pointer(&n)) == 0x04 +} + +// uint32Array2ByteArray returns the bytes represented by uint32 array c +// nolint:unused +func uint32Array2ByteArray(c []uint32) []byte { + buf := make([]byte, len(c)*4) + if isLittleEndian() { + for i, v := range c { + binary.LittleEndian.PutUint32(buf[i*4:], v) + } + } else { + for i, v := range c { + binary.BigEndian.PutUint32(buf[i*4:], v) + } + } + return buf +} + +// bytes2Keccak256 returns the keccak256 hash as a hex string (0x prefixed) +// for a given uint32 array (cache/dataset) +// nolint:unused +func uint32Array2Keccak256(data []uint32) string { + // convert to bytes + bytes := uint32Array2ByteArray(data) + // hash with keccak256 + digest := crypto.Keccak256(bytes) + // return hex string + return hexutil.Encode(digest) +} + +// memoryMap tries to memory map a file of uint32s for read only access. +func memoryMap(path string, lock bool) (*os.File, mmap.MMap, []uint32, error) { + file, err := os.OpenFile(path, os.O_RDONLY, 0644) + if err != nil { + return nil, nil, nil, err + } + mem, buffer, err := memoryMapFile(file, false) + if err != nil { + file.Close() + return nil, nil, nil, err + } + for i, magic := range dumpMagic { + if buffer[i] != magic { + mem.Unmap() + file.Close() + return nil, nil, nil, ErrInvalidDumpMagic + } + } + if lock { + if err := mem.Lock(); err != nil { + mem.Unmap() + file.Close() + return nil, nil, nil, err + } + } + return file, mem, buffer[len(dumpMagic):], err +} + +// memoryMapFile tries to memory map an already opened file descriptor. +func memoryMapFile(file *os.File, write bool) (mmap.MMap, []uint32, error) { + // Try to memory map the file + flag := mmap.RDONLY + if write { + flag = mmap.RDWR + } + mem, err := mmap.Map(file, flag, 0) + if err != nil { + return nil, nil, err + } + // The file is now memory-mapped. Create a []uint32 view of the file. + var view []uint32 + header := (*reflect.SliceHeader)(unsafe.Pointer(&view)) + header.Data = (*reflect.SliceHeader)(unsafe.Pointer(&mem)).Data + header.Cap = len(mem) / 4 + header.Len = header.Cap + return mem, view, nil +} + +// memoryMapAndGenerate tries to memory map a temporary file of uint32s for write +// access, fill it with the data from a generator and then move it into the final +// path requested. +func memoryMapAndGenerate(path string, size uint64, lock bool, generator func(buffer []uint32)) (*os.File, mmap.MMap, []uint32, error) { + // Ensure the data folder exists + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return nil, nil, nil, err + } + // Create a huge temporary empty file to fill with data + temp := path + "." + strconv.Itoa(rand.Int()) + + dump, err := os.Create(temp) + if err != nil { + return nil, nil, nil, err + } + if err = ensureSize(dump, int64(len(dumpMagic))*4+int64(size)); err != nil { + dump.Close() + os.Remove(temp) + return nil, nil, nil, err + } + // Memory map the file for writing and fill it with the generator + mem, buffer, err := memoryMapFile(dump, true) + if err != nil { + dump.Close() + os.Remove(temp) + return nil, nil, nil, err + } + copy(buffer, dumpMagic) + + data := buffer[len(dumpMagic):] + generator(data) + + if err := mem.Unmap(); err != nil { + return nil, nil, nil, err + } + if err := dump.Close(); err != nil { + return nil, nil, nil, err + } + if err := os.Rename(temp, path); err != nil { + return nil, nil, nil, err + } + return memoryMap(path, lock) +} + +type cacheOrDataset interface { + *cache | *dataset +} + +// lru tracks caches or datasets by their last use time, keeping at most N of them. +type lru[T cacheOrDataset] struct { + what string + new func(epoch uint64, epochLength uint64) T + mu sync.Mutex + // Items are kept in a LRU cache, but there is a special case: + // We always keep an item for (highest seen epoch) + 1 as the 'future item'. + cache lrupkg.BasicLRU[uint64, T] + future uint64 + futureItem T +} + +// newlru create a new least-recently-used cache for either the verification caches +// or the mining datasets. +func newlru[T cacheOrDataset](maxItems int, new func(epoch uint64, epochLength uint64) T) *lru[T] { + var what string + switch any(T(nil)).(type) { + case *cache: + what = "cache" + case *dataset: + what = "dataset" + default: + panic("unknown type") + } + return &lru[T]{ + what: what, + new: new, + cache: lrupkg.NewBasicLRU[uint64, T](maxItems), + } +} + +// get retrieves or creates an item for the given epoch. The first return value is always +// non-nil. The second return value is non-nil if lru thinks that an item will be useful in +// the near future. +func (lru *lru[T]) get(epoch uint64, epochLength uint64, ecip1099FBlock *uint64) (item, future T) { + lru.mu.Lock() + defer lru.mu.Unlock() + + // Use the sum of epoch and epochLength as the cache key. + // This is not perfectly safe, but it's good enough (at least for the first 30000 epochs, or the first 427 years). + cacheKey := epochLength + epoch + + // Get or create the item for the requested epoch. + item, ok := lru.cache.Get(cacheKey) + if !ok { + if lru.future > 0 && lru.future == epoch { + item = lru.futureItem + } else { + log.Trace("Requiring new ethashb3 "+lru.what, "epoch", epoch) + item = lru.new(epoch, epochLength) + } + lru.cache.Add(cacheKey, item) + } + + // Ensure pre-generation handles ecip-1099 changeover correctly + var nextEpoch = epoch + 1 + var nextEpochLength = epochLength + if ecip1099FBlock != nil { + nextEpochBlock := nextEpoch * epochLength + // Note that == demands that the ECIP1099 activation block is situated + // at the beginning of an epoch. + // https://github.com/ethereumclassic/ECIPs/blob/master/_specs/ecip-1099.md#implementation + if nextEpochBlock == *ecip1099FBlock && epochLength == epochLengthDefault { + nextEpoch = nextEpoch / 2 + nextEpochLength = epochLengthECIP1099 + } + } + + // Update the 'future item' if epoch is larger than previously seen. + // Last conditional clause ('lru.future > nextEpoch') handles the ECIP1099 case where + // the next epoch is expected to be LESSER THAN that of the previous state's future epoch number. + if epoch < maxEpoch-1 && lru.future != nextEpoch { + log.Trace("Requiring new future ethashb3 "+lru.what, "epoch", nextEpoch) + future = lru.new(nextEpoch, nextEpochLength) + lru.future = nextEpoch + lru.futureItem = future + } + return item, future +} + +// cache wraps an ethash cache with some metadata to allow easier concurrent use. +type cache struct { + epoch uint64 // Epoch for which this cache is relevant + epochLength uint64 // Epoch length (ECIP-1099) + dump *os.File // File descriptor of the memory mapped cache + mmap mmap.MMap // Memory map itself to unmap before releasing + cache []uint32 // The actual cache data content (may be memory mapped) + once sync.Once // Ensures the cache is generated only once +} + +// newCache creates a new ethash verification cache. +func newCache(epoch uint64, epochLength uint64) *cache { + return &cache{epoch: epoch, epochLength: epochLength} +} + +// generate ensures that the cache content is generated before use. +func (c *cache) generate(dir string, limit int, lock bool, test bool) { + c.once.Do(func() { + size := cacheSize(c.epoch) + seed := seedHash(c.epoch, c.epochLength) + if test { + size = 1024 + } + // If we don't store anything on disk, generate and return. + if dir == "" { + c.cache = make([]uint32, size/4) + generateCache(c.cache, c.epoch, c.epochLength, seed) + return + } + // Disk storage is needed, this will get fancy + var endian string + if !isLittleEndian() { + endian = ".be" + } + // The file path naming scheme was changed to include epoch values in the filename, + // which enables a filepath glob with scan to identify out-of-bounds caches and remove them. + // The legacy path declaration is provided below as a comment for reference. + // + // path := filepath.Join(dir, fmt.Sprintf("cache-R%d-%x%s", algorithmRevision, seed[:8], endian)) // LEGACY + path := filepath.Join(dir, fmt.Sprintf("cache-R%d-%d-%x%s", algorithmRevision, c.epoch, seed[:8], endian)) // CURRENT + logger := log.New("epoch", c.epoch, "epochLength", c.epochLength) + + // We're about to mmap the file, ensure that the mapping is cleaned up when the + // cache becomes unused. + runtime.SetFinalizer(c, (*cache).finalizer) + + // Try to load the file from disk and memory map it + var err error + c.dump, c.mmap, c.cache, err = memoryMap(path, lock) + if err == nil { + logger.Debug("Loaded old ethashb3 cache from disk") + return + } + logger.Debug("Failed to load old ethashb3 cache", "err", err) + + // No usable previous cache available, create a new cache file to fill + c.dump, c.mmap, c.cache, err = memoryMapAndGenerate(path, size, lock, func(buffer []uint32) { generateCache(buffer, c.epoch, c.epochLength, seed) }) + if err != nil { + logger.Error("Failed to generate mapped ethashb3 cache", "err", err) + + c.cache = make([]uint32, size/4) + generateCache(c.cache, c.epoch, c.epochLength, seed) + } + + // Iterate over all cache file instances, deleting any out of bounds (where epoch is below lower limit, or above upper limit). + matches, _ := filepath.Glob(filepath.Join(dir, fmt.Sprintf("cache-R%d*", algorithmRevision))) + for _, file := range matches { + var ar int // algorithm revision + var e uint64 // epoch + var s string // seed + if _, err := fmt.Sscanf(filepath.Base(file), "cache-R%d-%d-%s"+endian, &ar, &e, &s); err != nil { + // There is an unrecognized file in this directory. + // See if the name matches the expected pattern of the legacy naming scheme. + if _, err := fmt.Sscanf(filepath.Base(file), "cache-R%d-%s"+endian, &ar, &s); err == nil { + // This file matches the previous generation naming pattern (sans epoch). + if err := os.Remove(file); err != nil { + logger.Error("Failed to remove legacy ethashb3 cache file", "file", file, "err", err) + } else { + logger.Warn("Deleted legacy ethashb3 cache file", "path", file) + } + } + // Else the file is unrecognized (unknown name format), leave it alone. + continue + } + if e <= c.epoch-uint64(limit) || e > c.epoch+1 { + if err := os.Remove(file); err == nil { + logger.Debug("Deleted ethashb3 cache file", "target.epoch", e, "file", file) + } else { + logger.Error("Failed to delete ethashb3 cache file", "target.epoch", e, "file", file, "err", err) + } + } + } + }) +} + +// finalizer unmaps the memory and closes the file. +func (c *cache) finalizer() { + if c.mmap != nil { + c.mmap.Unmap() + c.dump.Close() + c.mmap, c.dump = nil, nil + } +} + +// dataset wraps an ethash dataset with some metadata to allow easier concurrent use. +type dataset struct { + epoch uint64 // Epoch for which this cache is relevant + epochLength uint64 // Epoch length (ECIP-1099) + dump *os.File // File descriptor of the memory mapped cache + mmap mmap.MMap // Memory map itself to unmap before releasing + dataset []uint32 // The actual cache data content + once sync.Once // Ensures the cache is generated only once + done atomic.Bool // Atomic flag to determine generation status +} + +// newDataset creates a new ethash mining dataset and returns it as a plain Go +// interface to be usable in an LRU cache. +func newDataset(epoch uint64, epochLength uint64) *dataset { + return &dataset{epoch: epoch, epochLength: epochLength} +} + +// generate ensures that the dataset content is generated before use. +func (d *dataset) generate(dir string, limit int, lock bool, test bool) { + d.once.Do(func() { + // Mark the dataset generated after we're done. This is needed for remote + defer d.done.Store(true) + + csize := cacheSize(d.epoch) + dsize := datasetSize(d.epoch) + seed := seedHash(d.epoch, d.epochLength) + if test { + csize = 1024 + dsize = 32 * 1024 + } + // If we don't store anything on disk, generate and return + if dir == "" { + cache := make([]uint32, csize/4) + generateCache(cache, d.epoch, d.epochLength, seed) + + d.dataset = make([]uint32, dsize/4) + generateDataset(d.dataset, d.epoch, d.epochLength, cache) + + return + } + // Disk storage is needed, this will get fancy + var endian string + if !isLittleEndian() { + endian = ".be" + } + path := filepath.Join(dir, fmt.Sprintf("full-R%d-%d-%x%s", algorithmRevision, d.epoch, seed[:8], endian)) + logger := log.New("epoch", d.epoch) + + // We're about to mmap the file, ensure that the mapping is cleaned up when the + // cache becomes unused. + runtime.SetFinalizer(d, (*dataset).finalizer) + + // Try to load the file from disk and memory map it + var err error + d.dump, d.mmap, d.dataset, err = memoryMap(path, lock) + if err == nil { + logger.Debug("Loaded old ethashb3 dataset from disk", "path", path) + return + } + logger.Debug("Failed to load old ethashb3 dataset", "err", err) + + // No usable previous dataset available, create a new dataset file to fill + cache := make([]uint32, csize/4) + generateCache(cache, d.epoch, d.epochLength, seed) + + d.dump, d.mmap, d.dataset, err = memoryMapAndGenerate(path, dsize, lock, func(buffer []uint32) { generateDataset(buffer, d.epoch, d.epochLength, cache) }) + if err != nil { + logger.Error("Failed to generate mapped ethashb3 dataset", "err", err) + + d.dataset = make([]uint32, dsize/4) + generateDataset(d.dataset, d.epoch, d.epochLength, cache) + } + + // Iterate over all full file instances, deleting any out of bounds (where epoch is below lower limit, or above upper limit). + matches, _ := filepath.Glob(filepath.Join(dir, fmt.Sprintf("full-R%d*", algorithmRevision))) + for _, file := range matches { + var ar int // algorithm revision + var e uint64 // epoch + var s string // seed + if _, err := fmt.Sscanf(filepath.Base(file), "full-R%d-%d-%s"+endian, &ar, &e, &s); err != nil { + // There is an unrecognized file in this directory. + // See if the name matches the expected pattern of the legacy naming scheme. + if _, err := fmt.Sscanf(filepath.Base(file), "full-R%d-%s"+endian, &ar, &s); err == nil { + // This file matches the previous generation naming pattern (sans epoch). + if err := os.Remove(file); err != nil { + logger.Error("Failed to remove legacy ethash full file", "file", file, "err", err) + } else { + logger.Warn("Deleted legacy ethashb3 full file", "path", file) + } + } + // Else the file is unrecognized (unknown name format), leave it alone. + continue + } + if e <= d.epoch-uint64(limit) || e > d.epoch+1 { + if err := os.Remove(file); err == nil { + logger.Debug("Deleted ethashb3 full file", "target.epoch", e, "file", file) + } else { + logger.Error("Failed to delete ethash full file", "target.epoch", e, "file", file, "err", err) + } + } + } + }) +} + +// generated returns whether this particular dataset finished generating already +// or not (it may not have been started at all). This is useful for remote miners +// to default to verification caches instead of blocking on DAG generations. +func (d *dataset) generated() bool { + return d.done.Load() +} + +// finalizer closes any file handlers and memory maps open. +func (d *dataset) finalizer() { + if d.mmap != nil { + d.mmap.Unmap() + d.dump.Close() + d.mmap, d.dump = nil, nil + } +} + +// MakeCache generates a new ethash cache and optionally stores it to disk. +func MakeCache(block uint64, epochLength uint64, dir string) { + epoch := calcEpoch(block, epochLength) + c := cache{epoch: epoch, epochLength: epochLength} + c.generate(dir, math.MaxInt32, false, false) +} + +// MakeDataset generates a new ethash dataset and optionally stores it to disk. +func MakeDataset(block uint64, epochLength uint64, dir string) { + epoch := calcEpoch(block, epochLength) + d := dataset{epoch: epoch, epochLength: epochLength} + d.generate(dir, math.MaxInt32, false, false) +} + +// Mode defines the type and amount of PoW verification an ethash engine makes. +type Mode uint + +const ( + ModeNormal Mode = iota + ModeShared + ModeTest + ModeFake + ModePoissonFake + ModeFullFake +) + +func (m Mode) String() string { + switch m { + case ModeNormal: + return "Normal" + case ModeShared: + return "Shared" + case ModeTest: + return "Test" + case ModeFake: + return "Fake" + case ModePoissonFake: + return "PoissonFake" + case ModeFullFake: + return "FullFake" + } + return "unknown" +} + +// Config are the configuration parameters of the ethash. +type Config struct { + CacheDir string + CachesInMem int + CachesOnDisk int + CachesLockMmap bool + DatasetDir string + DatasetsInMem int + DatasetsOnDisk int + DatasetsLockMmap bool + 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:"-"` + // ECIP-1099 + ECIP1099Block *uint64 `toml:"-"` +} + +// EthashB3 is a consensus engine based on proof-of-work implementing the ethash +// algorithm. +type EthashB3 struct { + config Config + + caches *lru[*cache] // In memory caches to avoid regenerating too often + datasets *lru[*dataset] // In memory datasets to avoid regenerating too often + + // 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 + + // The fields below are hooks for testing + shared *EthashB3 // 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. +} + +// 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) *EthashB3 { + if config.Log == nil { + config.Log = log.Root() + } + if config.CachesInMem <= 0 { + config.Log.Warn("One ethashb3 cache must always be in memory", "requested", config.CachesInMem) + config.CachesInMem = 1 + } + if config.CacheDir != "" && config.CachesOnDisk > 0 { + config.Log.Info("Disk storage enabled for ethash caches", "dir", config.CacheDir, "count", config.CachesOnDisk) + } + if config.DatasetDir != "" && config.DatasetsOnDisk > 0 { + config.Log.Info("Disk storage enabled for ethash DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk) + } + ethash := &EthashB3{ + config: config, + caches: newlru(config.CachesInMem, newCache), + datasets: newlru(config.DatasetsInMem, newDataset), + update: make(chan struct{}), + hashrate: metrics.NewMeterForced(), + } + if config.PowMode == ModeShared { + ethash.shared = sharedEthash + } + ethash.remote = startRemoteSealer(ethash, notify, noverify) + return ethash +} + +// NewTester creates a small sized ethash PoW scheme useful only for testing +// purposes. +func NewTester(notify []string, noverify bool) *EthashB3 { + return New(Config{PowMode: ModeTest}, notify, noverify) +} + +// 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() *EthashB3 { + return &EthashB3{ + 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) *EthashB3 { + return &EthashB3{ + 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) *EthashB3 { + return &EthashB3{ + config: Config{ + PowMode: ModeFake, + Log: log.Root(), + }, + fakeDelay: delay, + } +} + +// NewPoissonFaker creates a ethash consensus engine with a fake PoW scheme that +// accepts all blocks as valid, but delays mining by some time based on miner.threads, though +// they still have to conform to the Ethereum consensus rules. +func NewPoissonFaker() *EthashB3 { + return &EthashB3{ + config: Config{ + PowMode: ModePoissonFake, + Log: log.Root(), + }, + } +} + +// 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() *EthashB3 { + return &EthashB3{ + 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() *EthashB3 { + return &EthashB3{shared: sharedEthash} +} + +// Close closes the exit channel to notify all backend threads exiting. +func (ethash *EthashB3) Close() error { + return ethash.StopRemoteSealer() +} + +// StopRemoteSealer stops the remote sealer +func (ethash *EthashB3) StopRemoteSealer() error { + ethash.closeOnce.Do(func() { + // Short circuit if the exit channel is not allocated. + if ethash.remote == nil { + return + } + close(ethash.remote.requestExit) + <-ethash.remote.exitCh + }) + return nil +} + +// cache tries to retrieve a verification cache for the specified block number +// by first checking against a list of in-memory caches, then against caches +// stored on disk, and finally generating one if none can be found. +func (ethash *EthashB3) cache(block uint64) *cache { + epochLength := calcEpochLength(block, ethash.config.ECIP1099Block) + epoch := calcEpoch(block, epochLength) + current, future := ethash.caches.get(epoch, epochLength, ethash.config.ECIP1099Block) + + // Wait for generation finish. + current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest) + + // If we need a new future cache, now's a good time to regenerate it. + if future != nil { + go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest) + } + return current +} + +// dataset tries to retrieve a mining dataset for the specified block number +// by first checking against a list of in-memory datasets, then against DAGs +// stored on disk, and finally generating one if none can be found. +// +// If async is specified, not only the future but the current DAG is also +// generates on a background thread. +func (ethash *EthashB3) dataset(block uint64, async bool) *dataset { + // Retrieve the requested ethash dataset + epochLength := calcEpochLength(block, ethash.config.ECIP1099Block) + epoch := calcEpoch(block, epochLength) + current, future := ethash.datasets.get(epoch, epochLength, ethash.config.ECIP1099Block) + + // set async false if ecip-1099 transition in case of regeneratiion bad DAG on disk + if epochLength == epochLengthECIP1099 && (epoch == 42 || epoch == 195) { + async = false + } + + // If async is specified, generate everything in a background thread + if async && !current.generated() { + go func() { + current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + if future != nil { + future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + } + }() + } else { + // Either blocking generation was requested, or already done + current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + if future != nil { + go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + } + } + return current +} + +// Threads returns the number of mining threads currently enabled. This doesn't +// necessarily mean that mining is running! +func (ethash *EthashB3) Threads() int { + ethash.lock.Lock() + defer ethash.lock.Unlock() + + return ethash.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 (ethash *EthashB3) SetThreads(threads int) { + ethash.lock.Lock() + defer ethash.lock.Unlock() + + // If we're running a shared PoW, set the thread count on that instead + if ethash.shared != nil { + ethash.shared.SetThreads(threads) + return + } + // Update the threads and ping any running seal to pull in any changes + ethash.threads = threads + select { + case ethash.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 (ethash *EthashB3) Hashrate() float64 { + // Short circuit if we are run the ethash in normal/test mode. + if ethash.config.PowMode != ModeNormal && ethash.config.PowMode != ModeTest { + return ethash.hashrate.Rate1() + } + var res = make(chan uint64, 1) + + select { + case ethash.remote.fetchRateCh <- res: + case <-ethash.remote.exitCh: + // Return local hashrate only if ethash is stopped. + return ethash.hashrate.Rate1() + } + + // Gather total submitted hash rate of remote sealers. + return ethash.hashrate.Rate1() + float64(<-res) +} + +// APIs implements consensus.Engine, returning the user facing RPC APIs. +func (ethash *EthashB3) APIs(chain consensus.ChainHeaderReader) []rpc.API { + // In order to ensure backward compatibility, we exposes ethash RPC APIs + // to both eth and ethash namespaces. + return []rpc.API{ + { + Namespace: "eth", + Service: &API{ethash}, + }, + { + Namespace: "ethashb3", + Service: &API{ethash}, + }, + } +} + +// SeedHash is the seed to use for generating a verification cache and the mining +// dataset. +func SeedHash(epoch uint64, epochLength uint64) []byte { + return seedHash(epoch, epochLength) +} + +// CalcEpochLength returns the epoch length for a given block number (ECIP-1099) +func CalcEpochLength(block uint64, ecip1099FBlock *uint64) uint64 { + return calcEpochLength(block, ecip1099FBlock) +} + +// CalcEpoch returns the epoch for a given block number (ECIP-1099) +func CalcEpoch(block uint64, epochLength uint64) uint64 { + return calcEpoch(block, epochLength) +} diff --git a/consensus/ethashb3/mmap_help_linux.go b/consensus/ethashb3/mmap_help_linux.go new file mode 100644 index 0000000000..b3763355a7 --- /dev/null +++ b/consensus/ethashb3/mmap_help_linux.go @@ -0,0 +1,35 @@ +// Copyright 2021 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 . + +//go:build linux +// +build linux + +package ethashb3 + +import ( + "os" + + "golang.org/x/sys/unix" +) + +// ensureSize expands the file to the given size. This is to prevent runtime +// errors later on, if the underlying file expands beyond the disk capacity, +// even though it ostensibly is already expanded, but due to being sparse +// does not actually occupy the full declared size on disk. +func ensureSize(f *os.File, size int64) error { + // Docs: https://www.man7.org/linux/man-pages/man2/fallocate.2.html + return unix.Fallocate(int(f.Fd()), 0, 0, size) +} diff --git a/consensus/ethashb3/mmap_help_other.go b/consensus/ethashb3/mmap_help_other.go new file mode 100644 index 0000000000..d499cd85fc --- /dev/null +++ b/consensus/ethashb3/mmap_help_other.go @@ -0,0 +1,36 @@ +// Copyright 2021 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 . + +//go:build !linux +// +build !linux + +package ethashb3 + +import ( + "os" +) + +// ensureSize expands the file to the given size. This is to prevent runtime +// errors later on, if the underlying file expands beyond the disk capacity, +// even though it ostensibly is already expanded, but due to being sparse +// does not actually occupy the full declared size on disk. +func ensureSize(f *os.File, size int64) error { + // On systems which do not support fallocate, we merely truncate it. + // More robust alternatives would be to + // - Use posix_fallocate, or + // - explicitly fill the file with zeroes. + return f.Truncate(size) +} diff --git a/consensus/ethashb3/sealer.go b/consensus/ethashb3/sealer.go new file mode 100644 index 0000000000..3847f5ef8a --- /dev/null +++ b/consensus/ethashb3/sealer.go @@ -0,0 +1,499 @@ +// 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 ethashb3 + +import ( + "bytes" + "context" + crand "crypto/rand" + "encoding/json" + "errors" + "math" + "math/big" + "math/rand" + "net/http" + "runtime" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/types" + exprand "golang.org/x/exp/rand" + "gonum.org/v1/gonum/stat/distuv" +) + +const ( + // staleThreshold is the maximum depth of the acceptable stale but valid ethash solution. + staleThreshold = 7 +) + +var ( + errNoMiningWork = errors.New("no mining work available yet") + errInvalidSealResult = errors.New("invalid or stale proof-of-work solution") +) + +// makePoissonFakeDelay uses the ethash.threads value as a mean time (lambda) +// for a Poisson distribution, returning a random value from +// that discrete function. I think a Poisson distribution probably +// fairly accurately models real world block times. +// Note that this is a hacky way to use ethash.threads since +// lower values will yield faster blocks, but it saves having +// to add or modify any more code than necessary. +func (ethash *EthashB3) makePoissonFakeDelay() float64 { + p := distuv.Poisson{ + Lambda: float64(ethash.Threads()), + Src: exprand.NewSource(uint64(time.Now().UnixNano())), + } + return p.Rand() +} + +// Seal implements consensus.Engine, attempting to find a nonce that satisfies +// the block's difficulty requirements. +func (ethash *EthashB3) 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 ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake { + header := block.Header() + header.Nonce, header.MixDigest = types.BlockNonce{}, common.Hash{} + select { + case results <- block.WithSeal(header): + default: + ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header())) + } + return nil + } else if ethash.config.PowMode == ModePoissonFake { + go func(header *types.Header) { + // Assign random (but non-zero) values to header nonce and mix. + header.Nonce = types.EncodeNonce(uint64(rand.Int63n(math.MaxInt64))) + b, _ := header.Nonce.MarshalText() + header.MixDigest = common.BytesToHash(b) + + // Wait some amount of time. + timeout := time.NewTimer(time.Duration(ethash.makePoissonFakeDelay()) * time.Second) + defer timeout.Stop() + + select { + case <-stop: + return + case <-ethash.update: + timeout.Stop() + if err := ethash.Seal(chain, block, results, stop); err != nil { + ethash.config.Log.Error("Failed to restart sealing after update", "err", err) + } + case <-timeout.C: + // Send the results when the timeout expires. + select { + case results <- block.WithSeal(header): + default: + ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header())) + } + } + }(block.Header()) + return nil + } + // If we're running a shared PoW, delegate sealing to it + if ethash.shared != nil { + return ethash.shared.Seal(chain, block, results, stop) + } + // Create a runner and the multiple search threads it directs + abort := make(chan struct{}) + + ethash.lock.Lock() + threads := ethash.threads + if ethash.rand == nil { + seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) + if err != nil { + ethash.lock.Unlock() + return err + } + ethash.rand = rand.New(rand.NewSource(seed.Int64())) + } + ethash.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 ethash.remote != nil { + ethash.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() + ethash.mine(block, id, nonce, abort, locals) + }(i, uint64(ethash.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: + ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "local", "sealhash", ethash.SealHash(block.Header())) + } + close(abort) + case <-ethash.update: + // Thread count was changed on user request, restart + close(abort) + if err := ethash.Seal(chain, block, results, stop); err != nil { + ethash.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 (ethash *EthashB3) 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 = ethash.SealHash(header).Bytes() + target = new(big.Int).Div(two256, header.Difficulty) + number = header.Number.Uint64() + dataset = ethash.dataset(number, false) + ) + // Start generating random nonces until we abort or find a good one + var ( + attempts = int64(0) + nonce = seed + powBuffer = new(big.Int) + ) + logger := ethash.config.Log.New("miner", id) + logger.Trace("Started ethash search for new nonces", "seed", seed) +search: + for { + select { + case <-abort: + // Mining terminated, update stats and abort + logger.Trace("EthashB3 nonce search aborted", "attempts", nonce-seed) + ethash.hashrate.Mark(attempts) + break search + + default: + // We don't have to update hash rate on every nonce, so update after after 2^X nonces + attempts++ + if (attempts % (1 << 15)) == 0 { + ethash.hashrate.Mark(attempts) + attempts = 0 + } + // Compute the PoW value of this nonce + digest, result := hashimotoFull(dataset.dataset, hash, nonce) + if powBuffer.SetBytes(result).Cmp(target) <= 0 { + // Correct nonce found, create a new header with it + header = types.CopyHeader(header) + header.Nonce = types.EncodeNonce(nonce) + header.MixDigest = common.BytesToHash(digest) + + // Seal and return a block (if still needed) + select { + case found <- block.WithSeal(header): + logger.Trace("EthashB3 nonce found and reported", "attempts", nonce-seed, "nonce", nonce) + case <-abort: + logger.Trace("EthashB3 nonce found but discarded", "attempts", nonce-seed, "nonce", nonce) + } + break search + } + nonce++ + } + } + // Datasets are unmapped in a finalizer. Ensure that the dataset stays live + // during sealing so it's not unmapped while being read. + runtime.KeepAlive(dataset) +} + +// 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 + + ethash *EthashB3 + 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(ethash *EthashB3, urls []string, noverify bool) *remoteSealer { + ctx, cancel := context.WithCancel(context.Background()) + s := &remoteSealer{ + ethash: ethash, + 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.ethash.config.Log.Trace("EthashB3 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.ethash.SealHash(block.Header()) + epochLength := calcEpochLength(block.NumberU64(), s.ethash.config.ECIP1099Block) + epoch := calcEpoch(block.NumberU64(), epochLength) + s.currentWork[0] = hash.Hex() + s.currentWork[1] = common.BytesToHash(SeedHash(epoch, epochLength)).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.ethash.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(http.MethodPost, url, bytes.NewReader(json)) + if err != nil { + s.ethash.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.ethash.config.Log.Warn("Failed to notify remote miner", "err", err) + } else { + s.ethash.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.ethash.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.ethash.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.ethash.verifySeal(nil, header, true); err != nil { + s.ethash.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.ethash.config.Log.Warn("EthashB3 result channel is empty, submitted mining result is rejected") + return false + } + s.ethash.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.ethash.config.Log.Debug("Work submitted is acceptable", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) + return true + default: + s.ethash.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.ethash.config.Log.Warn("Work submitted is too old", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) + return false +} diff --git a/go.mod b/go.mod index c1d04d8aa9..43fd0404c7 100644 --- a/go.mod +++ b/go.mod @@ -86,6 +86,7 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/urfave/cli.v1 v1.20.0 gopkg.in/yaml.v3 v3.0.1 + lukechampine.com/blake3 v1.2.1 ) require ( @@ -135,6 +136,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect diff --git a/go.sum b/go.sum index ff453b35b5..9b2970cab4 100644 --- a/go.sum +++ b/go.sum @@ -353,6 +353,8 @@ github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -785,6 +787,8 @@ gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= +lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/params/config_hypra.go b/params/config_hypra.go new file mode 100644 index 0000000000..a54848b29f --- /dev/null +++ b/params/config_hypra.go @@ -0,0 +1,110 @@ +// Copyright 2019 The multi-geth Authors +// This file is part of the multi-geth library. +// +// The multi-geth 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 multi-geth 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 multi-geth library. If not, see . +package params + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params/types/coregeth" + "github.com/ethereum/go-ethereum/params/types/ctypes" + "github.com/ethereum/go-ethereum/params/vars" +) + +var ( + // HypraChainConfig is the chain parameters to run a node on the Classic main network. + HypraChainConfig = &coregeth.CoreGethChainConfig{ + NetworkID: 622277, + EthashB3: new(ctypes.EthashB3Config), + ChainID: big.NewInt(622277), + SupportedProtocolVersions: vars.DefaultProtocolVersions, + + EIP2FBlock: big.NewInt(0), + EIP7FBlock: big.NewInt(0), + + // DAOForkBlock: big.NewInt(1920000), + + EIP150Block: big.NewInt(0), + + EIP155Block: big.NewInt(0), + EIP160FBlock: big.NewInt(0), + ECIP1010PauseBlock: big.NewInt(0), + ECIP1010Length: big.NewInt(0), + + ECIP1017FBlock: big.NewInt(0), + ECIP1017EraRounds: big.NewInt(0), + + DisposalBlock: big.NewInt(0), + + // EIP158~ + EIP161FBlock: big.NewInt(0), + EIP170FBlock: big.NewInt(0), + + // Byzantium eq + EIP100FBlock: big.NewInt(1001), + EIP140FBlock: big.NewInt(1001), + EIP198FBlock: big.NewInt(1001), + EIP211FBlock: big.NewInt(1001), + EIP212FBlock: big.NewInt(1001), + EIP213FBlock: big.NewInt(1001), + EIP214FBlock: big.NewInt(1001), + EIP658FBlock: big.NewInt(1001), + + // Constantinople eq, aka Agharta + EIP145FBlock: big.NewInt(5503), + EIP1014FBlock: big.NewInt(5503), + EIP1052FBlock: big.NewInt(5503), + EIP1283FBlock: big.NewInt(5503), + PetersburgBlock: big.NewInt(5507), + + // Istanbul eq, aka Phoenix + // ECIP-1088 + EIP152FBlock: big.NewInt(5519), + EIP1108FBlock: big.NewInt(5519), + EIP1344FBlock: big.NewInt(5519), + EIP1884FBlock: big.NewInt(5519), + EIP2028FBlock: big.NewInt(5519), + EIP2200FBlock: big.NewInt(5519), // RePetersburg (=~ re-1283) + + // Hypra does not use ETC Improvements + // ECBP1100FBlock: big.NewInt(11_380_000), // ETA 09 Oct 2020 + // ECBP1100DeactivateFBlock: big.NewInt(19_250_000), // ETA 31 Jan 2023 (== Spiral hard fork) + // ECIP1099FBlock: big.NewInt(11_700_000), // Etchash (DAG size limit) + + // Berlin eq, aka Magneto + EIP2565FBlock: big.NewInt(5527), + EIP2718FBlock: big.NewInt(5527), + EIP2929FBlock: big.NewInt(5527), + EIP2930FBlock: big.NewInt(5527), + + // London (partially), aka Mystique + EIP3529FBlock: big.NewInt(14_525_000), + EIP3541FBlock: big.NewInt(14_525_000), + + // Spiral, aka Shanghai (partially) + // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. ETC does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. + EIP3651FBlock: big.NewInt(19_250_000), // Warm COINBASE (gas reprice) + EIP3855FBlock: big.NewInt(19_250_000), // PUSH0 instruction + EIP3860FBlock: big.NewInt(19_250_000), // Limit and meter initcode + // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + EIP6049FBlock: big.NewInt(19_250_000), // Deprecate SELFDESTRUCT (noop) + + RequireBlockHashes: map[uint64]common.Hash{ + 1920000: common.HexToHash("0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f"), + 2500000: common.HexToHash("0xca12c63534f565899681965528d536c52cb05b7c48e269c2a6cb77ad864d878a"), + }, + } +) diff --git a/params/genesis_hypra.go b/params/genesis_hypra.go new file mode 100644 index 0000000000..c448dd27e5 --- /dev/null +++ b/params/genesis_hypra.go @@ -0,0 +1,40 @@ +// Copyright 2019 The multi-geth Authors +// This file is part of the multi-geth library. +// +// The multi-geth 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 multi-geth 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 multi-geth library. If not, see . + +package params + +import ( + "github.com/ethereum/go-ethereum/common" + "math/big" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/params/types/genesisT" +) + +var HypraGenesisHash = common.HexToHash("0x0fb784d1481f0aa911d21d639641763ca09641413842b35f1d10eb5d208abdf8") + +// ClassicGenesisBlock returns the Ethereum Classic genesis block. +func DefaultHypraGenesisBlock() *genesisT.Genesis { + return &genesisT.Genesis{ + Config: HypraChainConfig, + Nonce: 4009, + ExtraData: hexutil.MustDecode("0x5465736c6120656e746572732074686520656c65637472696320747275636b20626174746c65206166746572206669727374204379626572747275636b20726f6c6c73206f6666207468652070726f64756374696f6e206c696e65"), + GasLimit: 50000, + Difficulty: big.NewInt(9_035_329), + Alloc: genesisT.DecodePreAlloc(HypraAllocData), + Timestamp: 1689703500, + } +} diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index 7db8b8525e..e1bd3bb106 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -244,10 +244,11 @@ type CoreGethChainConfig struct { DisposalBlock *big.Int `json:"disposalBlock,omitempty"` // Bomb disposal HF block // Various consensus engines - Ethash *ctypes.EthashConfig `json:"ethash,omitempty"` - Clique *ctypes.CliqueConfig `json:"clique,omitempty"` - Lyra2 *ctypes.Lyra2Config `json:"lyra2,omitempty"` - IsDevMode bool `json:"isDev,omitempty"` + Ethash *ctypes.EthashConfig `json:"ethash,omitempty"` + EthashB3 *ctypes.EthashB3Config `json:"ethashb3,omitempty"` + Clique *ctypes.CliqueConfig `json:"clique,omitempty"` + Lyra2 *ctypes.Lyra2Config `json:"lyra2,omitempty"` + IsDevMode bool `json:"isDev,omitempty"` // TerminalTotalDifficulty is the amount of total difficulty reached by // the network that triggers the consensus upgrade. @@ -275,6 +276,8 @@ func (c *CoreGethChainConfig) String() string { switch { case c.Ethash != nil: engine = c.Ethash + case c.EthashB3 != nil: + engine = c.EthashB3 case c.Clique != nil: engine = c.Clique case c.Lyra2 != nil: diff --git a/params/types/ctypes/types.go b/params/types/ctypes/types.go index 0c133281ea..a63c21ae01 100644 --- a/params/types/ctypes/types.go +++ b/params/types/ctypes/types.go @@ -273,12 +273,15 @@ const ( ConsensusEngineT_Ethash ConsensusEngineT_Clique ConsensusEngineT_Lyra2 + ConsensusEngineT_EthashB3 ) func (c ConsensusEngineT) String() string { switch c { case ConsensusEngineT_Ethash: return "ethash" + case ConsensusEngineT_EthashB3: + return "ethashb3" case ConsensusEngineT_Clique: return "clique" case ConsensusEngineT_Lyra2: @@ -292,6 +295,10 @@ func (c ConsensusEngineT) IsEthash() bool { return c == ConsensusEngineT_Ethash } +func (c ConsensusEngineT) IsEthashB3() bool { + return c == ConsensusEngineT_EthashB3 +} + func (c ConsensusEngineT) IsClique() bool { return c == ConsensusEngineT_Clique } @@ -388,3 +395,11 @@ type Lyra2Config struct{} func (c *Lyra2Config) String() string { return "lyra2" } + +// EthashB3Config is the consensus engine configs for proof-of-work based sealing. +type EthashB3Config struct{} + +// String implements the stringer interface, returning the consensus engine details. +func (c *EthashB3Config) String() string { + return "ethashb3" +} From 824ec662dc7674e49387fa721cb43a39e6b853f1 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 20:56:16 +0000 Subject: [PATCH 02/45] params: Align Hypra mainnet blocks --- params/config_hypra.go | 65 ++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/params/config_hypra.go b/params/config_hypra.go index a54848b29f..3f6340dff1 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -25,7 +25,7 @@ import ( ) var ( - // HypraChainConfig is the chain parameters to run a node on the Classic main network. + // HypraChainConfig is the chain parameters to run a node on the Hypra main network. HypraChainConfig = &coregeth.CoreGethChainConfig{ NetworkID: 622277, EthashB3: new(ctypes.EthashB3Config), @@ -34,24 +34,19 @@ var ( EIP2FBlock: big.NewInt(0), EIP7FBlock: big.NewInt(0), - - // DAOForkBlock: big.NewInt(1920000), - - EIP150Block: big.NewInt(0), - + // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? + // DAOForkSupport isnt in this struct + // DAOForkBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP160FBlock: big.NewInt(0), ECIP1010PauseBlock: big.NewInt(0), ECIP1010Length: big.NewInt(0), - - ECIP1017FBlock: big.NewInt(0), - ECIP1017EraRounds: big.NewInt(0), - - DisposalBlock: big.NewInt(0), - - // EIP158~ - EIP161FBlock: big.NewInt(0), - EIP170FBlock: big.NewInt(0), + ECIP1017FBlock: big.NewInt(0), + ECIP1017EraRounds: big.NewInt(0), + DisposalBlock: big.NewInt(0), + EIP161FBlock: big.NewInt(0), + EIP170FBlock: big.NewInt(0), // Byzantium eq EIP100FBlock: big.NewInt(1001), @@ -63,7 +58,7 @@ var ( EIP214FBlock: big.NewInt(1001), EIP658FBlock: big.NewInt(1001), - // Constantinople eq, aka Agharta + // Constantinople eq EIP145FBlock: big.NewInt(5503), EIP1014FBlock: big.NewInt(5503), EIP1052FBlock: big.NewInt(5503), @@ -71,40 +66,36 @@ var ( PetersburgBlock: big.NewInt(5507), // Istanbul eq, aka Phoenix - // ECIP-1088 EIP152FBlock: big.NewInt(5519), EIP1108FBlock: big.NewInt(5519), EIP1344FBlock: big.NewInt(5519), EIP1884FBlock: big.NewInt(5519), EIP2028FBlock: big.NewInt(5519), - EIP2200FBlock: big.NewInt(5519), // RePetersburg (=~ re-1283) + EIP2200FBlock: big.NewInt(5519), - // Hypra does not use ETC Improvements - // ECBP1100FBlock: big.NewInt(11_380_000), // ETA 09 Oct 2020 - // ECBP1100DeactivateFBlock: big.NewInt(19_250_000), // ETA 31 Jan 2023 (== Spiral hard fork) - // ECIP1099FBlock: big.NewInt(11_700_000), // Etchash (DAG size limit) + // Berlin + EIP2565FBlock: big.NewInt(5527), // ModExp Gas Cost + EIP2718FBlock: big.NewInt(5527), // Typed Transaction Envelope + EIP2929FBlock: big.NewInt(5527), // Gas cost increases for state access opcodes + EIP2930FBlock: big.NewInt(5527), // Optional access lists - // Berlin eq, aka Magneto - EIP2565FBlock: big.NewInt(5527), - EIP2718FBlock: big.NewInt(5527), - EIP2929FBlock: big.NewInt(5527), - EIP2930FBlock: big.NewInt(5527), + // London + shanghai EVM upgrade, aka Gaspar + EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds + EIP3541FBlock: big.NewInt(1_600_957), // Reject new contract code starting with the 0xEF byte + EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction + EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode - // London (partially), aka Mystique - EIP3529FBlock: big.NewInt(14_525_000), - EIP3541FBlock: big.NewInt(14_525_000), + // EIP3651FBlock: big.NewInt(1_600_957), // Warm COINBASE (gas reprice) -- I don't think this was enabled on hypra as part of Gaspar + // EIP1559FBlock: big.NewInt(0), // EIP-1559 transactions are not enabled on Hypra yet -- TODO // Spiral, aka Shanghai (partially) - // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. ETC does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. - EIP3651FBlock: big.NewInt(19_250_000), // Warm COINBASE (gas reprice) - EIP3855FBlock: big.NewInt(19_250_000), // PUSH0 instruction - EIP3860FBlock: big.NewInt(19_250_000), // Limit and meter initcode + // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations - EIP6049FBlock: big.NewInt(19_250_000), // Deprecate SELFDESTRUCT (noop) + // EIP6049FBlock: big.NewInt(19_250_000), // Deprecate SELFDESTRUCT (noop) RequireBlockHashes: map[uint64]common.Hash{ - 1920000: common.HexToHash("0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f"), - 2500000: common.HexToHash("0xca12c63534f565899681965528d536c52cb05b7c48e269c2a6cb77ad864d878a"), + 156000: common.HexToHash("0x2a27bec023108c5f650cb0c9b7aaae7e7fdeefbeb3cd14a8390bb0957043aca2"), + 512000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), }, } ) From 009e77945b0eac3376c03b6dd1695166608367f8 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 21:09:15 +0000 Subject: [PATCH 03/45] params: Include Veldin definition for Hypra TODO: use in AccumulateRewards --- params/config_hypra.go | 4 ++++ params/types/coregeth/chain_config.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/params/config_hypra.go b/params/config_hypra.go index 3f6340dff1..6ec0dfae6d 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -79,6 +79,10 @@ var ( EIP2929FBlock: big.NewInt(5527), // Gas cost increases for state access opcodes EIP2930FBlock: big.NewInt(5527), // Optional access lists + // Veldin fork was used to enable rewards to miners for including uncle blocks. + // Previously overlooked and unrewarded. TODO: use in AccumulateRewards + HIPVeldin: big.NewInt(500_009), + // London + shanghai EVM upgrade, aka Gaspar EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds EIP3541FBlock: big.NewInt(1_600_957), // Reject new contract code starting with the 0xEF byte diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index e1bd3bb106..c147400be8 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -268,6 +268,10 @@ type CoreGethChainConfig struct { RequireBlockHashes map[uint64]common.Hash `json:"requireBlockHashes"` Lyra2NonceTransitionBlock *big.Int `json:"lyra2NonceTransitionBlock,omitempty"` + + // Veldin fork was used to enable rewards to miners for including uncle blocks. + // Previously overlooked and unrewarded. + HIPVeldin *big.Int `json:"hipveldin,omitempty"` } // String implements the fmt.Stringer interface. From 56c83dd3b09a4b963533491dc4ff3ad21a71e071 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 21:23:57 +0000 Subject: [PATCH 04/45] params: Add reward Schedule, remove etc improvments --- params/config_hypra.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/params/config_hypra.go b/params/config_hypra.go index 6ec0dfae6d..399a4e6e12 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -37,16 +37,11 @@ var ( // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? // DAOForkSupport isnt in this struct // DAOForkBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP160FBlock: big.NewInt(0), - ECIP1010PauseBlock: big.NewInt(0), - ECIP1010Length: big.NewInt(0), - ECIP1017FBlock: big.NewInt(0), - ECIP1017EraRounds: big.NewInt(0), - DisposalBlock: big.NewInt(0), - EIP161FBlock: big.NewInt(0), - EIP170FBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP160FBlock: big.NewInt(0), + EIP161FBlock: big.NewInt(0), + EIP170FBlock: big.NewInt(0), // Byzantium eq EIP100FBlock: big.NewInt(1001), @@ -97,6 +92,14 @@ var ( // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations // EIP6049FBlock: big.NewInt(19_250_000), // Deprecate SELFDESTRUCT (noop) + // Define the planned 3 year decreasing rewards. + BlockRewardSchedule: map[uint64]*big.Int{ + 0: big.NewInt(4 * vars.Ether), + 13_524_557: big.NewInt(3 * vars.Ether), + 27_200_177: big.NewInt(2 * vars.Ether), + 40_725_107: big.NewInt(1 * vars.Ether), + }, + RequireBlockHashes: map[uint64]common.Hash{ 156000: common.HexToHash("0x2a27bec023108c5f650cb0c9b7aaae7e7fdeefbeb3cd14a8390bb0957043aca2"), 512000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), From 1c3036f8c03facd174e5ed1c47d125ec5dc41b8c Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 21:32:48 +0000 Subject: [PATCH 05/45] params: Add Hypra alloc data --- params/alloc_hypra.go | 3 +++ params/genesis_hypra.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 params/alloc_hypra.go diff --git a/params/alloc_hypra.go b/params/alloc_hypra.go new file mode 100644 index 0000000000..10b42d7a3f --- /dev/null +++ b/params/alloc_hypra.go @@ -0,0 +1,3 @@ +package params + +var hypraAllocData = "\xf9\x02\xc1\xca\x01\x88\r\u0db3\xa7d\x00\x01\xca\x02\x88\x1b\xc1mgN\xc8\x00\x02\xca\x03\x88)\xa2$\x1a\xf6,\x00\x03\xca\x04\x887\x82\xda\u039d\x90\x00\x04\xca\x05\x88Ec\x91\x82D\xf4\x00\x05\xca\x06\x88SDH5\xecX\x00\x06\xca\a\x88a$\xfe\u94fc\x00\a\xca\b\x88o\x05\xb5\x9d; \x00\b\xca\t\x88|\xe6lP\xe2\x84\x00\t\u07d2\xb2\xbe}\u03c7*Fb\xe3;L\t\xe7\xfc\xe2\xd5\x00\x00\x8b\x01\xbc\xb1:e{&8\x80\x00\x00\u0794\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\r\u0db3\xa7d\x00\x00\xe0\x94\x12\xbb\xad|\x1f>\a\x9a\xf5\xe1\xea\x13te\xe7\x05o\xf3?\x87\x8aO\xf6c5\xad\xe1\x04\xb0\x00\x00\u0794 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x1b\xc1mgN\xc8\x00\x00\xe0\x94%U\u049a\x0eb\xd4Sco\xeaLoe\x13\x15\xdbM\xcd)\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07940\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88)\xa2$\x1a\xf6,\x00\x00\xe0\x942\xbc\xa0[\xe7z~9c\xa4:\xad\xfd\xac-\xeb\x16^@ \x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94=\x16i\x92\x88\xf87\xd4c\x9e\x87\xee=\xa3\x18gUq\xdee\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u0794@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x887\x82\xda\u039d\x90\x00\x00\u0794P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88Ec\x91\x82D\xf4\x00\x00\u0794`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88SDH5\xecX\x00\x00\xe1\x94d\xcf\\A\xe0Prb\xf9\"v\x80\xb8\xa4\x02\xe7{\xeb\xe0u\x8b\x04\"\u028b\n\x00\xa4%\x00\x00\x00\u0794j\xd9v0>3\xffaa\n\x13{\x98\x87\xf3h:U\x19K\x88\xa6\x88\x90k\u0630\x059\u0794p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88a$\xfe\u94fc\x00\x00\u0794\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88o\x05\xb5\x9d; \x00\x00\u150d\x01\xbf1\b\xc7>\x8dX0\nk\xf3\r[N\xa7H\u0783\x8b\x02\x90sV4H\x13\u0640\x00\x00\u0794\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88|\xe6lP\xe2\x84\x00\x00\u0794\xd8\x02h\u0792\x81\x9b\x8b\x99\x01?\xa9\xdd\v\xad?\xacc\xf0\x03\x88\r\u0db3\xa7d\x00\x00\xe0\x94\xf9a2Z\xa3 \xee+\xa6\xce\a\xa0\xf4\xb47t\x8f[\xcf\xe8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" \ No newline at end of file diff --git a/params/genesis_hypra.go b/params/genesis_hypra.go index c448dd27e5..0e14a1d613 100644 --- a/params/genesis_hypra.go +++ b/params/genesis_hypra.go @@ -34,7 +34,7 @@ func DefaultHypraGenesisBlock() *genesisT.Genesis { ExtraData: hexutil.MustDecode("0x5465736c6120656e746572732074686520656c65637472696320747275636b20626174746c65206166746572206669727374204379626572747275636b20726f6c6c73206f6666207468652070726f64756374696f6e206c696e65"), GasLimit: 50000, Difficulty: big.NewInt(9_035_329), - Alloc: genesisT.DecodePreAlloc(HypraAllocData), + Alloc: genesisT.DecodePreAlloc(hypraAllocData), Timestamp: 1689703500, } } From 6ef0c0d04b270848b521a09941e3f2cab70aac24 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 21:44:47 +0000 Subject: [PATCH 06/45] flags: Added --hypra flag --- cmd/utils/flags.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2182e0d5d3..80bb6b3912 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -190,6 +190,11 @@ var ( Usage: "Sepolia network: pre-configured proof-of-work test network", Category: flags.EthCategory, } + HypraFlag = &cli.BoolFlag{ + Name: "hypra", + Usage: "Hypra Network mainnet: pre-configured Hypra Network mainnet", + Category: flags.EthCategory, + } // Dev mode DeveloperFlag = &cli.BoolFlag{ @@ -1119,6 +1124,7 @@ var ( MainnetFlag, ClassicFlag, MintMeFlag, + HypraFlag, }, TestnetFlags...) // DatabasePathFlags is the flag group of all database path flags. @@ -1191,6 +1197,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls = params.ClassicBootnodes case ctx.Bool(MintMeFlag.Name): urls = params.MintMeBootnodes + case ctx.Bool(HypraFlag.Name): + urls = params.HypraBootnodes case ctx.Bool(MordorFlag.Name): urls = params.MordorBootnodes case ctx.Bool(SepoliaFlag.Name): @@ -1232,6 +1240,8 @@ func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { urls = params.GoerliBootnodes case ctx.Bool(MintMeFlag.Name): urls = params.MintMeBootnodes + case ctx.Bool(HypraFlag.Name): + urls = params.HypraBootnodes case cfg.BootstrapNodesV5 != nil: return // already set, don't apply defaults. } @@ -1702,6 +1712,8 @@ func dataDirPathForCtxChainConfig(ctx *cli.Context, baseDataDirPath string) stri return filepath.Join(baseDataDirPath, "sepolia") case ctx.Bool(MintMeFlag.Name): return filepath.Join(baseDataDirPath, "mintme") + case ctx.Bool(HypraFlag.Name): + return filepath.Join(baseDataDirPath, "hypra") } return baseDataDirPath } @@ -1952,7 +1964,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, DeveloperPoWFlag, GoerliFlag, SepoliaFlag, ClassicFlag, MordorFlag, MintMeFlag) + CheckExclusive(ctx, MainnetFlag, DeveloperFlag, DeveloperPoWFlag, GoerliFlag, SepoliaFlag, ClassicFlag, MordorFlag, MintMeFlag, HypraFlag) CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, DeveloperFlag, DeveloperPoWFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { @@ -2511,6 +2523,8 @@ func genesisForCtxChainConfig(ctx *cli.Context) *genesisT.Genesis { genesis = params.DefaultGoerliGenesisBlock() case ctx.Bool(MintMeFlag.Name): genesis = params.DefaultMintMeGenesisBlock() + case ctx.Bool(HypraFlag.Name): + genesis = params.DefaultHypraGenesisBlock() case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } From 16782da52bfd9e98743f98a080b0fb69b55b852b Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 7 Feb 2024 21:45:03 +0000 Subject: [PATCH 07/45] params: Added Hypra bootnodes --- params/bootnodes_hypra.go | 18 ++++++++++++++++++ params/config_hypra.go | 5 +++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 params/bootnodes_hypra.go diff --git a/params/bootnodes_hypra.go b/params/bootnodes_hypra.go new file mode 100644 index 0000000000..2096ce8bdf --- /dev/null +++ b/params/bootnodes_hypra.go @@ -0,0 +1,18 @@ +package params + +// HypraBootnodes are the enode URLs of the P2P bootstrap nodes running +// reliably and availably on the MintMe network. +var HypraBootnodes = []string{ + // Foundation Bootnodes + "enode://b3d8c6ad187f54860bd288e8e343c5cb05db023b3a74a4cd9d85cae3e2677074f92b3afecfd2bb445f9cba151848d3294abff9bedcee5d437ff161300f5144e9@77.100.75.201:30303", // Dev + "enode://301c2d2d622fe3d49f9a9d5a294a1a65ce0f686a10b5b6ea2e965533b7e84ecea25f1f2eec78e6fa948ca129ec5f9a8fe731d9641df0163e4847ded09dbfd1e4@54.36.108.60:30303", // Explorer + + // Communtiy Bootnodes + "enode://959f6378ee6162f57977e5e6ab8dd56bd8ef5d1bc2a1bb01c6b41cfc2d07ea490d4c939c7625f13886c684b221a9c3e710e4a66a718a3231c40d2536c344df9d@27.254.39.27:30308", + "enode://e82bf286f09a7b86f5528a0e7c29928a8bb0bf9416d9678a91da9e2729480700a71777490ed115cad82b9f75268fc1f9a0d9483bb65acd6665708778c2d035f5@178.234.84.24:30303?discport=1337", + "enode://fe072785d5044f22b393df8a364dcc92d927b9f88aff14bff2484db20caa8350a07df3b9b1f0fb0b222304f426ab887ad9829bff6948aba84e3b5f1776b8dd52@195.201.122.219:30303", +} + +// Once Hypra network has DNS discovery set up, +// this value can be configured. +// var HypraDNSNetwork = "enrtree://AJE62Q4DUX4QMMXEHCSSCSC65TDHZYSMONSD64P3WULVLSF6MRQ3K@example.network" diff --git a/params/config_hypra.go b/params/config_hypra.go index 399a4e6e12..dad533ab70 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -101,8 +101,9 @@ var ( }, RequireBlockHashes: map[uint64]common.Hash{ - 156000: common.HexToHash("0x2a27bec023108c5f650cb0c9b7aaae7e7fdeefbeb3cd14a8390bb0957043aca2"), - 512000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), + 156_000: common.HexToHash("0x2a27bec023108c5f650cb0c9b7aaae7e7fdeefbeb3cd14a8390bb0957043aca2"), + 512_000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), + 1_878_299: common.HexToHash("0x1834091726bd0890539db04a22b673a6d9262d8b350dffaefdb10abc72e2113d"), }, } ) From d1a8fd8d8379a154fafcb9cb51a920470d32f2be Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 16:37:19 +0000 Subject: [PATCH 08/45] ethashb3: rename structs to ethashb3, remove classic epoch forks. --- consensus/ethashb3/algorithm.go | 46 +++++----- consensus/ethashb3/api.go | 28 +++--- consensus/ethashb3/consensus.go | 82 ++++++++--------- consensus/ethashb3/ethash.go | 153 ++++++++++++++------------------ consensus/ethashb3/sealer.go | 76 ++++++++-------- 5 files changed, 182 insertions(+), 203 deletions(-) diff --git a/consensus/ethashb3/algorithm.go b/consensus/ethashb3/algorithm.go index c61c9232e0..2d649c6b51 100644 --- a/consensus/ethashb3/algorithm.go +++ b/consensus/ethashb3/algorithm.go @@ -35,28 +35,22 @@ import ( ) const ( - datasetInitBytes = 1 << 30 // Bytes in dataset at genesis - datasetGrowthBytes = 1 << 23 // Dataset growth per epoch - cacheInitBytes = 1 << 24 // Bytes in cache at genesis - cacheGrowthBytes = 1 << 17 // Cache growth per epoch - epochLengthDefault = 32000 // Default epoch length (blocks per epoch) - epochLengthECIP1099 = 60000 // Blocks per epoch if ECIP-1099 is activated - mixBytes = 128 // Width of mix - hashBytes = 64 // Hash length in bytes - hashWords = 16 // Number of 32 bit ints in a hash - datasetParents = 256 // Number of parents of each dataset element - cacheRounds = 3 // Number of rounds in cache production - loopAccesses = 64 // Number of accesses in hashimoto loop - maxEpoch = 2048 // Max Epoch for included tables + datasetInitBytes = 1 << 30 // Bytes in dataset at genesis + datasetGrowthBytes = 1 << 23 // Dataset growth per epoch + cacheInitBytes = 1 << 24 // Bytes in cache at genesis + cacheGrowthBytes = 1 << 17 // Cache growth per epoch + epochLengthDefault = 32000 // Default epoch length (blocks per epoch) + mixBytes = 128 // Width of mix + hashBytes = 64 // Hash length in bytes + hashWords = 16 // Number of 32 bit ints in a hash + datasetParents = 256 // Number of parents of each dataset element + cacheRounds = 3 // Number of rounds in cache production + loopAccesses = 64 // Number of accesses in hashimoto loop + maxEpoch = 2048 // Max Epoch for included tables ) -// calcEpochLength returns the epoch length for a given block number (ECIP-1099) -func calcEpochLength(block uint64, ecip1099FBlock *uint64) uint64 { - if ecip1099FBlock != nil { - if block >= *ecip1099FBlock { - return epochLengthECIP1099 - } - } +// calcEpochLength returns the epoch length, block number isnt used on Hypra +func calcEpochLength(_ uint64) uint64 { return epochLengthDefault } @@ -71,7 +65,7 @@ func calcEpochBlock(epoch uint64, epochLength uint64) uint64 { return epoch*epochLength + 1 } -// cacheSize returns the size of the ethash verification cache that belongs to a certain +// cacheSize returns the size of the ethashb3 verification cache that belongs to a certain // block number. func cacheSize(epoch uint64) uint64 { if epoch < maxEpoch { @@ -91,7 +85,7 @@ func calcCacheSize(epoch uint64) uint64 { return size } -// datasetSize returns the size of the ethash mining dataset that belongs to a certain +// datasetSize returns the size of the ethashb3 mining dataset that belongs to a certain // block number. func datasetSize(epoch uint64) uint64 { if epoch < maxEpoch { @@ -249,7 +243,7 @@ func fnv(a, b uint32) uint32 { return a*0x01000193 ^ b } -// fnvHash mixes in data into mix using the ethash fnv method. +// fnvHash mixes in data into mix using the ethashb3 fnv method. func fnvHash(mix []uint32, data []uint32) { for i := 0; i < len(mix); i++ { mix[i] = mix[i]*0x01000193 ^ data[i] @@ -289,7 +283,7 @@ func generateDatasetItem(cache []uint32, index uint32, keccak512 hasher) []byte return mix } -// generateDataset generates the entire ethash dataset for mining. +// generateDataset generates the entire ethashb3 dataset for mining. // This method places the result into dest in machine byte order. func generateDataset(dest []uint32, epoch uint64, epochLength uint64, cache []uint32) { // Print some debug logs to allow analysis on low end devices @@ -431,7 +425,7 @@ func hashimotoFull(dataset []uint32, hash []byte, nonce uint64) ([]byte, []byte) return hashimoto(hash, nonce, uint64(len(dataset))*4, lookup) } -// datasetSizes is a lookup table for the ethash dataset size for the first 2048 +// datasetSizes is a lookup table for the ethashb3 dataset size for the first 2048 // epochs (i.e. 61440000 blocks). var datasetSizes = [maxEpoch]uint64{ 1073739904, 1082130304, 1090514816, 1098906752, 1107293056, @@ -845,7 +839,7 @@ var datasetSizes = [maxEpoch]uint64{ 18186498944, 18194886784, 18203275648, 18211666048, 18220048768, 18228444544, 18236833408, 18245220736} -// cacheSizes is a lookup table for the ethash verification cache size for the +// cacheSizes is a lookup table for the ethashb3 verification cache size for the // first 2048 epochs (i.e. 61440000 blocks). var cacheSizes = [maxEpoch]uint64{ 16776896, 16907456, 17039296, 17170112, 17301056, 17432512, 17563072, diff --git a/consensus/ethashb3/api.go b/consensus/ethashb3/api.go index aab2d67b84..573823b573 100644 --- a/consensus/ethashb3/api.go +++ b/consensus/ethashb3/api.go @@ -24,11 +24,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -var errEthashStopped = errors.New("ethashb3 stopped") +var errEthashB3Stopped = errors.New("ethashb3 stopped") -// API exposes ethash related methods for the RPC interface. +// API exposes ethashb3 related methods for the RPC interface. type API struct { - ethash *EthashB3 + ethashb3 *EthashB3 } // GetWork returns a work package for external miner. @@ -40,7 +40,7 @@ type API struct { // 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.ethash.remote == nil { + if api.ethashb3.remote == nil { return [4]string{}, errors.New("not supported") } @@ -49,9 +49,9 @@ func (api *API) GetWork() ([4]string, error) { errc = make(chan error, 1) ) select { - case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}: - case <-api.ethash.remote.exitCh: - return [4]string{}, errEthashStopped + case api.ethashb3.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}: + case <-api.ethashb3.remote.exitCh: + return [4]string{}, errEthashB3Stopped } select { case work := <-workCh: @@ -65,19 +65,19 @@ func (api *API) GetWork() ([4]string, error) { // 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.ethash.remote == nil { + if api.ethashb3.remote == nil { return false } var errc = make(chan error, 1) select { - case api.ethash.remote.submitWorkCh <- &mineResult{ + case api.ethashb3.remote.submitWorkCh <- &mineResult{ nonce: nonce, mixDigest: digest, hash: hash, errc: errc, }: - case <-api.ethash.remote.exitCh: + case <-api.ethashb3.remote.exitCh: return false } err := <-errc @@ -91,14 +91,14 @@ func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) boo // 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 { - if api.ethash.remote == nil { + if api.ethashb3.remote == nil { return false } var done = make(chan struct{}, 1) select { - case api.ethash.remote.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}: - case <-api.ethash.remote.exitCh: + case api.ethashb3.remote.submitRateCh <- &hashrate{done: done, rate: uint64(rate), id: id}: + case <-api.ethashb3.remote.exitCh: return false } @@ -109,5 +109,5 @@ func (api *API) SubmitHashrate(rate hexutil.Uint64, id common.Hash) bool { // GetHashrate returns the current hashrate for local CPU miner and remote miner. func (api *API) GetHashrate() uint64 { - return uint64(api.ethash.Hashrate()) + return uint64(api.ethashb3.Hashrate()) } diff --git a/consensus/ethashb3/consensus.go b/consensus/ethashb3/consensus.go index b74f222100..bb01f37d3c 100644 --- a/consensus/ethashb3/consensus.go +++ b/consensus/ethashb3/consensus.go @@ -63,15 +63,15 @@ var ( // Author implements consensus.Engine, returning the header's coinbase as the // proof-of-work verified author of the block. -func (ethash *EthashB3) Author(header *types.Header) (common.Address, error) { +func (ethashb3 *EthashB3) 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 ethash engine. -func (ethash *EthashB3) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { +// stock Ethereum ethashb3 engine. +func (ethashb3 *EthashB3) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { // If we're running a full engine faking, accept any input as valid - if ethash.config.PowMode == ModeFullFake { + if ethashb3.config.PowMode == ModeFullFake { return nil } // Short circuit if the header is known, or its parent not @@ -84,15 +84,15 @@ func (ethash *EthashB3) VerifyHeader(chain consensus.ChainHeaderReader, header * return consensus.ErrUnknownAncestor } // Sanity checks passed, do a proper verification - return ethash.verifyHeader(chain, header, parent, false, seal, time.Now().Unix()) + return ethashb3.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 (ethash *EthashB3) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { +func (ethashb3 *EthashB3) 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 ethash.config.PowMode == ModeFullFake || len(headers) == 0 { + if ethashb3.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 @@ -117,7 +117,7 @@ func (ethash *EthashB3) VerifyHeaders(chain consensus.ChainHeaderReader, headers for i := 0; i < workers; i++ { go func() { for index := range inputs { - errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index, unixNow) + errors[index] = ethashb3.verifyHeaderWorker(chain, headers, seals, index, unixNow) done <- index } }() @@ -153,7 +153,7 @@ func (ethash *EthashB3) VerifyHeaders(chain consensus.ChainHeaderReader, headers return abort, errorsOut } -func (ethash *EthashB3) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, index int, unixNow int64) error { +func (ethashb3 *EthashB3) 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) @@ -163,14 +163,14 @@ func (ethash *EthashB3) verifyHeaderWorker(chain consensus.ChainHeaderReader, he if parent == nil { return consensus.ErrUnknownAncestor } - return ethash.verifyHeader(chain, headers[index], parent, false, seals[index], unixNow) + return ethashb3.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 ethash engine. -func (ethash *EthashB3) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { +// rules of the stock Ethereum ethashb3 engine. +func (ethashb3 *EthashB3) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { // If we're running a full engine faking, accept any input as valid - if ethash.config.PowMode == ModeFullFake { + if ethashb3.config.PowMode == ModeFullFake { return nil } // Verify that there are at most 2 uncles included in this block @@ -222,7 +222,7 @@ func (ethash *EthashB3) VerifyUncles(chain consensus.ChainReader, block *types.B if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { return errDanglingUncle } - if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true, time.Now().Unix()); err != nil { + if err := ethashb3.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true, time.Now().Unix()); err != nil { return err } } @@ -230,9 +230,9 @@ func (ethash *EthashB3) VerifyUncles(chain consensus.ChainReader, block *types.B } // verifyHeader checks whether a header conforms to the consensus rules of the -// stock Ethereum ethash engine. +// stock Ethereum ethashb3 engine. // See YP section 4.3.4. "Block Header Validity" -func (ethash *EthashB3) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, seal bool, unixNow int64) error { +func (ethashb3 *EthashB3) 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)) > vars.MaximumExtraDataSize { return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), vars.MaximumExtraDataSize) @@ -247,7 +247,7 @@ func (ethash *EthashB3) verifyHeader(chain consensus.ChainHeaderReader, header, return errOlderBlockTime } // Verify the block's difficulty based on its timestamp and parent's difficulty - expected := ethash.CalcDifficulty(chain, header.Time, parent) + expected := ethashb3.CalcDifficulty(chain, header.Time, parent) if expected.Cmp(header.Difficulty) != 0 { return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) @@ -280,7 +280,7 @@ func (ethash *EthashB3) verifyHeader(chain consensus.ChainHeaderReader, header, // Verify the engine specific seal securing the block if seal { - if err := ethash.verifySeal(chain, header, false); err != nil { + if err := ethashb3.verifySeal(chain, header, false); err != nil { return err } } @@ -294,7 +294,7 @@ func (ethash *EthashB3) verifyHeader(chain consensus.ChainHeaderReader, header, // 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 (ethash *EthashB3) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { +func (ethashb3 *EthashB3) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { return CalcDifficulty(chain.Config(), time, parent) } @@ -383,20 +383,20 @@ var HomesteadDifficultyCalculator = CalcDifficultyHomesteadU256 var DynamicDifficultyCalculator = MakeDifficultyCalculatorU256 // verifySeal checks whether a block satisfies the PoW difficulty requirements, -// either using the usual ethash cache for it, or alternatively using a full DAG +// either using the usual ethashb3 cache for it, or alternatively using a full DAG // to make remote mining fast. -func (ethash *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error { +func (ethashb3 *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error { // If we're running a fake PoW, accept any seal as valid - if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModePoissonFake || ethash.config.PowMode == ModeFullFake { - time.Sleep(ethash.fakeDelay) - if ethash.fakeFail == header.Number.Uint64() { + if ethashb3.config.PowMode == ModeFake || ethashb3.config.PowMode == ModePoissonFake || ethashb3.config.PowMode == ModeFullFake { + time.Sleep(ethashb3.fakeDelay) + if ethashb3.fakeFail == header.Number.Uint64() { return errInvalidPoW } return nil } // If we're running a shared PoW, delegate verification to it - if ethash.shared != nil { - return ethash.shared.verifySeal(chain, header, fulldag) + if ethashb3.shared != nil { + return ethashb3.shared.verifySeal(chain, header, fulldag) } // Ensure that we have a valid difficulty for the block if header.Difficulty.Sign() <= 0 { @@ -409,11 +409,11 @@ func (ethash *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *ty digest []byte result []byte ) - // If fast-but-heavy PoW verification was requested, use an ethash dataset + // If fast-but-heavy PoW verification was requested, use an ethashb3 dataset if fulldag { - dataset := ethash.dataset(number, true) + dataset := ethashb3.dataset(number, true) if dataset.generated() { - digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) + digest, result = hashimotoFull(dataset.dataset, ethashb3.SealHash(header).Bytes(), header.Nonce.Uint64()) // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive // until after the call to hashimotoFull so it's not unmapped while being used. @@ -423,16 +423,16 @@ func (ethash *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *ty fulldag = false } } - // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache + // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethashb3 cache if !fulldag { - cache := ethash.cache(number) - epochLength := calcEpochLength(number, ethash.config.ECIP1099Block) + cache := ethashb3.cache(number) + epochLength := calcEpochLength(number) epoch := calcEpoch(number, epochLength) size := datasetSize(epoch) - if ethash.config.PowMode == ModeTest { + if ethashb3.config.PowMode == ModeTest { size = 32 * 1024 } - digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) + digest, result = hashimotoLight(size, cache.cache, ethashb3.SealHash(header).Bytes(), header.Nonce.Uint64()) // Caches are unmapped in a finalizer. Ensure that the cache stays alive // until after the call to hashimotoLight so it's not unmapped while being used. @@ -450,30 +450,30 @@ func (ethash *EthashB3) verifySeal(chain consensus.ChainHeaderReader, header *ty } // Prepare implements consensus.Engine, initializing the difficulty field of a -// header to conform to the ethash protocol. The changes are done inline. -func (ethash *EthashB3) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { +// header to conform to the ethashb3 protocol. The changes are done inline. +func (ethashb3 *EthashB3) 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 = ethash.CalcDifficulty(chain, header.Time, parent) + header.Difficulty = ethashb3.CalcDifficulty(chain, header.Time, parent) return nil } // Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *EthashB3) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (ethashb3 *EthashB3) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Accumulate any block and uncle rewards and commit the final state root mutations.AccumulateRewards(chain.Config(), state, header, uncles) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. -func (ethash *EthashB3) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (ethashb3 *EthashB3) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if len(withdrawals) > 0 { return nil, errors.New("ethashb3 does not support withdrawals") } // Finalize block - ethash.Finalize(chain, header, state, txs, uncles, nil) + ethashb3.Finalize(chain, header, state, txs, uncles, nil) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEnabled(chain.Config().GetEIP161dTransition, header.Number)) @@ -483,7 +483,7 @@ func (ethash *EthashB3) FinalizeAndAssemble(chain consensus.ChainHeaderReader, h } // SealHash returns the hash of a block prior to it being sealed. -func (ethash *EthashB3) SealHash(header *types.Header) (hash common.Hash) { +func (ethashb3 *EthashB3) SealHash(header *types.Header) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() enc := []interface{}{ diff --git a/consensus/ethashb3/ethash.go b/consensus/ethashb3/ethash.go index e3f1eaf786..e8cad539c4 100644 --- a/consensus/ethashb3/ethash.go +++ b/consensus/ethashb3/ethash.go @@ -234,7 +234,7 @@ func newlru[T cacheOrDataset](maxItems int, new func(epoch uint64, epochLength u // get retrieves or creates an item for the given epoch. The first return value is always // non-nil. The second return value is non-nil if lru thinks that an item will be useful in // the near future. -func (lru *lru[T]) get(epoch uint64, epochLength uint64, ecip1099FBlock *uint64) (item, future T) { +func (lru *lru[T]) get(epoch uint64, epochLength uint64) (item, future T) { lru.mu.Lock() defer lru.mu.Unlock() @@ -257,16 +257,6 @@ func (lru *lru[T]) get(epoch uint64, epochLength uint64, ecip1099FBlock *uint64) // Ensure pre-generation handles ecip-1099 changeover correctly var nextEpoch = epoch + 1 var nextEpochLength = epochLength - if ecip1099FBlock != nil { - nextEpochBlock := nextEpoch * epochLength - // Note that == demands that the ECIP1099 activation block is situated - // at the beginning of an epoch. - // https://github.com/ethereumclassic/ECIPs/blob/master/_specs/ecip-1099.md#implementation - if nextEpochBlock == *ecip1099FBlock && epochLength == epochLengthDefault { - nextEpoch = nextEpoch / 2 - nextEpochLength = epochLengthECIP1099 - } - } // Update the 'future item' if epoch is larger than previously seen. // Last conditional clause ('lru.future > nextEpoch') handles the ECIP1099 case where @@ -280,7 +270,7 @@ func (lru *lru[T]) get(epoch uint64, epochLength uint64, ecip1099FBlock *uint64) return item, future } -// cache wraps an ethash cache with some metadata to allow easier concurrent use. +// cache wraps an ethashb3 cache with some metadata to allow easier concurrent use. type cache struct { epoch uint64 // Epoch for which this cache is relevant epochLength uint64 // Epoch length (ECIP-1099) @@ -290,7 +280,7 @@ type cache struct { once sync.Once // Ensures the cache is generated only once } -// newCache creates a new ethash verification cache. +// newCache creates a new ethashb3 verification cache. func newCache(epoch uint64, epochLength uint64) *cache { return &cache{epoch: epoch, epochLength: epochLength} } @@ -384,7 +374,7 @@ func (c *cache) finalizer() { } } -// dataset wraps an ethash dataset with some metadata to allow easier concurrent use. +// dataset wraps an ethashb3 dataset with some metadata to allow easier concurrent use. type dataset struct { epoch uint64 // Epoch for which this cache is relevant epochLength uint64 // Epoch length (ECIP-1099) @@ -395,7 +385,7 @@ type dataset struct { done atomic.Bool // Atomic flag to determine generation status } -// newDataset creates a new ethash mining dataset and returns it as a plain Go +// newDataset creates a new ethashb3 mining dataset and returns it as a plain Go // interface to be usable in an LRU cache. func newDataset(epoch uint64, epochLength uint64) *dataset { return &dataset{epoch: epoch, epochLength: epochLength} @@ -469,7 +459,7 @@ func (d *dataset) generate(dir string, limit int, lock bool, test bool) { if _, err := fmt.Sscanf(filepath.Base(file), "full-R%d-%s"+endian, &ar, &s); err == nil { // This file matches the previous generation naming pattern (sans epoch). if err := os.Remove(file); err != nil { - logger.Error("Failed to remove legacy ethash full file", "file", file, "err", err) + logger.Error("Failed to remove legacy ethashb3 full file", "file", file, "err", err) } else { logger.Warn("Deleted legacy ethashb3 full file", "path", file) } @@ -481,7 +471,7 @@ func (d *dataset) generate(dir string, limit int, lock bool, test bool) { if err := os.Remove(file); err == nil { logger.Debug("Deleted ethashb3 full file", "target.epoch", e, "file", file) } else { - logger.Error("Failed to delete ethash full file", "target.epoch", e, "file", file, "err", err) + logger.Error("Failed to delete ethashb3 full file", "target.epoch", e, "file", file, "err", err) } } } @@ -504,21 +494,21 @@ func (d *dataset) finalizer() { } } -// MakeCache generates a new ethash cache and optionally stores it to disk. +// MakeCache generates a new ethashb3 cache and optionally stores it to disk. func MakeCache(block uint64, epochLength uint64, dir string) { epoch := calcEpoch(block, epochLength) c := cache{epoch: epoch, epochLength: epochLength} c.generate(dir, math.MaxInt32, false, false) } -// MakeDataset generates a new ethash dataset and optionally stores it to disk. +// MakeDataset generates a new ethashb3 dataset and optionally stores it to disk. func MakeDataset(block uint64, epochLength uint64, dir string) { epoch := calcEpoch(block, epochLength) d := dataset{epoch: epoch, epochLength: epochLength} d.generate(dir, math.MaxInt32, false, false) } -// Mode defines the type and amount of PoW verification an ethash engine makes. +// Mode defines the type and amount of PoW verification an ethashb3 engine makes. type Mode uint const ( @@ -548,7 +538,7 @@ func (m Mode) String() string { return "unknown" } -// Config are the configuration parameters of the ethash. +// Config are the configuration parameters of the ethashb3. type Config struct { CacheDir string CachesInMem int @@ -569,7 +559,7 @@ type Config struct { ECIP1099Block *uint64 `toml:"-"` } -// EthashB3 is a consensus engine based on proof-of-work implementing the ethash +// EthashB3 is a consensus engine based on proof-of-work implementing the ethashb3 // algorithm. type EthashB3 struct { config Config @@ -593,7 +583,7 @@ type EthashB3 struct { closeOnce sync.Once // Ensures exit channel will not be closed twice. } -// New creates a full sized ethash PoW scheme and starts a background thread for +// New creates a full sized ethashb3 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) *EthashB3 { @@ -605,10 +595,10 @@ func New(config Config, notify []string, noverify bool) *EthashB3 { config.CachesInMem = 1 } if config.CacheDir != "" && config.CachesOnDisk > 0 { - config.Log.Info("Disk storage enabled for ethash caches", "dir", config.CacheDir, "count", config.CachesOnDisk) + config.Log.Info("Disk storage enabled for ethashb3 caches", "dir", config.CacheDir, "count", config.CachesOnDisk) } if config.DatasetDir != "" && config.DatasetsOnDisk > 0 { - config.Log.Info("Disk storage enabled for ethash DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk) + config.Log.Info("Disk storage enabled for ethashb3 DAGs", "dir", config.DatasetDir, "count", config.DatasetsOnDisk) } ethash := &EthashB3{ config: config, @@ -624,13 +614,13 @@ func New(config Config, notify []string, noverify bool) *EthashB3 { return ethash } -// NewTester creates a small sized ethash PoW scheme useful only for testing +// NewTester creates a small sized ethashb3 PoW scheme useful only for testing // purposes. func NewTester(notify []string, noverify bool) *EthashB3 { return New(Config{PowMode: ModeTest}, notify, noverify) } -// NewFaker creates a ethash consensus engine with a fake PoW scheme that accepts +// NewFaker creates a ethashb3 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() *EthashB3 { @@ -642,7 +632,7 @@ func NewFaker() *EthashB3 { } } -// NewFakeFailer creates a ethash consensus engine with a fake PoW scheme that +// NewFakeFailer creates a ethashb3 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) *EthashB3 { @@ -655,7 +645,7 @@ func NewFakeFailer(fail uint64) *EthashB3 { } } -// NewFakeDelayer creates a ethash consensus engine with a fake PoW scheme that +// NewFakeDelayer creates a ethashb3 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) *EthashB3 { @@ -668,7 +658,7 @@ func NewFakeDelayer(delay time.Duration) *EthashB3 { } } -// NewPoissonFaker creates a ethash consensus engine with a fake PoW scheme that +// NewPoissonFaker creates a ethashb3 consensus engine with a fake PoW scheme that // accepts all blocks as valid, but delays mining by some time based on miner.threads, though // they still have to conform to the Ethereum consensus rules. func NewPoissonFaker() *EthashB3 { @@ -680,7 +670,7 @@ func NewPoissonFaker() *EthashB3 { } } -// NewFullFaker creates an ethash consensus engine with a full fake scheme that +// NewFullFaker creates an ethashb3 consensus engine with a full fake scheme that // accepts all blocks as valid, without checking any consensus rules whatsoever. func NewFullFaker() *EthashB3 { return &EthashB3{ @@ -691,26 +681,26 @@ func NewFullFaker() *EthashB3 { } } -// NewShared creates a full sized ethash PoW shared between all requesters running +// NewShared creates a full sized ethashb3 PoW shared between all requesters running // in the same process. func NewShared() *EthashB3 { return &EthashB3{shared: sharedEthash} } // Close closes the exit channel to notify all backend threads exiting. -func (ethash *EthashB3) Close() error { - return ethash.StopRemoteSealer() +func (ethashb3 *EthashB3) Close() error { + return ethashb3.StopRemoteSealer() } // StopRemoteSealer stops the remote sealer -func (ethash *EthashB3) StopRemoteSealer() error { - ethash.closeOnce.Do(func() { +func (ethashb3 *EthashB3) StopRemoteSealer() error { + ethashb3.closeOnce.Do(func() { // Short circuit if the exit channel is not allocated. - if ethash.remote == nil { + if ethashb3.remote == nil { return } - close(ethash.remote.requestExit) - <-ethash.remote.exitCh + close(ethashb3.remote.requestExit) + <-ethashb3.remote.exitCh }) return nil } @@ -718,17 +708,17 @@ func (ethash *EthashB3) StopRemoteSealer() error { // cache tries to retrieve a verification cache for the specified block number // by first checking against a list of in-memory caches, then against caches // stored on disk, and finally generating one if none can be found. -func (ethash *EthashB3) cache(block uint64) *cache { - epochLength := calcEpochLength(block, ethash.config.ECIP1099Block) +func (ethashb3 *EthashB3) cache(block uint64) *cache { + epochLength := calcEpochLength(block) epoch := calcEpoch(block, epochLength) - current, future := ethash.caches.get(epoch, epochLength, ethash.config.ECIP1099Block) + current, future := ethashb3.caches.get(epoch, epochLength) // Wait for generation finish. - current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest) + current.generate(ethashb3.config.CacheDir, ethashb3.config.CachesOnDisk, ethashb3.config.CachesLockMmap, ethashb3.config.PowMode == ModeTest) // If we need a new future cache, now's a good time to regenerate it. if future != nil { - go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest) + go future.generate(ethashb3.config.CacheDir, ethashb3.config.CachesOnDisk, ethashb3.config.CachesLockMmap, ethashb3.config.PowMode == ModeTest) } return current } @@ -739,30 +729,25 @@ func (ethash *EthashB3) cache(block uint64) *cache { // // If async is specified, not only the future but the current DAG is also // generates on a background thread. -func (ethash *EthashB3) dataset(block uint64, async bool) *dataset { - // Retrieve the requested ethash dataset - epochLength := calcEpochLength(block, ethash.config.ECIP1099Block) +func (ethashb3 *EthashB3) dataset(block uint64, async bool) *dataset { + // Retrieve the requested ethashb3 dataset + epochLength := calcEpochLength(block) epoch := calcEpoch(block, epochLength) - current, future := ethash.datasets.get(epoch, epochLength, ethash.config.ECIP1099Block) - - // set async false if ecip-1099 transition in case of regeneratiion bad DAG on disk - if epochLength == epochLengthECIP1099 && (epoch == 42 || epoch == 195) { - async = false - } + current, future := ethashb3.datasets.get(epoch, epochLength) // If async is specified, generate everything in a background thread if async && !current.generated() { go func() { - current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + current.generate(ethashb3.config.DatasetDir, ethashb3.config.DatasetsOnDisk, ethashb3.config.DatasetsLockMmap, ethashb3.config.PowMode == ModeTest) if future != nil { - future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + future.generate(ethashb3.config.DatasetDir, ethashb3.config.DatasetsOnDisk, ethashb3.config.DatasetsLockMmap, ethashb3.config.PowMode == ModeTest) } }() } else { // Either blocking generation was requested, or already done - current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + current.generate(ethashb3.config.DatasetDir, ethashb3.config.DatasetsOnDisk, ethashb3.config.DatasetsLockMmap, ethashb3.config.PowMode == ModeTest) if future != nil { - go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest) + go future.generate(ethashb3.config.DatasetDir, ethashb3.config.DatasetsOnDisk, ethashb3.config.DatasetsLockMmap, ethashb3.config.PowMode == ModeTest) } } return current @@ -770,11 +755,11 @@ func (ethash *EthashB3) dataset(block uint64, async bool) *dataset { // Threads returns the number of mining threads currently enabled. This doesn't // necessarily mean that mining is running! -func (ethash *EthashB3) Threads() int { - ethash.lock.Lock() - defer ethash.lock.Unlock() +func (ethashb3 *EthashB3) Threads() int { + ethashb3.lock.Lock() + defer ethashb3.lock.Unlock() - return ethash.threads + return ethashb3.threads } // SetThreads updates the number of mining threads currently enabled. Calling @@ -782,19 +767,19 @@ func (ethash *EthashB3) Threads() int { // 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 (ethash *EthashB3) SetThreads(threads int) { - ethash.lock.Lock() - defer ethash.lock.Unlock() +func (ethashb3 *EthashB3) SetThreads(threads int) { + ethashb3.lock.Lock() + defer ethashb3.lock.Unlock() // If we're running a shared PoW, set the thread count on that instead - if ethash.shared != nil { - ethash.shared.SetThreads(threads) + if ethashb3.shared != nil { + ethashb3.shared.SetThreads(threads) return } // Update the threads and ping any running seal to pull in any changes - ethash.threads = threads + ethashb3.threads = threads select { - case ethash.update <- struct{}{}: + case ethashb3.update <- struct{}{}: default: } } @@ -803,36 +788,36 @@ func (ethash *EthashB3) SetThreads(threads int) { // per second over the last minute. // Note the returned hashrate includes local hashrate, but also includes the total // hashrate of all remote miner. -func (ethash *EthashB3) Hashrate() float64 { - // Short circuit if we are run the ethash in normal/test mode. - if ethash.config.PowMode != ModeNormal && ethash.config.PowMode != ModeTest { - return ethash.hashrate.Rate1() +func (ethashb3 *EthashB3) Hashrate() float64 { + // Short circuit if we are run the ethashb3 in normal/test mode. + if ethashb3.config.PowMode != ModeNormal && ethashb3.config.PowMode != ModeTest { + return ethashb3.hashrate.Rate1() } var res = make(chan uint64, 1) select { - case ethash.remote.fetchRateCh <- res: - case <-ethash.remote.exitCh: - // Return local hashrate only if ethash is stopped. - return ethash.hashrate.Rate1() + case ethashb3.remote.fetchRateCh <- res: + case <-ethashb3.remote.exitCh: + // Return local hashrate only if ethashb3 is stopped. + return ethashb3.hashrate.Rate1() } // Gather total submitted hash rate of remote sealers. - return ethash.hashrate.Rate1() + float64(<-res) + return ethashb3.hashrate.Rate1() + float64(<-res) } // APIs implements consensus.Engine, returning the user facing RPC APIs. -func (ethash *EthashB3) APIs(chain consensus.ChainHeaderReader) []rpc.API { - // In order to ensure backward compatibility, we exposes ethash RPC APIs - // to both eth and ethash namespaces. +func (ethashb3 *EthashB3) APIs(chain consensus.ChainHeaderReader) []rpc.API { + // In order to ensure backward compatibility, we exposes ethashb3 RPC APIs + // to both eth and ethashb3 namespaces. return []rpc.API{ { Namespace: "eth", - Service: &API{ethash}, + Service: &API{ethashb3}, }, { Namespace: "ethashb3", - Service: &API{ethash}, + Service: &API{ethashb3}, }, } } @@ -844,8 +829,8 @@ func SeedHash(epoch uint64, epochLength uint64) []byte { } // CalcEpochLength returns the epoch length for a given block number (ECIP-1099) -func CalcEpochLength(block uint64, ecip1099FBlock *uint64) uint64 { - return calcEpochLength(block, ecip1099FBlock) +func CalcEpochLength(block uint64) uint64 { + return calcEpochLength(block) } // CalcEpoch returns the epoch for a given block number (ECIP-1099) diff --git a/consensus/ethashb3/sealer.go b/consensus/ethashb3/sealer.go index 3847f5ef8a..734aec0bc6 100644 --- a/consensus/ethashb3/sealer.go +++ b/consensus/ethashb3/sealer.go @@ -39,7 +39,7 @@ import ( ) const ( - // staleThreshold is the maximum depth of the acceptable stale but valid ethash solution. + // staleThreshold is the maximum depth of the acceptable stale but valid ethashb3 solution. staleThreshold = 7 ) @@ -48,16 +48,16 @@ var ( errInvalidSealResult = errors.New("invalid or stale proof-of-work solution") ) -// makePoissonFakeDelay uses the ethash.threads value as a mean time (lambda) +// makePoissonFakeDelay uses the ethashb3.threads value as a mean time (lambda) // for a Poisson distribution, returning a random value from // that discrete function. I think a Poisson distribution probably // fairly accurately models real world block times. -// Note that this is a hacky way to use ethash.threads since +// Note that this is a hacky way to use ethashb3.threads since // lower values will yield faster blocks, but it saves having // to add or modify any more code than necessary. -func (ethash *EthashB3) makePoissonFakeDelay() float64 { +func (ethashb3 *EthashB3) makePoissonFakeDelay() float64 { p := distuv.Poisson{ - Lambda: float64(ethash.Threads()), + Lambda: float64(ethashb3.Threads()), Src: exprand.NewSource(uint64(time.Now().UnixNano())), } return p.Rand() @@ -65,18 +65,18 @@ func (ethash *EthashB3) makePoissonFakeDelay() float64 { // Seal implements consensus.Engine, attempting to find a nonce that satisfies // the block's difficulty requirements. -func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { +func (ethashb3 *EthashB3) 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 ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake { + if ethashb3.config.PowMode == ModeFake || ethashb3.config.PowMode == ModeFullFake { header := block.Header() header.Nonce, header.MixDigest = types.BlockNonce{}, common.Hash{} select { case results <- block.WithSeal(header): default: - ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header())) + ethashb3.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethashb3.SealHash(block.Header())) } return nil - } else if ethash.config.PowMode == ModePoissonFake { + } else if ethashb3.config.PowMode == ModePoissonFake { go func(header *types.Header) { // Assign random (but non-zero) values to header nonce and mix. header.Nonce = types.EncodeNonce(uint64(rand.Int63n(math.MaxInt64))) @@ -84,46 +84,46 @@ func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Blo header.MixDigest = common.BytesToHash(b) // Wait some amount of time. - timeout := time.NewTimer(time.Duration(ethash.makePoissonFakeDelay()) * time.Second) + timeout := time.NewTimer(time.Duration(ethashb3.makePoissonFakeDelay()) * time.Second) defer timeout.Stop() select { case <-stop: return - case <-ethash.update: + case <-ethashb3.update: timeout.Stop() - if err := ethash.Seal(chain, block, results, stop); err != nil { - ethash.config.Log.Error("Failed to restart sealing after update", "err", err) + if err := ethashb3.Seal(chain, block, results, stop); err != nil { + ethashb3.config.Log.Error("Failed to restart sealing after update", "err", err) } case <-timeout.C: // Send the results when the timeout expires. select { case results <- block.WithSeal(header): default: - ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header())) + ethashb3.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethashb3.SealHash(block.Header())) } } }(block.Header()) return nil } // If we're running a shared PoW, delegate sealing to it - if ethash.shared != nil { - return ethash.shared.Seal(chain, block, results, stop) + if ethashb3.shared != nil { + return ethashb3.shared.Seal(chain, block, results, stop) } // Create a runner and the multiple search threads it directs abort := make(chan struct{}) - ethash.lock.Lock() - threads := ethash.threads - if ethash.rand == nil { + ethashb3.lock.Lock() + threads := ethashb3.threads + if ethashb3.rand == nil { seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) if err != nil { - ethash.lock.Unlock() + ethashb3.lock.Unlock() return err } - ethash.rand = rand.New(rand.NewSource(seed.Int64())) + ethashb3.rand = rand.New(rand.NewSource(seed.Int64())) } - ethash.lock.Unlock() + ethashb3.lock.Unlock() if threads == 0 { threads = runtime.NumCPU() } @@ -131,8 +131,8 @@ func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Blo threads = 0 // Allows disabling local mining without extra logic around local/remote } // Push new work to remote sealer - if ethash.remote != nil { - ethash.remote.workCh <- &sealTask{block: block, results: results} + if ethashb3.remote != nil { + ethashb3.remote.workCh <- &sealTask{block: block, results: results} } var ( pend sync.WaitGroup @@ -142,8 +142,8 @@ func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Blo pend.Add(1) go func(id int, nonce uint64) { defer pend.Done() - ethash.mine(block, id, nonce, abort, locals) - }(i, uint64(ethash.rand.Int63())) + ethashb3.mine(block, id, nonce, abort, locals) + }(i, uint64(ethashb3.rand.Int63())) } // Wait until sealing is terminated or a nonce is found go func() { @@ -157,14 +157,14 @@ func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Blo select { case results <- result: default: - ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "local", "sealhash", ethash.SealHash(block.Header())) + ethashb3.config.Log.Warn("Sealing result is not read by miner", "mode", "local", "sealhash", ethashb3.SealHash(block.Header())) } close(abort) - case <-ethash.update: + case <-ethashb3.update: // Thread count was changed on user request, restart close(abort) - if err := ethash.Seal(chain, block, results, stop); err != nil { - ethash.config.Log.Error("Failed to restart sealing after update", "err", err) + if err := ethashb3.Seal(chain, block, results, stop); err != nil { + ethashb3.config.Log.Error("Failed to restart sealing after update", "err", err) } } // Wait for all miners to terminate and return the block @@ -175,14 +175,14 @@ func (ethash *EthashB3) Seal(chain consensus.ChainHeaderReader, block *types.Blo // mine is the actual proof-of-work miner that searches for a nonce starting from // seed that results in correct final block difficulty. -func (ethash *EthashB3) mine(block *types.Block, id int, seed uint64, abort chan struct{}, found chan *types.Block) { +func (ethashb3 *EthashB3) 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 = ethash.SealHash(header).Bytes() + hash = ethashb3.SealHash(header).Bytes() target = new(big.Int).Div(two256, header.Difficulty) number = header.Number.Uint64() - dataset = ethash.dataset(number, false) + dataset = ethashb3.dataset(number, false) ) // Start generating random nonces until we abort or find a good one var ( @@ -190,22 +190,22 @@ func (ethash *EthashB3) mine(block *types.Block, id int, seed uint64, abort chan nonce = seed powBuffer = new(big.Int) ) - logger := ethash.config.Log.New("miner", id) - logger.Trace("Started ethash search for new nonces", "seed", seed) + logger := ethashb3.config.Log.New("miner", id) + logger.Trace("Started ethashb3 search for new nonces", "seed", seed) search: for { select { case <-abort: // Mining terminated, update stats and abort logger.Trace("EthashB3 nonce search aborted", "attempts", nonce-seed) - ethash.hashrate.Mark(attempts) + ethashb3.hashrate.Mark(attempts) break search default: // We don't have to update hash rate on every nonce, so update after after 2^X nonces attempts++ if (attempts % (1 << 15)) == 0 { - ethash.hashrate.Mark(attempts) + ethashb3.hashrate.Mark(attempts) attempts = 0 } // Compute the PoW value of this nonce @@ -392,7 +392,7 @@ func (s *remoteSealer) loop() { // result[3], hex encoded block number func (s *remoteSealer) makeWork(block *types.Block) { hash := s.ethash.SealHash(block.Header()) - epochLength := calcEpochLength(block.NumberU64(), s.ethash.config.ECIP1099Block) + epochLength := calcEpochLength(block.NumberU64()) epoch := calcEpoch(block.NumberU64(), epochLength) s.currentWork[0] = hash.Hex() s.currentWork[1] = common.BytesToHash(SeedHash(epoch, epochLength)).Hex() From cc9e24c76d19d1af676fc998f54387b12985e8ad Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 17:58:47 +0000 Subject: [PATCH 09/45] types, params: Added getters and setters for Veldin and fixed some genesis. --- params/alloc_hypra.go | 2 +- params/config_hypra.go | 10 ++++++---- params/genesis_hypra.go | 4 ++-- params/types/coregeth/chain_config.go | 4 ++-- params/types/coregeth/chain_config_configurator.go | 9 +++++++++ params/types/ctypes/configurator_iface.go | 4 ++++ 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/params/alloc_hypra.go b/params/alloc_hypra.go index 10b42d7a3f..6b403fe008 100644 --- a/params/alloc_hypra.go +++ b/params/alloc_hypra.go @@ -1,3 +1,3 @@ package params -var hypraAllocData = "\xf9\x02\xc1\xca\x01\x88\r\u0db3\xa7d\x00\x01\xca\x02\x88\x1b\xc1mgN\xc8\x00\x02\xca\x03\x88)\xa2$\x1a\xf6,\x00\x03\xca\x04\x887\x82\xda\u039d\x90\x00\x04\xca\x05\x88Ec\x91\x82D\xf4\x00\x05\xca\x06\x88SDH5\xecX\x00\x06\xca\a\x88a$\xfe\u94fc\x00\a\xca\b\x88o\x05\xb5\x9d; \x00\b\xca\t\x88|\xe6lP\xe2\x84\x00\t\u07d2\xb2\xbe}\u03c7*Fb\xe3;L\t\xe7\xfc\xe2\xd5\x00\x00\x8b\x01\xbc\xb1:e{&8\x80\x00\x00\u0794\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\r\u0db3\xa7d\x00\x00\xe0\x94\x12\xbb\xad|\x1f>\a\x9a\xf5\xe1\xea\x13te\xe7\x05o\xf3?\x87\x8aO\xf6c5\xad\xe1\x04\xb0\x00\x00\u0794 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x1b\xc1mgN\xc8\x00\x00\xe0\x94%U\u049a\x0eb\xd4Sco\xeaLoe\x13\x15\xdbM\xcd)\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07940\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88)\xa2$\x1a\xf6,\x00\x00\xe0\x942\xbc\xa0[\xe7z~9c\xa4:\xad\xfd\xac-\xeb\x16^@ \x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94=\x16i\x92\x88\xf87\xd4c\x9e\x87\xee=\xa3\x18gUq\xdee\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u0794@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x887\x82\xda\u039d\x90\x00\x00\u0794P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88Ec\x91\x82D\xf4\x00\x00\u0794`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88SDH5\xecX\x00\x00\xe1\x94d\xcf\\A\xe0Prb\xf9\"v\x80\xb8\xa4\x02\xe7{\xeb\xe0u\x8b\x04\"\u028b\n\x00\xa4%\x00\x00\x00\u0794j\xd9v0>3\xffaa\n\x13{\x98\x87\xf3h:U\x19K\x88\xa6\x88\x90k\u0630\x059\u0794p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88a$\xfe\u94fc\x00\x00\u0794\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88o\x05\xb5\x9d; \x00\x00\u150d\x01\xbf1\b\xc7>\x8dX0\nk\xf3\r[N\xa7H\u0783\x8b\x02\x90sV4H\x13\u0640\x00\x00\u0794\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88|\xe6lP\xe2\x84\x00\x00\u0794\xd8\x02h\u0792\x81\x9b\x8b\x99\x01?\xa9\xdd\v\xad?\xacc\xf0\x03\x88\r\u0db3\xa7d\x00\x00\xe0\x94\xf9a2Z\xa3 \xee+\xa6\xce\a\xa0\xf4\xb47t\x8f[\xcf\xe8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" \ No newline at end of file +var HypraAllocData = "\xf9\x02\xc1\xca\x01\x88\r\u0db3\xa7d\x00\x01\xca\x02\x88\x1b\xc1mgN\xc8\x00\x02\xca\x03\x88)\xa2$\x1a\xf6,\x00\x03\xca\x04\x887\x82\xda\u039d\x90\x00\x04\xca\x05\x88Ec\x91\x82D\xf4\x00\x05\xca\x06\x88SDH5\xecX\x00\x06\xca\a\x88a$\xfe\u94fc\x00\a\xca\b\x88o\x05\xb5\x9d; \x00\b\xca\t\x88|\xe6lP\xe2\x84\x00\t\u07d2\xb2\xbe}\u03c7*Fb\xe3;L\t\xe7\xfc\xe2\xd5\x00\x00\x8b\x01\xbc\xb1:e{&8\x80\x00\x00\u0794\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\r\u0db3\xa7d\x00\x00\xe0\x94\x12\xbb\xad|\x1f>\a\x9a\xf5\xe1\xea\x13te\xe7\x05o\xf3?\x87\x8aO\xf6c5\xad\xe1\x04\xb0\x00\x00\u0794 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x1b\xc1mgN\xc8\x00\x00\xe0\x94%U\u049a\x0eb\xd4Sco\xeaLoe\x13\x15\xdbM\xcd)\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07940\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88)\xa2$\x1a\xf6,\x00\x00\xe0\x942\xbc\xa0[\xe7z~9c\xa4:\xad\xfd\xac-\xeb\x16^@ \x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94=\x16i\x92\x88\xf87\xd4c\x9e\x87\xee=\xa3\x18gUq\xdee\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u0794@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x887\x82\xda\u039d\x90\x00\x00\u0794P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88Ec\x91\x82D\xf4\x00\x00\u0794`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88SDH5\xecX\x00\x00\xe1\x94d\xcf\\A\xe0Prb\xf9\"v\x80\xb8\xa4\x02\xe7{\xeb\xe0u\x8b\x04\"\u028b\n\x00\xa4%\x00\x00\x00\u0794j\xd9v0>3\xffaa\n\x13{\x98\x87\xf3h:U\x19K\x88\xa6\x88\x90k\u0630\x059\u0794p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88a$\xfe\u94fc\x00\x00\u0794\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88o\x05\xb5\x9d; \x00\x00\u150d\x01\xbf1\b\xc7>\x8dX0\nk\xf3\r[N\xa7H\u0783\x8b\x02\x90sV4H\x13\u0640\x00\x00\u0794\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88|\xe6lP\xe2\x84\x00\x00\u0794\xd8\x02h\u0792\x81\x9b\x8b\x99\x01?\xa9\xdd\v\xad?\xacc\xf0\x03\x88\r\u0db3\xa7d\x00\x00\xe0\x94\xf9a2Z\xa3 \xee+\xa6\xce\a\xa0\xf4\xb47t\x8f[\xcf\xe8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" diff --git a/params/config_hypra.go b/params/config_hypra.go index dad533ab70..14c5b4e1ea 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -24,12 +24,14 @@ import ( "github.com/ethereum/go-ethereum/params/vars" ) +const HypraChainId = 622277 + var ( // HypraChainConfig is the chain parameters to run a node on the Hypra main network. HypraChainConfig = &coregeth.CoreGethChainConfig{ - NetworkID: 622277, + NetworkID: HypraChainId, EthashB3: new(ctypes.EthashB3Config), - ChainID: big.NewInt(622277), + ChainID: big.NewInt(HypraChainId), SupportedProtocolVersions: vars.DefaultProtocolVersions, EIP2FBlock: big.NewInt(0), @@ -74,9 +76,9 @@ var ( EIP2929FBlock: big.NewInt(5527), // Gas cost increases for state access opcodes EIP2930FBlock: big.NewInt(5527), // Optional access lists - // Veldin fork was used to enable rewards to miners for including uncle blocks. + // Veldin fork was used to enable rewards to miners for including uncle blocks on Hypra network. // Previously overlooked and unrewarded. TODO: use in AccumulateRewards - HIPVeldin: big.NewInt(500_009), + HIPVeldinFBlock: big.NewInt(500_009), // London + shanghai EVM upgrade, aka Gaspar EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds diff --git a/params/genesis_hypra.go b/params/genesis_hypra.go index 0e14a1d613..710908a5e3 100644 --- a/params/genesis_hypra.go +++ b/params/genesis_hypra.go @@ -26,7 +26,7 @@ import ( var HypraGenesisHash = common.HexToHash("0x0fb784d1481f0aa911d21d639641763ca09641413842b35f1d10eb5d208abdf8") -// ClassicGenesisBlock returns the Ethereum Classic genesis block. +// DefaultHypraGenesisBlock returns the Hypra Network genesis block. func DefaultHypraGenesisBlock() *genesisT.Genesis { return &genesisT.Genesis{ Config: HypraChainConfig, @@ -34,7 +34,7 @@ func DefaultHypraGenesisBlock() *genesisT.Genesis { ExtraData: hexutil.MustDecode("0x5465736c6120656e746572732074686520656c65637472696320747275636b20626174746c65206166746572206669727374204379626572747275636b20726f6c6c73206f6666207468652070726f64756374696f6e206c696e65"), GasLimit: 50000, Difficulty: big.NewInt(9_035_329), - Alloc: genesisT.DecodePreAlloc(hypraAllocData), + Alloc: genesisT.DecodePreAlloc(HypraAllocData), Timestamp: 1689703500, } } diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index c147400be8..a7fff8ef50 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -269,9 +269,9 @@ type CoreGethChainConfig struct { Lyra2NonceTransitionBlock *big.Int `json:"lyra2NonceTransitionBlock,omitempty"` - // Veldin fork was used to enable rewards to miners for including uncle blocks. + // Veldin fork was used to enable rewards to miners for including uncle blocks on Hypra network. // Previously overlooked and unrewarded. - HIPVeldin *big.Int `json:"hipveldin,omitempty"` + HIPVeldinFBlock *big.Int `json:"hipveldinfblock,omitempty"` } // String implements the fmt.Stringer interface. diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index 9fbfd42fad..df552a8ec3 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -1313,3 +1313,12 @@ func (c *CoreGethChainConfig) SetLyra2NonceTransition(n *uint64) error { return nil } + +func (c *CoreGethChainConfig) GetHIPVeldinTransition() *uint64 { + return bigNewU64(c.HIPVeldinFBlock) +} + +func (c *CoreGethChainConfig) SetHIPVeldinTransition(n *uint64) error { + c.HIPVeldinFBlock = setBig(c.HIPVeldinFBlock, n) + return nil +} diff --git a/params/types/ctypes/configurator_iface.go b/params/types/ctypes/configurator_iface.go index 5780ae02d1..3e5e0f2835 100644 --- a/params/types/ctypes/configurator_iface.go +++ b/params/types/ctypes/configurator_iface.go @@ -231,6 +231,10 @@ type ProtocolSpecifier interface { // EIP6780 - SELFDESTRUCT only in same transaction - https://eips.ethereum.org/EIPS/eip-6780 GetEIP6780TransitionTime() *uint64 SetEIP6780TransitionTime(n *uint64) error + + // Hypra Network Specific Veldin Fork for uncle rewards fix + GetHIPVeldinTransition() *uint64 + SetHIPVeldinTransition(n *uint64) error } type Forker interface { From 48ad2b9654cc51779c4e97a14ed90ef0e79528a4 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 18:30:59 +0000 Subject: [PATCH 10/45] type: Add veldin? --- params/types/goethereum/goethereum.go | 1 + params/types/goethereum/goethereum_configurator.go | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/params/types/goethereum/goethereum.go b/params/types/goethereum/goethereum.go index b67fd314d1..53dd23573c 100644 --- a/params/types/goethereum/goethereum.go +++ b/params/types/goethereum/goethereum.go @@ -87,6 +87,7 @@ type ChainConfig struct { // Various consensus engines Ethash *ctypes.EthashConfig `json:"ethash,omitempty"` + EthashB3 *ctypes.EthashConfig `json:"ethashb3,omitempty"` Clique *ctypes.CliqueConfig `json:"clique,omitempty"` Lyra2 *ctypes.Lyra2Config `json:"lyra2,omitempty"` IsDevMode bool `json:"isDev,omitempty"` diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index e4e8845a63..743db8ceb9 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -1156,3 +1156,11 @@ func (c *ChainConfig) SetLyra2NonceTransition(n *uint64) error { return nil } + +func (c *ChainConfig) GetHIPVeldinTransition() *uint64 { + return nil +} + +func (c *ChainConfig) SetHIPVeldinTransition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} From 10c05c2aed8068c81827f5353eccc81a079b110c Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 18:46:41 +0000 Subject: [PATCH 11/45] gensisT: Veldin needed to be defined here? --- params/types/genesisT/genesis.go | 8 ++++++++ params/types/goethereum/goethereum.go | 10 +++++----- params/types/goethereum/goethereum_configurator.go | 14 +++++++++++++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/params/types/genesisT/genesis.go b/params/types/genesisT/genesis.go index be6a21e996..376360437d 100644 --- a/params/types/genesisT/genesis.go +++ b/params/types/genesisT/genesis.go @@ -1046,6 +1046,14 @@ func (g *Genesis) SetLyra2NonceTransition(n *uint64) error { return g.Config.SetLyra2NonceTransition(n) } +func (g *Genesis) GetHIPVeldinTransition() *uint64 { + return g.Config.GetHIPVeldinTransition() +} + +func (g *Genesis) SetHIPVeldinTransition(n uint64) error { + return g.Config.SetHIPVeldinTransition(n) +} + func (g *Genesis) String() string { j, _ := json.MarshalIndent(g, "", " ") return "Genesis: " + string(j) diff --git a/params/types/goethereum/goethereum.go b/params/types/goethereum/goethereum.go index 53dd23573c..15610ea709 100644 --- a/params/types/goethereum/goethereum.go +++ b/params/types/goethereum/goethereum.go @@ -86,11 +86,11 @@ type ChainConfig struct { EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated) // Various consensus engines - Ethash *ctypes.EthashConfig `json:"ethash,omitempty"` - EthashB3 *ctypes.EthashConfig `json:"ethashb3,omitempty"` - Clique *ctypes.CliqueConfig `json:"clique,omitempty"` - Lyra2 *ctypes.Lyra2Config `json:"lyra2,omitempty"` - IsDevMode bool `json:"isDev,omitempty"` + Ethash *ctypes.EthashConfig `json:"ethash,omitempty"` + EthashB3 *ctypes.EthashB3Config `json:"ethashb3,omitempty"` + Clique *ctypes.CliqueConfig `json:"clique,omitempty"` + Lyra2 *ctypes.Lyra2Config `json:"lyra2,omitempty"` + IsDevMode bool `json:"isDev,omitempty"` // NOTE: These are not included in this type upstream. TrustedCheckpoint *ctypes.TrustedCheckpoint `json:"trustedCheckpoint"` diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index 743db8ceb9..eb23417c64 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -752,6 +752,9 @@ func (c *ChainConfig) GetConsensusEngineType() ctypes.ConsensusEngineT { if c.Lyra2 != nil { return ctypes.ConsensusEngineT_Lyra2 } + if c.EthashB3 != nil { + return ctypes.ConsensusEngineT_EthashB3 + } return ctypes.ConsensusEngineT_Ethash } @@ -759,15 +762,24 @@ func (c *ChainConfig) MustSetConsensusEngineType(t ctypes.ConsensusEngineT) erro switch t { case ctypes.ConsensusEngineT_Ethash: c.Ethash = new(ctypes.EthashConfig) + c.EthashB3 = nil + c.Clique = nil + return nil + case ctypes.ConsensusEngineT_EthashB3: + c.EthashB3 = new(ctypes.EthashB3Config) + c.Lyra2 = nil + c.Ethash = nil c.Clique = nil return nil case ctypes.ConsensusEngineT_Clique: c.Clique = new(ctypes.CliqueConfig) c.Ethash = nil + c.EthashB3 = nil return nil case ctypes.ConsensusEngineT_Lyra2: c.Lyra2 = new(ctypes.Lyra2Config) c.Ethash = nil + c.EthashB3 = nil c.Clique = nil return nil default: @@ -1161,6 +1173,6 @@ func (c *ChainConfig) GetHIPVeldinTransition() *uint64 { return nil } -func (c *ChainConfig) SetHIPVeldinTransition(n *uint64) error { +func (c *ChainConfig) SetHIPVeldinTransition(_ *uint64) error { return ctypes.ErrUnsupportedConfigNoop } From 5a95422d047b6e65a765451c505dcba85123c82f Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 19:07:40 +0000 Subject: [PATCH 12/45] params: fix *uint64 to uint64 --- params/types/genesisT/genesis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/types/genesisT/genesis.go b/params/types/genesisT/genesis.go index 376360437d..9cc430fd23 100644 --- a/params/types/genesisT/genesis.go +++ b/params/types/genesisT/genesis.go @@ -1050,7 +1050,7 @@ func (g *Genesis) GetHIPVeldinTransition() *uint64 { return g.Config.GetHIPVeldinTransition() } -func (g *Genesis) SetHIPVeldinTransition(n uint64) error { +func (g *Genesis) SetHIPVeldinTransition(n *uint64) error { return g.Config.SetHIPVeldinTransition(n) } From 6bea66a49307fc981e84992cc3d18f4711cbc4a5 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 21:58:15 +0000 Subject: [PATCH 13/45] ethconfig: Added ethashb3 to consensus creation Refactored CreateConsensusEngine --- cmd/utils/flags.go | 72 +++++++++++++++++++++++++----------- eth/ethconfig/config.go | 81 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 22 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 80bb6b3912..8b54c7e744 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -24,6 +24,9 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/ethashb3" + "github.com/ethereum/go-ethereum/params/types/ctypes" "math" "math/big" "net" @@ -2544,30 +2547,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh gspec = MakeGenesis(ctx) chainDb = MakeChainDatabase(ctx, stack, readonly) ) - cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec) - if err != nil { - Fatalf("%v", err) - } - ethashConfig := ethconfig.Defaults.Ethash - - // ETC-specific configuration: ECIP1099 modifies the original Ethash algo, doubling the epoch size. - if gspec != nil && gspec.Config != nil { - ethashConfig.ECIP1099Block = gspec.GetEthashECIP1099Transition() // This will panic if the genesis config field is not nil. - } - - var lyra2Config *lyra2.Config - if ctx.Bool(MintMeFlag.Name) { - lyra2Config = &lyra2.Config{} - } - // Toggle PoW modes at user request. - if ctx.Bool(FakePoWFlag.Name) { - ethashConfig.PowMode = ethash.ModeFake - } else if ctx.Bool(FakePoWPoissonFlag.Name) { - ethashConfig.PowMode = ethash.ModePoissonFake - } + engine := CreateConsensusEngine(ctx, stack, gspec, chainDb) - engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, lyra2Config, nil, false, chainDb) if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } @@ -2608,6 +2590,52 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh return chain, chainDb } +// Create a Consensus Engine for a specific chains config +func CreateConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Genesis, chainDb ethdb.Database) (engine consensus.Engine) { + switch gspec.GetConsensusEngineType() { + case ctypes.ConsensusEngineT_Ethash: + ethashConfig := ethconfig.Defaults.Ethash + if gspec != nil && gspec.Config != nil { + ethashConfig.ECIP1099Block = gspec.GetEthashECIP1099Transition() // This will panic if the genesis config field is not nil. + } + if ctx.Bool(FakePoWFlag.Name) { + ethashConfig.PowMode = ethash.ModeFake + } else if ctx.Bool(FakePoWPoissonFlag.Name) { + ethashConfig.PowMode = ethash.ModePoissonFake + } + engine = ethconfig.CreateConsensusEngineEthash(stack, ðashConfig, nil, false) + break + + case ctypes.ConsensusEngineT_EthashB3: + ethashb3Config := ethconfig.Defaults.EthashB3 + if ctx.Bool(FakePoWFlag.Name) { + ethashb3Config.PowMode = ethashb3.ModeFake + } else if ctx.Bool(FakePoWPoissonFlag.Name) { + ethashb3Config.PowMode = ethashb3.ModePoissonFake + } + engine = ethconfig.CreateConsensusEngineEthashB3(stack, ðashb3Config, nil, false) + break + + case ctypes.ConsensusEngineT_Clique: + cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec) + if err != nil { + Fatalf("%v", err) + } + engine = ethconfig.CreateConsensusEngineClique(cliqueConfig, chainDb) + break + + case ctypes.ConsensusEngineT_Lyra2: + var lyra2Config *lyra2.Config + if ctx.Bool(MintMeFlag.Name) { + lyra2Config = &lyra2.Config{} + } + engine = ethconfig.CreateConsensusEngineLyra2(lyra2Config, nil, false) + break + } + + return engine +} + // MakeConsolePreloads retrieves the absolute paths for the console JavaScript // scripts to preload before starting. func MakeConsolePreloads(ctx *cli.Context) []string { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 5f8190ecac..915be20cdc 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -18,6 +18,7 @@ package ethconfig import ( + "github.com/ethereum/go-ethereum/consensus/ethashb3" "os" "os/user" "path/filepath" @@ -180,6 +181,9 @@ type Config struct { // Ethash options Ethash ethash.Config + // EthashB3 options + EthashB3 ethashb3.Config + // Transaction pool options TxPool legacypool.Config BlobPool blobpool.Config @@ -276,3 +280,80 @@ func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, clique return beacon.New(engine) } + +func CreateConsensusEngineEthash(stack *node.Node, ethashConfig *ethash.Config, notify []string, noverify bool) (engine consensus.Engine) { + switch ethashConfig.PowMode { + case ethash.ModeFake: + log.Warn("Ethash used in fake mode") + engine = ethash.NewFaker() + case ethash.ModeTest: + log.Warn("Ethash used in test mode") + engine = ethash.NewTester(nil, noverify) + case ethash.ModeShared: + log.Warn("Ethash used in shared mode") + engine = ethash.NewShared() + case ethash.ModePoissonFake: + log.Warn("Ethash used in fake Poisson mode") + engine = ethash.NewPoissonFaker() + default: + engine = ethash.New(ethash.Config{ + PowMode: ethashConfig.PowMode, + CacheDir: stack.ResolvePath(ethashConfig.CacheDir), + CachesInMem: ethashConfig.CachesInMem, + CachesOnDisk: ethashConfig.CachesOnDisk, + CachesLockMmap: ethashConfig.CachesLockMmap, + DatasetDir: ethashConfig.DatasetDir, + DatasetsInMem: ethashConfig.DatasetsInMem, + DatasetsOnDisk: ethashConfig.DatasetsOnDisk, + DatasetsLockMmap: ethashConfig.DatasetsLockMmap, + NotifyFull: ethashConfig.NotifyFull, + ECIP1099Block: ethashConfig.ECIP1099Block, + }, notify, noverify) + engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining + } + engine = beacon.New(engine) + return +} + +func CreateConsensusEngineEthashB3(stack *node.Node, ethashb3Config *ethashb3.Config, notify []string, noverify bool) (engine consensus.Engine) { + switch ethashb3Config.PowMode { + case ethashb3.ModeFake: + log.Warn("EthashB3 used in fake mode") + engine = ethashb3.NewFaker() + case ethashb3.ModeTest: + log.Warn("EthashB3 used in test mode") + engine = ethashb3.NewTester(nil, noverify) + case ethashb3.ModeShared: + log.Warn("EthashB3 used in shared mode") + engine = ethashb3.NewShared() + case ethashb3.ModePoissonFake: + log.Warn("EthashB3 used in fake Poisson mode") + engine = ethashb3.NewPoissonFaker() + default: + engine = ethashb3.New(ethashb3.Config{ + PowMode: ethashb3Config.PowMode, + CacheDir: stack.ResolvePath(ethashb3Config.CacheDir), + CachesInMem: ethashb3Config.CachesInMem, + CachesOnDisk: ethashb3Config.CachesOnDisk, + CachesLockMmap: ethashb3Config.CachesLockMmap, + DatasetDir: ethashb3Config.DatasetDir, + DatasetsInMem: ethashb3Config.DatasetsInMem, + DatasetsOnDisk: ethashb3Config.DatasetsOnDisk, + DatasetsLockMmap: ethashb3Config.DatasetsLockMmap, + NotifyFull: ethashb3Config.NotifyFull, + ECIP1099Block: ethashb3Config.ECIP1099Block, + }, notify, noverify) + engine.(*ethashb3.EthashB3).SetThreads(-1) // Disable CPU mining + } + return +} + +func CreateConsensusEngineClique(cliqueConfig *ctypes.CliqueConfig, db ethdb.Database) (engine consensus.Engine) { + engine = clique.New(cliqueConfig, db) + return +} + +func CreateConsensusEngineLyra2(lyra2Config *lyra2.Config, notify []string, noverify bool) (engine consensus.Engine) { + engine = lyra2.New(lyra2Config, notify, noverify) + return +} From 0c9aa5f1300e39db6891544bc3d8e1e39af831fc Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 22:15:03 +0000 Subject: [PATCH 14/45] ethashb3: does not support ECIP1099Block --- consensus/ethashb3/ethash.go | 2 -- eth/ethconfig/config.go | 1 - 2 files changed, 3 deletions(-) diff --git a/consensus/ethashb3/ethash.go b/consensus/ethashb3/ethash.go index e8cad539c4..a77fd66d36 100644 --- a/consensus/ethashb3/ethash.go +++ b/consensus/ethashb3/ethash.go @@ -555,8 +555,6 @@ type Config struct { NotifyFull bool Log log.Logger `toml:"-"` - // ECIP-1099 - ECIP1099Block *uint64 `toml:"-"` } // EthashB3 is a consensus engine based on proof-of-work implementing the ethashb3 diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 915be20cdc..8a891f31c8 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -341,7 +341,6 @@ func CreateConsensusEngineEthashB3(stack *node.Node, ethashb3Config *ethashb3.Co DatasetsOnDisk: ethashb3Config.DatasetsOnDisk, DatasetsLockMmap: ethashb3Config.DatasetsLockMmap, NotifyFull: ethashb3Config.NotifyFull, - ECIP1099Block: ethashb3Config.ECIP1099Block, }, notify, noverify) engine.(*ethashb3.EthashB3).SetThreads(-1) // Disable CPU mining } From 6248090fc94437a2dccd3b0cf58bae0beed38845 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 23:38:47 +0000 Subject: [PATCH 15/45] ethconfig: added EthashB3 defaults --- eth/ethconfig/config.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 8a891f31c8..5f00f48ffc 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -76,6 +76,15 @@ var Defaults = Config{ DatasetsOnDisk: 2, DatasetsLockMmap: false, }, + EthashB3: ethashb3.Config{ + CacheDir: "ethashb3", + CachesInMem: 2, + CachesOnDisk: 3, + CachesLockMmap: false, + DatasetsInMem: 1, + DatasetsOnDisk: 2, + DatasetsLockMmap: false, + }, NetworkId: vars.DefaultNetworkID, ProtocolVersions: vars.DefaultProtocolVersions, TxLookupLimit: 2350000, @@ -105,15 +114,19 @@ func init() { } if runtime.GOOS == "darwin" { Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "Ethash") + Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "EthashB3") } else if runtime.GOOS == "windows" { localappdata := os.Getenv("LOCALAPPDATA") if localappdata != "" { Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "Ethash") + Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "EthashB3") } else { Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "Ethash") + Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "EthashB3") } } else { Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethash") + Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethashb3") } } From e23deb805c36be88d3f990d79a39e198d7a339e6 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 8 Feb 2024 23:41:31 +0000 Subject: [PATCH 16/45] ethconfig: accidentally overwrote the ethash defaults with ethashb3 --- eth/ethconfig/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 5f00f48ffc..6028148ef9 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -114,19 +114,19 @@ func init() { } if runtime.GOOS == "darwin" { Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "Ethash") - Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "EthashB3") + Defaults.EthashB3.DatasetDir = filepath.Join(home, "Library", "EthashB3") } else if runtime.GOOS == "windows" { localappdata := os.Getenv("LOCALAPPDATA") if localappdata != "" { Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "Ethash") - Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "EthashB3") + Defaults.EthashB3.DatasetDir = filepath.Join(localappdata, "EthashB3") } else { Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "Ethash") - Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "EthashB3") + Defaults.EthashB3.DatasetDir = filepath.Join(home, "AppData", "Local", "EthashB3") } } else { Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethash") - Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethashb3") + Defaults.EthashB3.DatasetDir = filepath.Join(home, ".ethashb3") } } From 1dc0effc6e7e392c15fc98e13c83f44a76a30530 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 11 Feb 2024 00:41:41 +0000 Subject: [PATCH 17/45] ethconfig: Added Ethashb3 to CreateCensensusEngine. Defered to CreateCensensusEngineEthashB3 --- eth/backend.go | 3 ++- eth/ethconfig/config.go | 4 +++- les/client.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index b9af5f4762..dfe6e99b9b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -143,6 +143,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } // Transfer mining-related config to the ethash config. ethashConfig := config.Ethash + ethashb3Config := config.EthashB3 ethashConfig.NotifyFull = config.Miner.NotifyFull if config.Genesis != nil && config.Genesis.Config != nil { @@ -161,7 +162,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } } - engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, cliqueConfig, lyra2Config, config.Miner.Notify, config.Miner.Noverify, chainDb) + engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, ðashb3Config, cliqueConfig, lyra2Config, config.Miner.Notify, config.Miner.Noverify, chainDb) eth := &Ethereum{ config: config, diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 6028148ef9..bb605b3719 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -252,13 +252,15 @@ type Config struct { } // CreateConsensusEngine creates a consensus engine for the given chain configuration. -func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, cliqueConfig *ctypes.CliqueConfig, lyra2Config *lyra2.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { +func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, ethashb3Config *ethashb3.Config, cliqueConfig *ctypes.CliqueConfig, lyra2Config *lyra2.Config, 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 lyra2Config != nil { engine = lyra2.New(lyra2Config, notify, noverify) + } else if ethashb3Config != nil { + engine = CreateConsensusEngineEthashB3(stack, ethashb3Config, notify, noverify) } else { switch ethashConfig.PowMode { case ethash.ModeFake: diff --git a/les/client.go b/les/client.go index 945b5db65b..ed62503c44 100644 --- a/les/client.go +++ b/les/client.go @@ -150,7 +150,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, cliqueConfig, lyra2Config, nil, false, chainDb), + engine: ethconfig.CreateConsensusEngine(stack, &config.Ethash, &config.EthashB3, cliqueConfig, lyra2Config, nil, false, chainDb), bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: core.NewBloomIndexer(chainDb, vars.BloomBitsBlocksClient, vars.HelperTrieConfirmations), p2pServer: stack.Server(), From 9e3b3757c80f083e05badc5e512587c598eb8a80 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 11 Feb 2024 00:42:29 +0000 Subject: [PATCH 18/45] params: Fixed getting Scheduled rewards support for ethashb3 --- params/types/coregeth/chain_config_configurator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index df552a8ec3..7d08d27e83 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -1253,7 +1253,8 @@ func (c *CoreGethChainConfig) SetEthashDifficultyBombDelaySchedule(m ctypes.Uint } func (c *CoreGethChainConfig) GetEthashBlockRewardSchedule() ctypes.Uint64BigMapEncodesHex { - if c.GetConsensusEngineType() != ctypes.ConsensusEngineT_Ethash { + engineType := c.GetConsensusEngineType() + if engineType == ctypes.ConsensusEngineT_Ethash || engineType == ctypes.ConsensusEngineT_EthashB3 { return nil } return c.BlockRewardSchedule From e7a5f5f0833ddd9bfd4c2c1dd5d628c014ff10bd Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 11 Feb 2024 02:22:36 +0000 Subject: [PATCH 19/45] params, ethashb3: Added rewards and fixed ethashb3 dynamic difficulty --- consensus/ethash/consensus.go | 2 +- consensus/ethashb3/algorithm.go | 2 +- consensus/ethashb3/consensus.go | 42 ++++++++---- consensus/ethashb3/difficulty.go | 12 +--- params/config_hypra.go | 7 ++ params/mutations/rewards.go | 13 +++- params/mutations/rewards_hypra.go | 65 +++++++++++++++++++ .../coregeth/chain_config_configurator.go | 6 +- 8 files changed, 121 insertions(+), 28 deletions(-) create mode 100644 params/mutations/rewards_hypra.go diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 4310c813d2..b922a6d952 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -570,7 +570,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H // Finalize implements consensus.Engine, accumulating the block and uncle rewards. func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Accumulate any block and uncle rewards and commit the final state root - mutations.AccumulateRewards(chain.Config(), state, header, uncles) + mutations.AccumulateRewards(chain.Config(), state, header, uncles, txs) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and diff --git a/consensus/ethashb3/algorithm.go b/consensus/ethashb3/algorithm.go index 2d649c6b51..fe8b06aaec 100644 --- a/consensus/ethashb3/algorithm.go +++ b/consensus/ethashb3/algorithm.go @@ -1,7 +1,7 @@ // 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 +// The go-ethereum library is free software: you can redistribute it and/or modifadminy // 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. diff --git a/consensus/ethashb3/consensus.go b/consensus/ethashb3/consensus.go index bb01f37d3c..06e9558eab 100644 --- a/consensus/ethashb3/consensus.go +++ b/consensus/ethashb3/consensus.go @@ -44,6 +44,7 @@ import ( var ( maxUncles = 2 // Maximum number of uncles allowed in a single block allowedFutureBlockTime = 7 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks + MinimumDifficulty = big.NewInt(1_002_317) ) // Various error messages to mark blocks invalid. These should be private to @@ -315,11 +316,6 @@ func CalcDifficulty(config ctypes.ChainConfigurator, time uint64, parent *types. next := new(big.Int).Add(parent.Number, big1) out := new(big.Int) - // TODO (meowbits): do we need this? - // if config.IsEnabled(config.GetEthashTerminalTotalDifficulty, next) { - // return big.NewInt(1) - // } - // ADJUSTMENT algorithms if config.IsEnabled(config.GetEthashEIP100BTransition, next) { // https://github.com/ethereum/EIPs/issues/100 @@ -327,16 +323,38 @@ func CalcDifficulty(config ctypes.ChainConfigurator, time uint64, parent *types. // diff = (parent_diff + // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) // ) + 2^(periodCount - 2) - out.Div(parent_time_delta(time, parent), big.NewInt(6)) + 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) // 9 + x.Sub(bigTime, bigParentTime) + x.Div(x, big.NewInt(6)) if parent.UncleHash == types.EmptyUncleHash { - out.Sub(big1, out) + x.Sub(big1, x) } else { - out.Sub(big2, out) + x.Sub(big2, x) } - out.Set(math.BigMax(out, bigMinus99)) - out.Mul(parent_diff_over_dbd(parent), out) - out.Add(out, parent.Difficulty) + + // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) + if x.Cmp(bigMinus99) < 0 { + x.Set(bigMinus99) + } + + // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) + y.Div(parent.Difficulty, vars.DifficultyBoundDivisor) + x.Mul(y, x) + x.Add(parent.Difficulty, x) + + // minimum difficulty can ever be (before exponential factor) + if x.Cmp(MinimumDifficulty) < 0 { + x.Set(MinimumDifficulty) + } + + return x } else if config.IsEnabled(config.GetEIP2Transition, next) { // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md // algorithm: @@ -463,7 +481,7 @@ func (ethashb3 *EthashB3) Prepare(chain consensus.ChainHeaderReader, header *typ // Finalize implements consensus.Engine, accumulating the block and uncle rewards. func (ethashb3 *EthashB3) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Accumulate any block and uncle rewards and commit the final state root - mutations.AccumulateRewards(chain.Config(), state, header, uncles) + mutations.AccumulateRewards(chain.Config(), state, header, uncles, txs) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and diff --git a/consensus/ethashb3/difficulty.go b/consensus/ethashb3/difficulty.go index eb272e94ce..9a847363f9 100644 --- a/consensus/ethashb3/difficulty.go +++ b/consensus/ethashb3/difficulty.go @@ -134,7 +134,6 @@ func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int { func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { // Note, the calculations below looks at the parent number, which is 1 below // the block number. Thus we remove one from the delay given - bombDelayFromParent := bombDelay.Uint64() - 1 return func(time uint64, parent *types.Header) *big.Int { /* https://github.com/ethereum/EIPs/issues/100 @@ -176,16 +175,7 @@ func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent * if y.LtUint64(minimumDifficulty) { y.SetUint64(minimumDifficulty) } - // calculate a fake block number for the ice-age delay - // Specification: https://eips.ethereum.org/EIPS/eip-1234 - var pNum = parent.Number.Uint64() - if pNum >= bombDelayFromParent { - if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { - z.SetOne() - z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) - y.Add(z, y) - } - } + return y.ToBig() } } diff --git a/params/config_hypra.go b/params/config_hypra.go index 14c5b4e1ea..30604e3fe2 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -102,6 +102,13 @@ var ( 40_725_107: big.NewInt(1 * vars.Ether), }, + TrustedCheckpoint: &ctypes.TrustedCheckpoint{ + BloomRoot: common.HexToHash("0xb09a3dc1215903dc757dd83c960c6dd77ec508e03c185b16df62af069d197fc3"), + CHTRoot: common.HexToHash("0x21f6a69cbd097bd2c1d250ed7144888e483d46105b66a99a68e4847c99a863cd"), + SectionHead: common.HexToHash("0x2461cbf15f92264332e09ba8a9d6b9106c12b3cf0e7d7bfff78483c1b271e902"), + SectionIndex: 43, + }, + RequireBlockHashes: map[uint64]common.Hash{ 156_000: common.HexToHash("0x2a27bec023108c5f650cb0c9b7aaae7e7fdeefbeb3cd14a8390bb0957043aca2"), 512_000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), diff --git a/params/mutations/rewards.go b/params/mutations/rewards.go index ea5b26e785..472182b52b 100644 --- a/params/mutations/rewards.go +++ b/params/mutations/rewards.go @@ -62,8 +62,17 @@ func GetRewards(config ctypes.ChainConfigurator, header *types.Header, uncles [] // AccumulateRewards credits the coinbase of the given block with the mining // reward. The coinbase of each uncle block is also rewarded. -func AccumulateRewards(config ctypes.ChainConfigurator, state *state.StateDB, header *types.Header, uncles []*types.Header) { - minerReward, uncleRewards := GetRewards(config, header, uncles) +func AccumulateRewards(config ctypes.ChainConfigurator, state *state.StateDB, header *types.Header, uncles []*types.Header, txs []*types.Transaction) { + var minerReward *big.Int + var uncleRewards []*big.Int + + if config.GetChainID().Uint64() == params.HypraChainId { + // Hypra has a unique miner reward system which requires the translations. + minerReward, uncleRewards = GetRewardsHypra(config, header, uncles, txs) + } else { + minerReward, uncleRewards = GetRewards(config, header, uncles) + } + for i, uncle := range uncles { state.AddBalance(uncle.Coinbase, uncleRewards[i]) } diff --git a/params/mutations/rewards_hypra.go b/params/mutations/rewards_hypra.go new file mode 100644 index 0000000000..0937b875d4 --- /dev/null +++ b/params/mutations/rewards_hypra.go @@ -0,0 +1,65 @@ +// Copyright 2019 The multi-geth Authors +// This file is part of the multi-geth library. +// +// The multi-geth 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 multi-geth 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 multi-geth library. If not, see . +package mutations + +import ( + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params/types/ctypes" + "math/big" +) + +var ( + UncleBlockReward = big.NewInt(100_000_000_000_000_000) +) + +func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncles []*types.Header, txs []*types.Transaction) (*big.Int, []*big.Int) { + // Select the correct block minerReward based on chain progression + blockReward := ctypes.EthashBlockReward(config, header.Number) + + minerReward := new(big.Int).Set(blockReward) + uncleReward := new(big.Int).Set(UncleBlockReward) + uncleCount := new(big.Int).SetUint64(uint64(len(uncles))) + blockFeeReward := new(big.Int) + + // Collect the fee for all transactions. + for _, tx := range txs { + gas := new(big.Int).SetUint64(tx.Gas()) + gasPrice := tx.GasPrice() + blockFeeReward.Add(blockFeeReward, new(big.Int).Mul(gas, gasPrice)) + } + + if len(uncles) == 0 { // If no uncles, the miner gets the entire block fee. + minerReward.Add(minerReward, blockFeeReward) + } else if config.IsEnabled(config.GetEIP2718Transition, header.Number) { // During Berlin block, each miner and uncles are rewarded the block fee. + uncleReward.Add(uncleReward, blockFeeReward) + minerReward.Add(minerReward, blockFeeReward) + } else if config.IsEnabled(config.GetEthashHomesteadTransition, header.Number) { // Until Berlin block, Miners and Uncles are rewarded for the amount of uncles generated. + uncleReward.Add(uncleReward, blockFeeReward) + uncleReward.Mul(uncleReward, uncleCount) + minerReward.Add(minerReward, uncleReward) + } + + uncleRewards := make([]*big.Int, len(uncles)) + for i, _ := range uncles { + uncleRewards[i].Set(uncleReward) + + if config.IsEnabled(config.GetHIPVeldinTransition, header.Number) { + minerReward.Add(minerReward, uncleReward) + } + } + + return minerReward, uncleRewards +} diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index 7d08d27e83..aa95175041 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -727,6 +727,9 @@ func (c *CoreGethChainConfig) GetConsensusEngineType() ctypes.ConsensusEngineT { if c.Ethash != nil { return ctypes.ConsensusEngineT_Ethash } + if c.EthashB3 != nil { + return ctypes.ConsensusEngineT_EthashB3 + } if c.Clique != nil { return ctypes.ConsensusEngineT_Clique } @@ -1156,7 +1159,8 @@ func (c *CoreGethChainConfig) SetEthashECIP1017EraRounds(n *uint64) error { } func (c *CoreGethChainConfig) GetEthashEIP100BTransition() *uint64 { - if c.GetConsensusEngineType() != ctypes.ConsensusEngineT_Ethash { + engineType := c.GetConsensusEngineType() + if !(engineType == ctypes.ConsensusEngineT_Ethash || engineType == ctypes.ConsensusEngineT_EthashB3) { return nil } return bigNewU64(c.EIP100FBlock) From 6836fcc39051120d6f496d2fb3666f66b01fc94c Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 11 Feb 2024 02:37:55 +0000 Subject: [PATCH 20/45] params: Add ethashb3 to mustset --- params/types/coregeth/chain_config_configurator.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index aa95175041..014df33ecb 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -743,15 +743,26 @@ func (c *CoreGethChainConfig) MustSetConsensusEngineType(t ctypes.ConsensusEngin switch t { case ctypes.ConsensusEngineT_Ethash: c.Ethash = new(ctypes.EthashConfig) + c.EthashB3 = nil c.Clique = nil + c.Lyra2 = nil + return nil + case ctypes.ConsensusEngineT_EthashB3: + c.EthashB3 = new(ctypes.EthashB3Config) + c.Ethash = nil + c.Clique = nil + c.Lyra2 = nil return nil case ctypes.ConsensusEngineT_Clique: c.Clique = new(ctypes.CliqueConfig) c.Ethash = nil + c.EthashB3 = nil + c.Lyra2 = nil return nil case ctypes.ConsensusEngineT_Lyra2: c.Lyra2 = new(ctypes.Lyra2Config) c.Ethash = nil + c.EthashB3 = nil c.Clique = nil return nil default: @@ -1320,6 +1331,9 @@ func (c *CoreGethChainConfig) SetLyra2NonceTransition(n *uint64) error { } func (c *CoreGethChainConfig) GetHIPVeldinTransition() *uint64 { + if c.GetChainID() == big.NewInt(622277) { + return nil + } return bigNewU64(c.HIPVeldinFBlock) } From 66ac6e4fdc529bf51cd0ec824474576e9e680657 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Mon, 12 Feb 2024 12:33:01 +0000 Subject: [PATCH 21/45] Params: update chainspec and genesis hash test --- params/config_hypra.go | 18 +++++++++++------- params/config_hypra_test.go | 14 ++++++++++++++ params/genesis_hypra.go | 2 +- 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 params/config_hypra_test.go diff --git a/params/config_hypra.go b/params/config_hypra.go index 30604e3fe2..e51667384b 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -38,7 +38,7 @@ var ( EIP7FBlock: big.NewInt(0), // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? // DAOForkSupport isnt in this struct - // DAOForkBlock: big.NewInt(0), + DAOForkBlock: big.NewInt(0), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP160FBlock: big.NewInt(0), @@ -69,6 +69,7 @@ var ( EIP1884FBlock: big.NewInt(5519), EIP2028FBlock: big.NewInt(5519), EIP2200FBlock: big.NewInt(5519), + EIP2384FBlock: big.NewInt(5521), // Berlin EIP2565FBlock: big.NewInt(5527), // ModExp Gas Cost @@ -77,17 +78,20 @@ var ( EIP2930FBlock: big.NewInt(5527), // Optional access lists // Veldin fork was used to enable rewards to miners for including uncle blocks on Hypra network. - // Previously overlooked and unrewarded. TODO: use in AccumulateRewards + // Previously overlooked and unrewarded. HIPVeldinFBlock: big.NewInt(500_009), // London + shanghai EVM upgrade, aka Gaspar - EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds - EIP3541FBlock: big.NewInt(1_600_957), // Reject new contract code starting with the 0xEF byte EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode - - // EIP3651FBlock: big.NewInt(1_600_957), // Warm COINBASE (gas reprice) -- I don't think this was enabled on hypra as part of Gaspar - // EIP1559FBlock: big.NewInt(0), // EIP-1559 transactions are not enabled on Hypra yet -- TODO + EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode + + // London chain upgrades, aka Eudora + EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions are not enabled on Hypra yet + EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) + EIP6049FBlock: big.NewInt(13_524_557), // Deprecate SELFDESTRUCT + EIP3529FBlock: big.NewInt(13_524_557), // Reduction in refunds + EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte // Spiral, aka Shanghai (partially) // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. diff --git a/params/config_hypra_test.go b/params/config_hypra_test.go new file mode 100644 index 0000000000..2fdcbf417c --- /dev/null +++ b/params/config_hypra_test.go @@ -0,0 +1,14 @@ +package params + +import ( + "testing" +) + +// TestGenesisHashHypra tests that HypraGenesisHash is the correct value for the genesis configuration. +func TestGenesisHashHypra(t *testing.T) { + genesis := DefaultHypraGenesisBlock() + block := genesisToBlock(genesis, nil) + if block.Hash() != HypraGenesisHash { + t.Errorf("want: %s, got: %s", HypraGenesisHash.Hex(), block.Hash().Hex()) + } +} diff --git a/params/genesis_hypra.go b/params/genesis_hypra.go index 710908a5e3..b5097df20b 100644 --- a/params/genesis_hypra.go +++ b/params/genesis_hypra.go @@ -32,7 +32,7 @@ func DefaultHypraGenesisBlock() *genesisT.Genesis { Config: HypraChainConfig, Nonce: 4009, ExtraData: hexutil.MustDecode("0x5465736c6120656e746572732074686520656c65637472696320747275636b20626174746c65206166746572206669727374204379626572747275636b20726f6c6c73206f6666207468652070726f64756374696f6e206c696e65"), - GasLimit: 50000, + GasLimit: 50_000, Difficulty: big.NewInt(9_035_329), Alloc: genesisT.DecodePreAlloc(HypraAllocData), Timestamp: 1689703500, From 86a3180c007fa23611eb818bbe339a77252f7d4a Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Mon, 12 Feb 2024 13:06:24 +0000 Subject: [PATCH 22/45] params: correct some EthashB3 forks --- consensus/ethashb3/consensus.go | 12 +++++++++--- params/config_hypra.go | 2 +- params/types/coregeth/chain_config_configurator.go | 9 +++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/consensus/ethashb3/consensus.go b/consensus/ethashb3/consensus.go index 06e9558eab..d4c410351b 100644 --- a/consensus/ethashb3/consensus.go +++ b/consensus/ethashb3/consensus.go @@ -309,6 +309,12 @@ func parent_diff_over_dbd(p *types.Header) *big.Int { return new(big.Int).Div(p.Difficulty, vars.DifficultyBoundDivisor) } +var ( + big5 = big.NewInt(5) + big6 = big.NewInt(6) + big7 = big.NewInt(7) +) + // 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. @@ -332,7 +338,7 @@ func CalcDifficulty(config ctypes.ChainConfigurator, time uint64, parent *types. // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9 x.Sub(bigTime, bigParentTime) - x.Div(x, big.NewInt(6)) + x.Div(x, big6) if parent.UncleHash == types.EmptyUncleHash { x.Sub(big1, x) } else { @@ -361,7 +367,7 @@ func CalcDifficulty(config ctypes.ChainConfigurator, time uint64, parent *types. // diff = (parent_diff + // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) // ) - out.Div(parent_time_delta(time, parent), big.NewInt(5)) + out.Div(parent_time_delta(time, parent), big5) out.Sub(big1, out) out.Set(math.BigMax(out, bigMinus99)) out.Mul(parent_diff_over_dbd(parent), out) @@ -375,7 +381,7 @@ func CalcDifficulty(config ctypes.ChainConfigurator, time uint64, parent *types. // else // parent_diff - (parent_diff // 2048) out.Set(parent.Difficulty) - if parent_time_delta(time, parent).Cmp(vars.DurationLimit) < 0 { + if parent_time_delta(time, parent).Cmp(big7) < 0 { out.Add(out, parent_diff_over_dbd(parent)) } else { out.Sub(out, parent_diff_over_dbd(parent)) diff --git a/params/config_hypra.go b/params/config_hypra.go index e51667384b..7674860baf 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -38,7 +38,7 @@ var ( EIP7FBlock: big.NewInt(0), // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? // DAOForkSupport isnt in this struct - DAOForkBlock: big.NewInt(0), + // DAOForkBlock: big.NewInt(0), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP160FBlock: big.NewInt(0), diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index 014df33ecb..306beebb80 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -839,7 +839,8 @@ func (c *CoreGethChainConfig) SetEthashDurationLimit(i *big.Int) error { } func (c *CoreGethChainConfig) GetEthashHomesteadTransition() *uint64 { - if c.GetConsensusEngineType() != ctypes.ConsensusEngineT_Ethash { + engine := c.GetConsensusEngineType() + if engine != ctypes.ConsensusEngineT_Ethash && engine != ctypes.ConsensusEngineT_EthashB3 { return nil } if c.EIP2FBlock == nil || c.EIP7FBlock == nil { @@ -1178,7 +1179,7 @@ func (c *CoreGethChainConfig) GetEthashEIP100BTransition() *uint64 { } func (c *CoreGethChainConfig) SetEthashEIP100BTransition(n *uint64) error { - if c.Ethash == nil { + if c.Ethash == nil || c.EthashB3 == nil { return ctypes.ErrUnsupportedConfigFatal } c.EIP100FBlock = setBig(c.EIP100FBlock, n) @@ -1276,7 +1277,7 @@ func (c *CoreGethChainConfig) GetEthashBlockRewardSchedule() ctypes.Uint64BigMap } func (c *CoreGethChainConfig) SetEthashBlockRewardSchedule(m ctypes.Uint64BigMapEncodesHex) error { - if c.Ethash == nil { + if c.Ethash == nil || c.EthashB3 == nil { return ctypes.ErrUnsupportedConfigFatal } c.BlockRewardSchedule = m @@ -1331,7 +1332,7 @@ func (c *CoreGethChainConfig) SetLyra2NonceTransition(n *uint64) error { } func (c *CoreGethChainConfig) GetHIPVeldinTransition() *uint64 { - if c.GetChainID() == big.NewInt(622277) { + if c.GetChainID() != big.NewInt(622277) { return nil } return bigNewU64(c.HIPVeldinFBlock) From 4eef8b7b8ebde4ac7b223be80ab10bebc93f1e80 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Mon, 12 Feb 2024 17:21:45 +0000 Subject: [PATCH 23/45] flags: makeConsensusEngine rename --- cmd/utils/flags.go | 4 ++-- params/config_hypra.go | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 8b54c7e744..c7125c1bcf 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2548,7 +2548,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh chainDb = MakeChainDatabase(ctx, stack, readonly) ) - engine := CreateConsensusEngine(ctx, stack, gspec, chainDb) + engine := makeConsensusEngine(ctx, stack, gspec, chainDb) if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) @@ -2591,7 +2591,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh } // Create a Consensus Engine for a specific chains config -func CreateConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Genesis, chainDb ethdb.Database) (engine consensus.Engine) { +func makeConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Genesis, chainDb ethdb.Database) (engine consensus.Engine) { switch gspec.GetConsensusEngineType() { case ctypes.ConsensusEngineT_Ethash: ethashConfig := ethconfig.Defaults.Ethash diff --git a/params/config_hypra.go b/params/config_hypra.go index 7674860baf..7d85e7eb1a 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -62,7 +62,7 @@ var ( EIP1283FBlock: big.NewInt(5503), PetersburgBlock: big.NewInt(5507), - // Istanbul eq, aka Phoenix + // Istanbul eq EIP152FBlock: big.NewInt(5519), EIP1108FBlock: big.NewInt(5519), EIP1344FBlock: big.NewInt(5519), @@ -86,17 +86,19 @@ var ( EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode - // London chain upgrades, aka Eudora - EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions are not enabled on Hypra yet - EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) - EIP6049FBlock: big.NewInt(13_524_557), // Deprecate SELFDESTRUCT + // London chain upgrades, aka Planned Eudora + // TODO: move block numbers closer once testing has concluded + EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` EIP3529FBlock: big.NewInt(13_524_557), // Reduction in refunds - EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte + + // Unplanned Upgrade, aka Olantis + // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) + // EIP6049FBlock: big.NewInt(13_524_557), // Deprecate SELFDESTRUCT + // EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte // Spiral, aka Shanghai (partially) // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations - // EIP6049FBlock: big.NewInt(19_250_000), // Deprecate SELFDESTRUCT (noop) // Define the planned 3 year decreasing rewards. BlockRewardSchedule: map[uint64]*big.Int{ From 1112720ab62ee760a18602490e7bd17f06a13658 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 17:17:57 +0000 Subject: [PATCH 24/45] genesis: some changes to include Hypra genesis in other areas. --- cmd/devp2p/nodesetcmd.go | 2 ++ cmd/echainspec/main.go | 1 + core/genesis.go | 4 ++++ params/alloc_hypra.go | 2 +- params/config_hypra.go | 10 ++++++++-- 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cmd/devp2p/nodesetcmd.go b/cmd/devp2p/nodesetcmd.go index d6cb818f71..cd01768a40 100644 --- a/cmd/devp2p/nodesetcmd.go +++ b/cmd/devp2p/nodesetcmd.go @@ -239,6 +239,8 @@ func ethFilter(args []string) (nodeFilter, error) { filter = forkid.NewStaticFilter(params.MordorChainConfig, params.MordorGenesisHash) case "mintme": filter = forkid.NewStaticFilter(params.MintMeChainConfig, params.MintMeGenesisHash) + case "hypra": + filter = forkid.NewStaticFilter(params.HypraChainConfig, params.HypraGenesisHash) default: return nil, fmt.Errorf("unknown network %q", args[0]) } diff --git a/cmd/echainspec/main.go b/cmd/echainspec/main.go index 81d67bd615..2c0a08b1c8 100644 --- a/cmd/echainspec/main.go +++ b/cmd/echainspec/main.go @@ -48,6 +48,7 @@ var defaultChainspecValues = map[string]ctypes.Configurator{ "sepolia": params.DefaultSepoliaGenesisBlock(), "mintme": params.DefaultMintMeGenesisBlock(), + "hypra": params.DefaultHypraGenesisBlock(), } var defaultChainspecNames = func() []string { diff --git a/core/genesis.go b/core/genesis.go index 857dee8f09..aa04460db2 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -282,6 +282,8 @@ func configOrDefault(g *genesisT.Genesis, ghash common.Hash) ctypes.ChainConfigu return params.SepoliaChainConfig case ghash == params.MintMeGenesisHash: return params.MintMeChainConfig + case ghash == params.HypraGenesisHash: + return params.HypraChainConfig default: return params.AllEthashProtocolChanges } @@ -381,6 +383,8 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error { genesis = params.DefaultMordorGenesisBlock() case params.MintMeGenesisHash: genesis = params.DefaultMintMeGenesisBlock() + case params.HypraGenesisHash: + genesis = params.DefaultHypraGenesisBlock() } if genesis != nil { alloc = genesis.Alloc diff --git a/params/alloc_hypra.go b/params/alloc_hypra.go index 6b403fe008..b954d6a14e 100644 --- a/params/alloc_hypra.go +++ b/params/alloc_hypra.go @@ -1,3 +1,3 @@ package params -var HypraAllocData = "\xf9\x02\xc1\xca\x01\x88\r\u0db3\xa7d\x00\x01\xca\x02\x88\x1b\xc1mgN\xc8\x00\x02\xca\x03\x88)\xa2$\x1a\xf6,\x00\x03\xca\x04\x887\x82\xda\u039d\x90\x00\x04\xca\x05\x88Ec\x91\x82D\xf4\x00\x05\xca\x06\x88SDH5\xecX\x00\x06\xca\a\x88a$\xfe\u94fc\x00\a\xca\b\x88o\x05\xb5\x9d; \x00\b\xca\t\x88|\xe6lP\xe2\x84\x00\t\u07d2\xb2\xbe}\u03c7*Fb\xe3;L\t\xe7\xfc\xe2\xd5\x00\x00\x8b\x01\xbc\xb1:e{&8\x80\x00\x00\u0794\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\r\u0db3\xa7d\x00\x00\xe0\x94\x12\xbb\xad|\x1f>\a\x9a\xf5\xe1\xea\x13te\xe7\x05o\xf3?\x87\x8aO\xf6c5\xad\xe1\x04\xb0\x00\x00\u0794 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x1b\xc1mgN\xc8\x00\x00\xe0\x94%U\u049a\x0eb\xd4Sco\xeaLoe\x13\x15\xdbM\xcd)\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07940\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88)\xa2$\x1a\xf6,\x00\x00\xe0\x942\xbc\xa0[\xe7z~9c\xa4:\xad\xfd\xac-\xeb\x16^@ \x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94=\x16i\x92\x88\xf87\xd4c\x9e\x87\xee=\xa3\x18gUq\xdee\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u0794@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x887\x82\xda\u039d\x90\x00\x00\u0794P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88Ec\x91\x82D\xf4\x00\x00\u0794`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88SDH5\xecX\x00\x00\xe1\x94d\xcf\\A\xe0Prb\xf9\"v\x80\xb8\xa4\x02\xe7{\xeb\xe0u\x8b\x04\"\u028b\n\x00\xa4%\x00\x00\x00\u0794j\xd9v0>3\xffaa\n\x13{\x98\x87\xf3h:U\x19K\x88\xa6\x88\x90k\u0630\x059\u0794p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88a$\xfe\u94fc\x00\x00\u0794\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88o\x05\xb5\x9d; \x00\x00\u150d\x01\xbf1\b\xc7>\x8dX0\nk\xf3\r[N\xa7H\u0783\x8b\x02\x90sV4H\x13\u0640\x00\x00\u0794\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88|\xe6lP\xe2\x84\x00\x00\u0794\xd8\x02h\u0792\x81\x9b\x8b\x99\x01?\xa9\xdd\v\xad?\xacc\xf0\x03\x88\r\u0db3\xa7d\x00\x00\xe0\x94\xf9a2Z\xa3 \xee+\xa6\xce\a\xa0\xf4\xb47t\x8f[\xcf\xe8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" +const HypraAllocData = "\xf9\x02\xc1\xca\x01\x88\r\u0db3\xa7d\x00\x01\xca\x02\x88\x1b\xc1mgN\xc8\x00\x02\xca\x03\x88)\xa2$\x1a\xf6,\x00\x03\xca\x04\x887\x82\xda\u039d\x90\x00\x04\xca\x05\x88Ec\x91\x82D\xf4\x00\x05\xca\x06\x88SDH5\xecX\x00\x06\xca\a\x88a$\xfe\u94fc\x00\a\xca\b\x88o\x05\xb5\x9d; \x00\b\xca\t\x88|\xe6lP\xe2\x84\x00\t\u07d2\xb2\xbe}\u03c7*Fb\xe3;L\t\xe7\xfc\xe2\xd5\x00\x00\x8b\x01\xbc\xb1:e{&8\x80\x00\x00\u0794\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\r\u0db3\xa7d\x00\x00\xe0\x94\x12\xbb\xad|\x1f>\a\x9a\xf5\xe1\xea\x13te\xe7\x05o\xf3?\x87\x8aO\xf6c5\xad\xe1\x04\xb0\x00\x00\u0794 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x1b\xc1mgN\xc8\x00\x00\xe0\x94%U\u049a\x0eb\xd4Sco\xeaLoe\x13\x15\xdbM\xcd)\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07940\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88)\xa2$\x1a\xf6,\x00\x00\xe0\x942\xbc\xa0[\xe7z~9c\xa4:\xad\xfd\xac-\xeb\x16^@ \x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94=\x16i\x92\x88\xf87\xd4c\x9e\x87\xee=\xa3\x18gUq\xdee\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u0794@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x887\x82\xda\u039d\x90\x00\x00\u0794P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88Ec\x91\x82D\xf4\x00\x00\u0794`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88SDH5\xecX\x00\x00\xe1\x94d\xcf\\A\xe0Prb\xf9\"v\x80\xb8\xa4\x02\xe7{\xeb\xe0u\x8b\x04\"\u028b\n\x00\xa4%\x00\x00\x00\u0794j\xd9v0>3\xffaa\n\x13{\x98\x87\xf3h:U\x19K\x88\xa6\x88\x90k\u0630\x059\u0794p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88a$\xfe\u94fc\x00\x00\u0794\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88o\x05\xb5\x9d; \x00\x00\u150d\x01\xbf1\b\xc7>\x8dX0\nk\xf3\r[N\xa7H\u0783\x8b\x02\x90sV4H\x13\u0640\x00\x00\u0794\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88|\xe6lP\xe2\x84\x00\x00\u0794\xd8\x02h\u0792\x81\x9b\x8b\x99\x01?\xa9\xdd\v\xad?\xacc\xf0\x03\x88\r\u0db3\xa7d\x00\x00\xe0\x94\xf9a2Z\xa3 \xee+\xa6\xce\a\xa0\xf4\xb47t\x8f[\xcf\xe8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" diff --git a/params/config_hypra.go b/params/config_hypra.go index 7d85e7eb1a..47f7c2581d 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -38,14 +38,14 @@ var ( EIP7FBlock: big.NewInt(0), // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? // DAOForkSupport isnt in this struct - // DAOForkBlock: big.NewInt(0), + DAOForkBlock: big.NewInt(0), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP160FBlock: big.NewInt(0), EIP161FBlock: big.NewInt(0), EIP170FBlock: big.NewInt(0), - // Byzantium eq + // Byzantium eq -- Enables Smart contracts EIP100FBlock: big.NewInt(1001), EIP140FBlock: big.NewInt(1001), EIP198FBlock: big.NewInt(1001), @@ -53,6 +53,7 @@ var ( EIP212FBlock: big.NewInt(1001), EIP213FBlock: big.NewInt(1001), EIP214FBlock: big.NewInt(1001), + EIP649FBlock: big.NewInt(1001), EIP658FBlock: big.NewInt(1001), // Constantinople eq @@ -100,6 +101,11 @@ var ( // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + // Dummy EIPs, unused by ethashb3 + //EIP3554FBlock: big.NewInt(13_524_557), + //EIP3541FBlock: big.NewInt(13_524_557), + //EIP4345FBlock: big.NewInt(27_200_177), + //EIP5133FBlock: big.NewInt(40_725_107), // Define the planned 3 year decreasing rewards. BlockRewardSchedule: map[uint64]*big.Int{ 0: big.NewInt(4 * vars.Ether), From ba14c5d9f4f7aef21cdaa519500d8c3eeb038e33 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 17:55:08 +0000 Subject: [PATCH 25/45] params, forkid: Added support for hypra fake use of Grey Glacier for forkid to work. Currently stuck on (ForkID 12) --- core/forkid/forkid_test.go | 25 +++++++++++++++++++ params/config_hypra.go | 6 +++++ params/confp/configurator.go | 5 ++-- .../coregeth/chain_config_configurator.go | 6 +++-- .../goethereum/goethereum_configurator.go | 5 ++-- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 916c3721a1..18dfba5dcc 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -204,6 +204,31 @@ func TestCreation(t *testing.T) { {252500, 0, ID{Hash: checksumToBytes(0x50aed09f), Next: 0}}, }, }, + { + name: "Hypra", + config: params.HypraChainConfig, + genesis: params.HypraGenesisHash, + cases: []testcase{ + {0, 0, ID{Hash: checksumToBytes(0x61aefa70), Next: 1001}}, + {1000, 0, ID{Hash: checksumToBytes(0x61aefa70), Next: 1001}}, + {1001, 0, ID{Hash: checksumToBytes(0x7cc30c12), Next: 5503}}, + {1002, 0, ID{Hash: checksumToBytes(0x7cc30c12), Next: 5503}}, + {5502, 0, ID{Hash: checksumToBytes(0x7cc30c12), Next: 5503}}, + {5503, 0, ID{Hash: checksumToBytes(0xc04d6826), Next: 5507}}, + {5506, 0, ID{Hash: checksumToBytes(0xc04d6826), Next: 5507}}, + {5507, 0, ID{Hash: checksumToBytes(0xfbb573dd), Next: 5519}}, + {5510, 0, ID{Hash: checksumToBytes(0xfbb573dd), Next: 5519}}, + {5519, 0, ID{Hash: checksumToBytes(0x1aebed3d), Next: 5521}}, // -- fails from here + {5521, 0, ID{Hash: checksumToBytes(0xfff37fb6), Next: 5527}}, + {5526, 0, ID{Hash: checksumToBytes(0xfff37fb6), Next: 5527}}, + {5527, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, + {1_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, + {5_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, + {10_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, + {13_524_557, 0, ID{Hash: checksumToBytes(0xb09ff5ab), Next: 27_200_177}}, + {27_200_177, 0, ID{Hash: checksumToBytes(0x50ce6e77), Next: 40_725_107}}, + }, + }, } for i, tt := range tests { for j, ttt := range tt.cases { diff --git a/params/config_hypra.go b/params/config_hypra.go index 47f7c2581d..e6134bd71e 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -128,3 +128,9 @@ var ( }, } ) + +func init() { + // hack to override the default bomb schedule + eip2384 := HypraChainConfig.EIP2384FBlock.Uint64() + HypraChainConfig.SetEthashEIP2384Transition(&eip2384) +} diff --git a/params/confp/configurator.go b/params/confp/configurator.go index b24105cd83..fc7bdc9778 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -31,8 +31,9 @@ var ( // compatibleProtocolNameSchemes define matchable naming schemes used by configuration methods // that are not incompatible with configuration either having or lacking them. compatibleProtocolNameSchemes = []string{ - "ECBP", // "Ethereum Classic Best Practice" - "EBP", // "Ethereum Best Practice" + "ECBP", // "Ethereum Classic Best Practice" + "EBP", // "Ethereum Best Practice" + "HIPVeldin", // Hypra Veldin reward Patch } ) diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index 306beebb80..e557717018 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -980,7 +980,8 @@ func (c *CoreGethChainConfig) SetEthashEIP1234Transition(n *uint64) error { } func (c *CoreGethChainConfig) GetEthashEIP2384Transition() *uint64 { - if c.GetConsensusEngineType() != ctypes.ConsensusEngineT_Ethash { + engine := c.GetConsensusEngineType() + if engine != ctypes.ConsensusEngineT_Ethash && engine != ctypes.ConsensusEngineT_EthashB3 { return nil } if c.eip2384Inferred { @@ -995,11 +996,12 @@ func (c *CoreGethChainConfig) GetEthashEIP2384Transition() *uint64 { // Get block number (key) from map where EIP2384 criteria is met. diffN = ctypes.MapMeetsSpecification(c.DifficultyBombDelaySchedule, nil, vars.EIP2384DifficultyBombDelay, nil) + return diffN } func (c *CoreGethChainConfig) SetEthashEIP2384Transition(n *uint64) error { - if c.Ethash == nil { + if c.Ethash == nil && c.EthashB3 == nil { return ctypes.ErrUnsupportedConfigFatal } diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index eb23417c64..491c180dcc 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -945,14 +945,15 @@ func (c *ChainConfig) SetEthashEIP1234Transition(n *uint64) error { } func (c *ChainConfig) GetEthashEIP2384Transition() *uint64 { - if c.GetConsensusEngineType() != ctypes.ConsensusEngineT_Ethash { + engine := c.GetConsensusEngineType() + if engine != ctypes.ConsensusEngineT_Ethash && engine != ctypes.ConsensusEngineT_EthashB3 { return nil } return bigNewU64(c.MuirGlacierBlock) } func (c *ChainConfig) SetEthashEIP2384Transition(n *uint64) error { - if c.Ethash == nil { + if c.Ethash == nil && c.EthashB3 == nil { return ctypes.ErrUnsupportedConfigFatal } c.MuirGlacierBlock = setBig(c.MuirGlacierBlock, n) From 0944ae57323923098c9d879a9e8aee561b0f6705 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 18:18:52 +0000 Subject: [PATCH 26/45] Add per network incompatible map for such networks like Hypra who bung up the forks on Geth. --- core/forkid/forkid_test.go | 159 +---------------------------------- params/config_hypra.go | 4 +- params/confp/configurator.go | 32 ++++++- 3 files changed, 32 insertions(+), 163 deletions(-) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 18dfba5dcc..74d9322604 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -49,161 +49,6 @@ func TestCreation(t *testing.T) { cases []testcase }{ // Mainnet test cases - { - "mainnet", - params.MainnetChainConfig, - params.MainnetGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced - {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block - {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // First Homestead block - {1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // Last Homestead block - {1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // First DAO block - {2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // Last DAO block - {2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // First Tangerine block - {2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // Last Tangerine block - {2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // First Spurious block - {4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // Last Spurious block - {4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // First Byzantium block - {7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // Last Byzantium block - {7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // First and last Constantinople, first Petersburg block - {9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // Last Petersburg block - {9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // First Istanbul and first Muir Glacier block - {9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // Last Istanbul and first Muir Glacier block - {9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // First Muir Glacier block - {12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block - {12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block - {12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block - {12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // First London block - {13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // Last London block - {13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // First Arrow Glacier block - {15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // Last Arrow Glacier block - {15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // First Gray Glacier block - {20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block - {20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}}, // First Shanghai block - {30000000, 2000000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}}, // Future Shanghai block - }, - }, - // Goerli test cases - { - "goerli", - params.GoerliChainConfig, - params.GoerliGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block - {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block - {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block - {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block - {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block - {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block - {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block - {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block - {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // First Shanghai block - {6500000, 2678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // Future Shanghai block - }, - }, - // Sepolia test cases - { - "sepolia", - params.SepoliaChainConfig, - params.SepoliaGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block - {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block - {1735371, 0, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block - {1735372, 1677557087, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last MergeNetsplit block - {1735372, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 0}}, // First Shanghai block - }, - }, - { - "classic", - params.ClassicChainConfig, - params.MainnetGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {1, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {2, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {3, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {9, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {10, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, - {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, - {1150001, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, - {2499999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, - {2500000, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, - {2500001, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, - {2999999, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, - {3000000, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, - {3000001, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, - {4999999, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, - {5000000, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, - {5000001, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, - {5899999, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, - {5900000, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, - {5900001, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, - {8771999, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, - {8772000, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, - {8772001, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, - {9572999, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, - {9573000, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, - {9573001, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, - {10500838, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, - {10500839, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, - {10500840, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, - {11_699_999, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, - {11_700_000, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, - {11_700_001, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, - {13_189_132, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, - {13_189_133, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, - {13_189_134, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, - {14_524_999, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, - {14_525_000, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, - {14_525_001, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, - {19_249_999, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, - {19_250_000, 0, ID{Hash: checksumToBytes(0xbe46d57c), Next: 0}}, - {19_250_001, 0, ID{Hash: checksumToBytes(0xbe46d57c), Next: 0}}, - }, - }, - { - "mordor", - params.MordorChainConfig, - params.MordorGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {1, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {2, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {3, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {9, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {10, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {301242, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, - {301243, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, - {301244, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, - {999982, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, - {999983, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, - {999984, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, - {2_519_999, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, - {2_520_000, 0, ID{Hash: checksumToBytes(0x66b5c286), Next: 3_985_893}}, - {3_985_892, 0, ID{Hash: checksumToBytes(0x66b5c286), Next: 3_985_893}}, - {3_985_893, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, - {3_985_894, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, - {5_519_999, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, - {5_520_000, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, - {5_520_001, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, - {9_956_999, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, - {9_957_000, 0, ID{Hash: checksumToBytes(0x3a6b00d7), Next: 0}}, - {9_957_001, 0, ID{Hash: checksumToBytes(0x3a6b00d7), Next: 0}}, - }, - }, - // MintMe test cases - { - "mintme", - params.MintMeChainConfig, - params.MintMeGenesisHash, - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0x02bf4180), Next: 252500}}, - {252500, 0, ID{Hash: checksumToBytes(0x50aed09f), Next: 0}}, - }, - }, { name: "Hypra", config: params.HypraChainConfig, @@ -218,15 +63,13 @@ func TestCreation(t *testing.T) { {5506, 0, ID{Hash: checksumToBytes(0xc04d6826), Next: 5507}}, {5507, 0, ID{Hash: checksumToBytes(0xfbb573dd), Next: 5519}}, {5510, 0, ID{Hash: checksumToBytes(0xfbb573dd), Next: 5519}}, - {5519, 0, ID{Hash: checksumToBytes(0x1aebed3d), Next: 5521}}, // -- fails from here + {5519, 0, ID{Hash: checksumToBytes(0x1aebed3d), Next: 5521}}, {5521, 0, ID{Hash: checksumToBytes(0xfff37fb6), Next: 5527}}, {5526, 0, ID{Hash: checksumToBytes(0xfff37fb6), Next: 5527}}, {5527, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, {1_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, {5_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, {10_000_000, 0, ID{Hash: checksumToBytes(0x6f27ec43), Next: 13_524_557}}, - {13_524_557, 0, ID{Hash: checksumToBytes(0xb09ff5ab), Next: 27_200_177}}, - {27_200_177, 0, ID{Hash: checksumToBytes(0x50ce6e77), Next: 40_725_107}}, }, }, } diff --git a/params/config_hypra.go b/params/config_hypra.go index e6134bd71e..fe064a7118 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -102,8 +102,8 @@ var ( // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations // Dummy EIPs, unused by ethashb3 - //EIP3554FBlock: big.NewInt(13_524_557), - //EIP3541FBlock: big.NewInt(13_524_557), + EIP3554FBlock: big.NewInt(13_524_557), + EIP3541FBlock: big.NewInt(13_524_557), //EIP4345FBlock: big.NewInt(27_200_177), //EIP5133FBlock: big.NewInt(40_725_107), // Define the planned 3 year decreasing rewards. diff --git a/params/confp/configurator.go b/params/confp/configurator.go index fc7bdc9778..a562bc9605 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -31,9 +31,20 @@ var ( // compatibleProtocolNameSchemes define matchable naming schemes used by configuration methods // that are not incompatible with configuration either having or lacking them. compatibleProtocolNameSchemes = []string{ - "ECBP", // "Ethereum Classic Best Practice" - "EBP", // "Ethereum Best Practice" - "HIPVeldin", // Hypra Veldin reward Patch + "ECBP", // "Ethereum Classic Best Practice" + "EBP", // "Ethereum Best Practice" + } + + // incompatibleNetworkMap defines matchable naming schemes which are incompatible with certain + // legacy networks or networks who use their own forks unincluded in forkid. + // Introduced by Hypra (622277) + incompatibleNetworNameMap = map[uint64][]string{ + 622277: { + "HIPVeldin", + "EIP3855", + "EIP3860", + "EIP3198", + }, } ) @@ -46,6 +57,16 @@ func nameSignalsCompatibility(name string) bool { return false } +func networkSignalsCompatibility(netId uint64, name string) bool { + for _, s := range incompatibleNetworNameMap[netId] { + if regexp.MustCompile(s).MatchString(name) { + return true + } + } + return false + +} + var ( blockTransitionNamePattern = regexp.MustCompile(`(?m)^Get.+Transition$`) timeTransitionNamePattern = regexp.MustCompile(`(?m)^Get.+TransitionTime$`) @@ -468,6 +489,11 @@ func BlockForks(conf ctypes.ChainConfigurator) []uint64 { if nameSignalsCompatibility(names[i]) { continue } + + if networkSignalsCompatibility(conf.GetChainID().Uint64(), names[i]) { + continue + } + // Extract the fork rule block number and aggregate it response := tr() if response == nil || From 592cada81f53affe1f28c1a8ac8c44946a86ebee Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 18:19:54 +0000 Subject: [PATCH 27/45] forkid: readd other network tests after debugging Hypra --- core/forkid/forkid_test.go | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 74d9322604..4e7de15358 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -49,6 +49,161 @@ func TestCreation(t *testing.T) { cases []testcase }{ // Mainnet test cases + { + "mainnet", + params.MainnetChainConfig, + params.MainnetGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced + {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block + {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // First Homestead block + {1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // Last Homestead block + {1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // First DAO block + {2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // Last DAO block + {2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // First Tangerine block + {2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // Last Tangerine block + {2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // First Spurious block + {4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // Last Spurious block + {4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // First Byzantium block + {7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // Last Byzantium block + {7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // First and last Constantinople, first Petersburg block + {9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // Last Petersburg block + {9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // First Istanbul and first Muir Glacier block + {9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // Last Istanbul and first Muir Glacier block + {9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // First Muir Glacier block + {12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block + {12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block + {12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block + {12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // First London block + {13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // Last London block + {13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // First Arrow Glacier block + {15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // Last Arrow Glacier block + {15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // First Gray Glacier block + {20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block + {20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}}, // First Shanghai block + {30000000, 2000000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}}, // Future Shanghai block + }, + }, + // Goerli test cases + { + "goerli", + params.GoerliChainConfig, + params.GoerliGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block + {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block + {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block + {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block + {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block + {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block + {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block + {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block + {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // First Shanghai block + {6500000, 2678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // Future Shanghai block + }, + }, + // Sepolia test cases + { + "sepolia", + params.SepoliaChainConfig, + params.SepoliaGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block + {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block + {1735371, 0, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block + {1735372, 1677557087, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last MergeNetsplit block + {1735372, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 0}}, // First Shanghai block + }, + }, + { + "classic", + params.ClassicChainConfig, + params.MainnetGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {1, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {2, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {3, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {9, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {10, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, + {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, + {1150001, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, + {2499999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 2500000}}, + {2500000, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, + {2500001, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, + {2999999, 0, ID{Hash: checksumToBytes(0xdb06803f), Next: 3000000}}, + {3000000, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, + {3000001, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, + {4999999, 0, ID{Hash: checksumToBytes(0xaff4bed4), Next: 5000000}}, + {5000000, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, + {5000001, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, + {5899999, 0, ID{Hash: checksumToBytes(0xf79a63c0), Next: 5900000}}, + {5900000, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, + {5900001, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, + {8771999, 0, ID{Hash: checksumToBytes(0x744899d6), Next: 8772000}}, + {8772000, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, + {8772001, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, + {9572999, 0, ID{Hash: checksumToBytes(0x518b59c6), Next: 9573000}}, + {9573000, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, + {9573001, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, + {10500838, 0, ID{Hash: checksumToBytes(0x7ba22882), Next: 10500839}}, + {10500839, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, + {10500840, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, + {11_699_999, 0, ID{Hash: checksumToBytes(0x9007bfcc), Next: 11_700_000}}, + {11_700_000, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, + {11_700_001, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, + {13_189_132, 0, ID{Hash: checksumToBytes(0xdb63a1ca), Next: 13_189_133}}, + {13_189_133, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, + {13_189_134, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, + {14_524_999, 0, ID{Hash: checksumToBytes(0x0f6bf187), Next: 14_525_000}}, + {14_525_000, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, + {14_525_001, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, + {19_249_999, 0, ID{Hash: checksumToBytes(0x7fd1bb25), Next: 19_250_000}}, + {19_250_000, 0, ID{Hash: checksumToBytes(0xbe46d57c), Next: 0}}, + {19_250_001, 0, ID{Hash: checksumToBytes(0xbe46d57c), Next: 0}}, + }, + }, + { + "mordor", + params.MordorChainConfig, + params.MordorGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {1, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {2, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {3, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {9, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {10, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {301242, 0, ID{Hash: checksumToBytes(0x175782aa), Next: 301243}}, + {301243, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, + {301244, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, + {999982, 0, ID{Hash: checksumToBytes(0x604f6ee1), Next: 999983}}, + {999983, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, + {999984, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, + {2_519_999, 0, ID{Hash: checksumToBytes(0xf42f5539), Next: 2_520_000}}, + {2_520_000, 0, ID{Hash: checksumToBytes(0x66b5c286), Next: 3_985_893}}, + {3_985_892, 0, ID{Hash: checksumToBytes(0x66b5c286), Next: 3_985_893}}, + {3_985_893, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, + {3_985_894, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, + {5_519_999, 0, ID{Hash: checksumToBytes(0x92b323e0), Next: 5_520_000}}, + {5_520_000, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, + {5_520_001, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, + {9_956_999, 0, ID{Hash: checksumToBytes(0x8c9b1797), Next: 9_957_000}}, + {9_957_000, 0, ID{Hash: checksumToBytes(0x3a6b00d7), Next: 0}}, + {9_957_001, 0, ID{Hash: checksumToBytes(0x3a6b00d7), Next: 0}}, + }, + }, + // MintMe test cases + { + "mintme", + params.MintMeChainConfig, + params.MintMeGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0x02bf4180), Next: 252500}}, + {252500, 0, ID{Hash: checksumToBytes(0x50aed09f), Next: 0}}, + }, + }, { name: "Hypra", config: params.HypraChainConfig, From 3966827a0da804a49108970bb0710ca73d3e584c Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 18:27:23 +0000 Subject: [PATCH 28/45] params: Add some comments and fixed typo --- params/confp/configurator.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/params/confp/configurator.go b/params/confp/configurator.go index a562bc9605..3c4d5bc5a1 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -38,12 +38,12 @@ var ( // incompatibleNetworkMap defines matchable naming schemes which are incompatible with certain // legacy networks or networks who use their own forks unincluded in forkid. // Introduced by Hypra (622277) - incompatibleNetworNameMap = map[uint64][]string{ + incompatibleNetworkNameMap = map[uint64][]string{ 622277: { - "HIPVeldin", - "EIP3855", - "EIP3860", - "EIP3198", + "HIPVeldin", // Custom fork not used in forkId + "EIP3855", // Enabled on Hypra via Gaspar fork + "EIP3860", // Enabled on Hypra via Gaspar fork + "EIP3198", // Enabled on Hypra via Gaspar fork }, } ) @@ -58,7 +58,7 @@ func nameSignalsCompatibility(name string) bool { } func networkSignalsCompatibility(netId uint64, name string) bool { - for _, s := range incompatibleNetworNameMap[netId] { + for _, s := range incompatibleNetworkNameMap[netId] { if regexp.MustCompile(s).MatchString(name) { return true } From c9f373a3669b3ecf941d6ef6b47a555c541db5c1 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 19:22:32 +0000 Subject: [PATCH 29/45] params: Flip the condition correctly getting the rewards for EthashB3 --- params/types/coregeth/chain_config_configurator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index e557717018..aafadb6319 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -1272,7 +1272,7 @@ func (c *CoreGethChainConfig) SetEthashDifficultyBombDelaySchedule(m ctypes.Uint func (c *CoreGethChainConfig) GetEthashBlockRewardSchedule() ctypes.Uint64BigMapEncodesHex { engineType := c.GetConsensusEngineType() - if engineType == ctypes.ConsensusEngineT_Ethash || engineType == ctypes.ConsensusEngineT_EthashB3 { + if engineType != ctypes.ConsensusEngineT_Ethash && engineType != ctypes.ConsensusEngineT_EthashB3 { return nil } return c.BlockRewardSchedule From e8b80f4ef4b7a170f59739faa779cfa5bffc56e7 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 19:58:55 +0000 Subject: [PATCH 30/45] params: Fix veldin rewards causing invalid merkles --- params/mutations/rewards_hypra.go | 4 ++-- params/types/coregeth/chain_config_configurator.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/params/mutations/rewards_hypra.go b/params/mutations/rewards_hypra.go index 0937b875d4..e1b83a39e8 100644 --- a/params/mutations/rewards_hypra.go +++ b/params/mutations/rewards_hypra.go @@ -43,7 +43,7 @@ func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncl if len(uncles) == 0 { // If no uncles, the miner gets the entire block fee. minerReward.Add(minerReward, blockFeeReward) - } else if config.IsEnabled(config.GetEIP2718Transition, header.Number) { // During Berlin block, each miner and uncles are rewarded the block fee. + } else if config.IsEnabled(config.GetEIP2929Transition, header.Number) { // During Berlin block, each miner and uncles are rewarded the block fee. uncleReward.Add(uncleReward, blockFeeReward) minerReward.Add(minerReward, blockFeeReward) } else if config.IsEnabled(config.GetEthashHomesteadTransition, header.Number) { // Until Berlin block, Miners and Uncles are rewarded for the amount of uncles generated. @@ -54,7 +54,7 @@ func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncl uncleRewards := make([]*big.Int, len(uncles)) for i, _ := range uncles { - uncleRewards[i].Set(uncleReward) + uncleRewards[i] = uncleReward if config.IsEnabled(config.GetHIPVeldinTransition, header.Number) { minerReward.Add(minerReward, uncleReward) diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index aafadb6319..f316340524 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -1334,7 +1334,7 @@ func (c *CoreGethChainConfig) SetLyra2NonceTransition(n *uint64) error { } func (c *CoreGethChainConfig) GetHIPVeldinTransition() *uint64 { - if c.GetChainID() != big.NewInt(622277) { + if c.GetChainID().Uint64() != 622277 { return nil } return bigNewU64(c.HIPVeldinFBlock) From 593a6f55d254ec88107c826e9e79d31ada94e68b Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 20:11:21 +0000 Subject: [PATCH 31/45] params: Update checkpoint --- params/config_hypra.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/config_hypra.go b/params/config_hypra.go index fe064a7118..44c00a0fea 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -115,10 +115,10 @@ var ( }, TrustedCheckpoint: &ctypes.TrustedCheckpoint{ - BloomRoot: common.HexToHash("0xb09a3dc1215903dc757dd83c960c6dd77ec508e03c185b16df62af069d197fc3"), - CHTRoot: common.HexToHash("0x21f6a69cbd097bd2c1d250ed7144888e483d46105b66a99a68e4847c99a863cd"), - SectionHead: common.HexToHash("0x2461cbf15f92264332e09ba8a9d6b9106c12b3cf0e7d7bfff78483c1b271e902"), - SectionIndex: 43, + BloomRoot: common.HexToHash("0x60920705aff6a1441f0d7788864c705a5bfa3bcde92241689428c3a8a591f2ad"), + CHTRoot: common.HexToHash("0x4433e5c69618532e76baac60a97644376abd61709b4f4ac00068ab04c240de8d"), + SectionHead: common.HexToHash("0xab8c36d437605d3ed00c908a5839485e76fb07183932a60661c91fa5ee3ac320"), + SectionIndex: 61, }, RequireBlockHashes: map[uint64]common.Hash{ From 5a26d5db8a8e8cadd16905fb5baddbf4ec583e38 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 20:48:12 +0000 Subject: [PATCH 32/45] core: Uncle maker patch, a miner must be 2 blocks ahead to fork. --- core/forkchoice.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/forkchoice.go b/core/forkchoice.go index d07cdf6aa4..925b7df23e 100644 --- a/core/forkchoice.go +++ b/core/forkchoice.go @@ -115,6 +115,13 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b return true, nil } + // Reject the new header if it's the same as the current head. + // Refer to https://eprint.iacr.org/2022/1020 for more info. + // This is to prevent the uncle maker attack. + if current.Number.Cmp(extern.Number) == 0 { + return false, nil + } + // // If the total difficulty is higher than our known, add it to the canonical chain // if diff := externTd.Cmp(localTD); diff > 0 { // return true, nil From 18d0b6627f7cb583fd7a5dd6bcbe67638160fb5b Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 13 Feb 2024 23:52:21 +0000 Subject: [PATCH 33/45] params: Better aligned. --- README.md | 15 +++++++++++---- params/config_hypra.go | 12 +++++++----- params/confp/configurator.go | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 231e3be3e2..3cb852b0dc 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Upstream development from [ethereum/go-ethereum](https://github.com/ethereum/go- Networks supported by the respective go-ethereum packaged `geth` program. | Ticker | Consensus | Network | core-geth | ethereum/go-ethereum | -| --- | --- | --- | --- | --- | -| ETC | :zap: | Ethereum Classic | :heavy_check_mark: | | -| ETH | :zap: | Ethereum (Foundation) | :heavy_check_mark: | :heavy_check_mark: | +|--------|-------------------|---------------------------------------| --- | --- | +| ETC | :zap: Ethash | Ethereum Classic | :heavy_check_mark: | | +| ETH | :zap: Ethash | Ethereum (Foundation) | :heavy_check_mark: | :heavy_check_mark: | | - | :zap: :handshake: | Private chains | :heavy_check_mark: | :heavy_check_mark: | | | :zap: | Mordor (Geth+Parity ETH PoW Testnet) | :heavy_check_mark: | | | | :zap: | Morden (Geth+Parity ETH PoW Testnet) | | | @@ -31,11 +31,18 @@ Networks supported by the respective go-ethereum packaged `geth` program. | | :handshake: | Kovan (Parity-only ETH PoA Testnet) | | | | | | Tobalaba (EWF Testnet) | | | | | | Ephemeral development PoA network | :heavy_check_mark: | :heavy_check_mark: | -| MINTME | :zap: | MintMe.com Coin | :heavy_check_mark: | | +| MINTME | :zap: Lyra2 | MintMe.com Coin | :heavy_check_mark: | | +| HYP | :zap: EthashB3 | Hypra Network | :heavy_check_mark: | | - :zap: = __Proof of Work__ - :handshake: = __Proof of Authority__ +Supported Algorithms +- Ethash +- Etchash +- EthashB3 +- Lyra2 + 1: This is originally an [Ellaism Project](https://github.com/ellaism). However, A [recent hard fork](https://github.com/ellaism/specs/blob/master/specs/2018-0003-wasm-hardfork.md) diff --git a/params/config_hypra.go b/params/config_hypra.go index 44c00a0fea..8d7aa14b11 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -38,7 +38,7 @@ var ( EIP7FBlock: big.NewInt(0), // This is 0 on Hypra but Fork support is nil. Should this be enabled or not? // DAOForkSupport isnt in this struct - DAOForkBlock: big.NewInt(0), + //DAOForkBlock: big.NewInt(0), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP160FBlock: big.NewInt(0), @@ -53,7 +53,7 @@ var ( EIP212FBlock: big.NewInt(1001), EIP213FBlock: big.NewInt(1001), EIP214FBlock: big.NewInt(1001), - EIP649FBlock: big.NewInt(1001), + //EIP649FBlock: big.NewInt(1001), EIP658FBlock: big.NewInt(1001), // Constantinople eq @@ -86,11 +86,12 @@ var ( EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode + EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds // London chain upgrades, aka Planned Eudora // TODO: move block numbers closer once testing has concluded - EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` - EIP3529FBlock: big.NewInt(13_524_557), // Reduction in refunds + //EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` + //EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF // Unplanned Upgrade, aka Olantis // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) @@ -101,11 +102,12 @@ var ( // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations - // Dummy EIPs, unused by ethashb3 + // Dummy EIPs, unused by ethashb3 but used by forkid EIP3554FBlock: big.NewInt(13_524_557), EIP3541FBlock: big.NewInt(13_524_557), //EIP4345FBlock: big.NewInt(27_200_177), //EIP5133FBlock: big.NewInt(40_725_107), + // Define the planned 3 year decreasing rewards. BlockRewardSchedule: map[uint64]*big.Int{ 0: big.NewInt(4 * vars.Ether), diff --git a/params/confp/configurator.go b/params/confp/configurator.go index 3c4d5bc5a1..a420c3c719 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -44,6 +44,7 @@ var ( "EIP3855", // Enabled on Hypra via Gaspar fork "EIP3860", // Enabled on Hypra via Gaspar fork "EIP3198", // Enabled on Hypra via Gaspar fork + "EIP3529", // Enabled on Hypra via Gaspar fork }, } ) From 80e244db52cf8250abe9081ad0c82e62327eb731 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Tue, 20 Feb 2024 01:10:58 +0000 Subject: [PATCH 34/45] core: Symatically match Hypra Gaspar to enable EIP3860 EVM changes. NOTE: This still doesn't sync past gaspar :( --- cmd/evm/internal/t8ntool/transaction.go | 8 +++++--- core/state_transition.go | 22 +++++++++++++--------- light/txpool.go | 5 ++++- params/config_hypra.go | 15 ++++++++++----- params/mutations/rewards_hypra.go | 4 +--- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 39e86304f0..94c4e17cbf 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -20,6 +20,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ethereum/go-ethereum/params" "math/big" "os" "strings" @@ -145,11 +146,12 @@ func Transaction(ctx *cli.Context) error { eip2f := chainConfig.IsEnabled(chainConfig.GetEIP2Transition, new(big.Int)) eip2028f := chainConfig.IsEnabled(chainConfig.GetEIP2028Transition, new(big.Int)) zero := uint64(0) - eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int)) + eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || + chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int)) && + chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this // Check intrinsic gas - if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, - eip2f, eip2028f, eip3860f); err != nil { + if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, eip2f, eip2028f, eip3860f); err != nil { r.Error = err results = append(results, r) continue diff --git a/core/state_transition.go b/core/state_transition.go index 0aa7af9f04..8cf7feb5c9 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -19,6 +19,7 @@ package core import ( "errors" "fmt" + "github.com/ethereum/go-ethereum/params" "math" "math/big" @@ -376,35 +377,38 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { msg = st.msg sender = vm.AccountRef(msg.From) contractCreation = msg.To == nil + chainConfig = st.evm.ChainConfig() // EIP-2: Homestead - eip2f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2Transition, st.evm.Context.BlockNumber) + eip2f = chainConfig.IsEnabled(chainConfig.GetEIP2Transition, st.evm.Context.BlockNumber) // Istanbul // https://eips.ethereum.org/EIPS/eip-1679 // EIP-2028: Calldata gas cost reduction - eip2028f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2028Transition, st.evm.Context.BlockNumber) + eip2028f = chainConfig.IsEnabled(chainConfig.GetEIP2028Transition, st.evm.Context.BlockNumber) // Berlin // https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md // EIP-2930: Optional access lists - eip2930f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2930Transition, st.evm.Context.BlockNumber) + eip2930f = chainConfig.IsEnabled(chainConfig.GetEIP2930Transition, st.evm.Context.BlockNumber) // London // https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md // EIP-1559: Fee market change: burn fee and tips - eip1559f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP1559Transition, st.evm.Context.BlockNumber) + eip1559f = chainConfig.IsEnabled(chainConfig.GetEIP1559Transition, st.evm.Context.BlockNumber) // EIP-3529: Reduction in refunds - eip3529f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3529Transition, st.evm.Context.BlockNumber) + eip3529f = chainConfig.IsEnabled(chainConfig.GetEIP3529Transition, st.evm.Context.BlockNumber) && + chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this // EIP-3860: Limit and meter initcode - eip3860f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3860TransitionTime, &st.evm.Context.Time) || - st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3860Transition, st.evm.Context.BlockNumber) + eip3860f = chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &st.evm.Context.Time) || + chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, st.evm.Context.BlockNumber) && + chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this // EIP-3651: Warm coinbase - eip3651f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3651TransitionTime, &st.evm.Context.Time) || - st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3651Transition, st.evm.Context.BlockNumber) + eip3651f = chainConfig.IsEnabledByTime(chainConfig.GetEIP3651TransitionTime, &st.evm.Context.Time) || + chainConfig.IsEnabled(chainConfig.GetEIP3651Transition, st.evm.Context.BlockNumber) ) // Check clauses 4-5, subtract intrinsic gas if everything is correct diff --git a/light/txpool.go b/light/txpool.go index 688cc7493f..f64c29cb99 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -19,6 +19,7 @@ package light import ( "context" "fmt" + "github.com/ethereum/go-ethereum/params" "math/big" "sync" "time" @@ -339,7 +340,9 @@ func (pool *TxPool) setNewHead(head *types.Header) { pool.eip2028f = pool.config.IsEnabled(pool.config.GetEIP2028Transition, next) pool.eip2718 = pool.config.IsEnabled(pool.config.GetEIP2718Transition, next) now := uint64(time.Now().Unix()) - pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) || pool.config.IsEnabled(pool.config.GetEIP3860Transition, next) + pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) || + pool.config.IsEnabled(pool.config.GetEIP3860Transition, next) && + pool.config.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this } // Stop stops the light transaction pool diff --git a/params/config_hypra.go b/params/config_hypra.go index 8d7aa14b11..0634e99ae9 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -53,7 +53,6 @@ var ( EIP212FBlock: big.NewInt(1001), EIP213FBlock: big.NewInt(1001), EIP214FBlock: big.NewInt(1001), - //EIP649FBlock: big.NewInt(1001), EIP658FBlock: big.NewInt(1001), // Constantinople eq @@ -88,13 +87,14 @@ var ( EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds - // London chain upgrades, aka Planned Eudora + // London chain upgrades TX Type 2, aka Planned Eudora // TODO: move block numbers closer once testing has concluded - //EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` - //EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF + // EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` + // EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF + // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) + // EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte // Unplanned Upgrade, aka Olantis - // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) // EIP6049FBlock: big.NewInt(13_524_557), // Deprecate SELFDESTRUCT // EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte @@ -128,6 +128,11 @@ var ( 512_000: common.HexToHash("0xd547c896967174295c61ea18534d3c69337a6fa6e957909dc29e4bcba873592a"), 1_878_299: common.HexToHash("0x1834091726bd0890539db04a22b673a6d9262d8b350dffaefdb10abc72e2113d"), }, + + // No go + EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. Hypra does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. + EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + TerminalTotalDifficulty: nil, // Ewwww } ) diff --git a/params/mutations/rewards_hypra.go b/params/mutations/rewards_hypra.go index e1b83a39e8..643e08e4aa 100644 --- a/params/mutations/rewards_hypra.go +++ b/params/mutations/rewards_hypra.go @@ -27,9 +27,7 @@ var ( func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncles []*types.Header, txs []*types.Transaction) (*big.Int, []*big.Int) { // Select the correct block minerReward based on chain progression - blockReward := ctypes.EthashBlockReward(config, header.Number) - - minerReward := new(big.Int).Set(blockReward) + minerReward := ctypes.EthashBlockReward(config, header.Number) uncleReward := new(big.Int).Set(UncleBlockReward) uncleCount := new(big.Int).SetUint64(uint64(len(uncles))) blockFeeReward := new(big.Int) From 8282bb9cc2926105fac30a2d5253fa7d5cbb3c26 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 7 Mar 2024 23:38:49 +0000 Subject: [PATCH 35/45] Revert "core: Symatically match Hypra Gaspar to enable EIP3860 EVM changes." This reverts commit 80e244db52cf8250abe9081ad0c82e62327eb731. --- cmd/evm/internal/t8ntool/transaction.go | 8 +++----- core/state_transition.go | 22 +++++++++------------- light/txpool.go | 5 +---- params/config_hypra.go | 10 +++++----- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 94c4e17cbf..39e86304f0 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -20,7 +20,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ethereum/go-ethereum/params" "math/big" "os" "strings" @@ -146,12 +145,11 @@ func Transaction(ctx *cli.Context) error { eip2f := chainConfig.IsEnabled(chainConfig.GetEIP2Transition, new(big.Int)) eip2028f := chainConfig.IsEnabled(chainConfig.GetEIP2028Transition, new(big.Int)) zero := uint64(0) - eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || - chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int)) && - chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this + eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int)) // Check intrinsic gas - if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, eip2f, eip2028f, eip3860f); err != nil { + if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, + eip2f, eip2028f, eip3860f); err != nil { r.Error = err results = append(results, r) continue diff --git a/core/state_transition.go b/core/state_transition.go index 8cf7feb5c9..0aa7af9f04 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -19,7 +19,6 @@ package core import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/params" "math" "math/big" @@ -377,38 +376,35 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { msg = st.msg sender = vm.AccountRef(msg.From) contractCreation = msg.To == nil - chainConfig = st.evm.ChainConfig() // EIP-2: Homestead - eip2f = chainConfig.IsEnabled(chainConfig.GetEIP2Transition, st.evm.Context.BlockNumber) + eip2f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2Transition, st.evm.Context.BlockNumber) // Istanbul // https://eips.ethereum.org/EIPS/eip-1679 // EIP-2028: Calldata gas cost reduction - eip2028f = chainConfig.IsEnabled(chainConfig.GetEIP2028Transition, st.evm.Context.BlockNumber) + eip2028f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2028Transition, st.evm.Context.BlockNumber) // Berlin // https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md // EIP-2930: Optional access lists - eip2930f = chainConfig.IsEnabled(chainConfig.GetEIP2930Transition, st.evm.Context.BlockNumber) + eip2930f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP2930Transition, st.evm.Context.BlockNumber) // London // https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md // EIP-1559: Fee market change: burn fee and tips - eip1559f = chainConfig.IsEnabled(chainConfig.GetEIP1559Transition, st.evm.Context.BlockNumber) + eip1559f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP1559Transition, st.evm.Context.BlockNumber) // EIP-3529: Reduction in refunds - eip3529f = chainConfig.IsEnabled(chainConfig.GetEIP3529Transition, st.evm.Context.BlockNumber) && - chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this + eip3529f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3529Transition, st.evm.Context.BlockNumber) // EIP-3860: Limit and meter initcode - eip3860f = chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &st.evm.Context.Time) || - chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, st.evm.Context.BlockNumber) && - chainConfig.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this + eip3860f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3860TransitionTime, &st.evm.Context.Time) || + st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3860Transition, st.evm.Context.BlockNumber) // EIP-3651: Warm coinbase - eip3651f = chainConfig.IsEnabledByTime(chainConfig.GetEIP3651TransitionTime, &st.evm.Context.Time) || - chainConfig.IsEnabled(chainConfig.GetEIP3651Transition, st.evm.Context.BlockNumber) + eip3651f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3651TransitionTime, &st.evm.Context.Time) || + st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3651Transition, st.evm.Context.BlockNumber) ) // Check clauses 4-5, subtract intrinsic gas if everything is correct diff --git a/light/txpool.go b/light/txpool.go index f64c29cb99..688cc7493f 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -19,7 +19,6 @@ package light import ( "context" "fmt" - "github.com/ethereum/go-ethereum/params" "math/big" "sync" "time" @@ -340,9 +339,7 @@ func (pool *TxPool) setNewHead(head *types.Header) { pool.eip2028f = pool.config.IsEnabled(pool.config.GetEIP2028Transition, next) pool.eip2718 = pool.config.IsEnabled(pool.config.GetEIP2718Transition, next) now := uint64(time.Now().Unix()) - pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) || - pool.config.IsEnabled(pool.config.GetEIP3860Transition, next) && - pool.config.GetChainID().Uint64() != params.HypraChainId // Hypra did an oopsie and didn't fully enable EIP-3860, will be appended with another fork to TODO: fix this + pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) || pool.config.IsEnabled(pool.config.GetEIP3860Transition, next) } // Stop stops the light transaction pool diff --git a/params/config_hypra.go b/params/config_hypra.go index 0634e99ae9..7fa39190cd 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -53,6 +53,7 @@ var ( EIP212FBlock: big.NewInt(1001), EIP213FBlock: big.NewInt(1001), EIP214FBlock: big.NewInt(1001), + //EIP649FBlock: big.NewInt(1001), EIP658FBlock: big.NewInt(1001), // Constantinople eq @@ -87,14 +88,13 @@ var ( EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds - // London chain upgrades TX Type 2, aka Planned Eudora + // London chain upgrades, aka Planned Eudora // TODO: move block numbers closer once testing has concluded - // EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` - // EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF - // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) - // EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte + //EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` + //EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF // Unplanned Upgrade, aka Olantis + // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) // EIP6049FBlock: big.NewInt(13_524_557), // Deprecate SELFDESTRUCT // EIP3541FBlock: big.NewInt(13_524_557), // Reject new contract code starting with the 0xEF byte From 6a729000a53252e28ebad11de0376f0bce309aa5 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Thu, 7 Mar 2024 23:44:42 +0000 Subject: [PATCH 36/45] Define Gaspar fork block --- params/config_hypra.go | 3 +++ params/types/coregeth/chain_config.go | 3 +++ params/types/coregeth/chain_config_configurator.go | 12 ++++++++++++ params/types/ctypes/configurator_iface.go | 4 ++++ params/types/genesisT/genesis.go | 8 ++++++++ params/types/goethereum/goethereum_configurator.go | 8 ++++++++ 6 files changed, 38 insertions(+) diff --git a/params/config_hypra.go b/params/config_hypra.go index 7fa39190cd..3564c57e9d 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -82,6 +82,9 @@ var ( // Previously overlooked and unrewarded. HIPVeldinFBlock: big.NewInt(500_009), + //Gaspar fork was used to upgrade the EVM to include new opcodes and features. + HIPGasparFBlock: big.NewInt(1_600_957), + // London + shanghai EVM upgrade, aka Gaspar EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index a7fff8ef50..7786a254f0 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -272,6 +272,9 @@ type CoreGethChainConfig struct { // Veldin fork was used to enable rewards to miners for including uncle blocks on Hypra network. // Previously overlooked and unrewarded. HIPVeldinFBlock *big.Int `json:"hipveldinfblock,omitempty"` + + // Gaspar fork was used to upgrade the EVM to include new opcodes and features. + HIPGasparFBlock *big.Int `json:"hipgasparfblock,omitempty"` } // String implements the fmt.Stringer interface. diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index f316340524..7dc339f664 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -1344,3 +1344,15 @@ func (c *CoreGethChainConfig) SetHIPVeldinTransition(n *uint64) error { c.HIPVeldinFBlock = setBig(c.HIPVeldinFBlock, n) return nil } + +func (c *CoreGethChainConfig) GetHIPGasparTransition() *uint64 { + if c.GetChainID().Uint64() != 622277 { + return nil + } + return bigNewU64(c.HIPGasparFBlock) +} + +func (c *CoreGethChainConfig) SetHIPGasparTransition(n *uint64) error { + c.HIPGasparFBlock = setBig(c.HIPGasparFBlock, n) + return nil +} diff --git a/params/types/ctypes/configurator_iface.go b/params/types/ctypes/configurator_iface.go index 3e5e0f2835..66dd73b812 100644 --- a/params/types/ctypes/configurator_iface.go +++ b/params/types/ctypes/configurator_iface.go @@ -235,6 +235,10 @@ type ProtocolSpecifier interface { // Hypra Network Specific Veldin Fork for uncle rewards fix GetHIPVeldinTransition() *uint64 SetHIPVeldinTransition(n *uint64) error + + // Hypra Network Specific Gaspar Fork for EVM upgrade + GetHIPGasparTransition() *uint64 + SetHIPGasparTransition(n *uint64) error } type Forker interface { diff --git a/params/types/genesisT/genesis.go b/params/types/genesisT/genesis.go index 9cc430fd23..a3794e522b 100644 --- a/params/types/genesisT/genesis.go +++ b/params/types/genesisT/genesis.go @@ -1054,6 +1054,14 @@ func (g *Genesis) SetHIPVeldinTransition(n *uint64) error { return g.Config.SetHIPVeldinTransition(n) } +func (g *Genesis) GetHIPGasparTransition() *uint64 { + return g.Config.GetHIPGasparTransition() +} + +func (g *Genesis) SetHIPGasparTransition(n *uint64) error { + return g.Config.SetHIPGasparTransition(n) +} + func (g *Genesis) String() string { j, _ := json.MarshalIndent(g, "", " ") return "Genesis: " + string(j) diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index 491c180dcc..bb6609a968 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -1177,3 +1177,11 @@ func (c *ChainConfig) GetHIPVeldinTransition() *uint64 { func (c *ChainConfig) SetHIPVeldinTransition(_ *uint64) error { return ctypes.ErrUnsupportedConfigNoop } + +func (c *ChainConfig) GetHIPGasparTransition() *uint64 { + return nil +} + +func (c *ChainConfig) SetHIPGasparTransition(_ *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} From 6f6fdbda484f8373de66cd8eea33cc4d8d7e821d Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Fri, 8 Mar 2024 00:14:43 +0000 Subject: [PATCH 37/45] Gaspar EVM flags --- core/vm/jump_table.go | 8 ++++---- params/config_hypra.go | 8 ++++---- params/confp/configurator.go | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 9901eb03a9..4719bb63f1 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -187,10 +187,10 @@ func instructionSetForConfig(config ctypes.ChainConfigurator, isPostMerge bool, if config.IsEnabled(config.GetEIP2929Transition, bn) { enable2929(instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929 } - if config.IsEnabled(config.GetEIP3529Transition, bn) { + if config.IsEnabled(config.GetEIP3529Transition, bn) || config.IsEnabled(config.GetHIPGasparTransition, bn) { enable3529(instructionSet) // Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529 } - if config.IsEnabled(config.GetEIP3198Transition, bn) { + if config.IsEnabled(config.GetEIP3198Transition, bn) || config.IsEnabled(config.GetHIPGasparTransition, bn) { enable3198(instructionSet) // BASEFEE opcode https://eips.ethereum.org/EIPS/eip-3198 } if isPostMerge || config.IsEnabled(config.GetEIP4399Transition, bn) { // EIP4399: Supplant DIFFICULTY opcode with PREVRANDAO (ETH @ PoS) @@ -203,10 +203,10 @@ func instructionSetForConfig(config ctypes.ChainConfigurator, isPostMerge bool, } // Shangai - if config.IsEnabledByTime(config.GetEIP3855TransitionTime, bt) || config.IsEnabled(config.GetEIP3855Transition, bn) { + if config.IsEnabledByTime(config.GetEIP3855TransitionTime, bt) || config.IsEnabled(config.GetEIP3855Transition, bn) || config.IsEnabled(config.GetHIPGasparTransition, bn) { enable3855(instructionSet) // PUSH0 instruction } - if config.IsEnabledByTime(config.GetEIP3860TransitionTime, bt) || config.IsEnabled(config.GetEIP3860Transition, bn) { + if config.IsEnabledByTime(config.GetEIP3860TransitionTime, bt) || config.IsEnabled(config.GetEIP3860Transition, bn) || config.IsEnabled(config.GetHIPGasparTransition, bn) { enable3860(instructionSet) // Limit and meter initcode } diff --git a/params/config_hypra.go b/params/config_hypra.go index 3564c57e9d..d65dd1dc2b 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -86,10 +86,10 @@ var ( HIPGasparFBlock: big.NewInt(1_600_957), // London + shanghai EVM upgrade, aka Gaspar - EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction - EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode - EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode - EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds + //EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction + //EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode + //EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode + //EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds // London chain upgrades, aka Planned Eudora // TODO: move block numbers closer once testing has concluded diff --git a/params/confp/configurator.go b/params/confp/configurator.go index a420c3c719..6b03cf075b 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -41,6 +41,7 @@ var ( incompatibleNetworkNameMap = map[uint64][]string{ 622277: { "HIPVeldin", // Custom fork not used in forkId + "HIPGaspar", // Custom fork not used in forkId "EIP3855", // Enabled on Hypra via Gaspar fork "EIP3860", // Enabled on Hypra via Gaspar fork "EIP3198", // Enabled on Hypra via Gaspar fork From 655cbb2ffa5f228313ed9a98ee41d261e2ccaead Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Fri, 8 Mar 2024 00:25:26 +0000 Subject: [PATCH 38/45] Change reward assignment to fix merkle root. --- params/mutations/rewards_hypra.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/params/mutations/rewards_hypra.go b/params/mutations/rewards_hypra.go index 643e08e4aa..e1b83a39e8 100644 --- a/params/mutations/rewards_hypra.go +++ b/params/mutations/rewards_hypra.go @@ -27,7 +27,9 @@ var ( func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncles []*types.Header, txs []*types.Transaction) (*big.Int, []*big.Int) { // Select the correct block minerReward based on chain progression - minerReward := ctypes.EthashBlockReward(config, header.Number) + blockReward := ctypes.EthashBlockReward(config, header.Number) + + minerReward := new(big.Int).Set(blockReward) uncleReward := new(big.Int).Set(UncleBlockReward) uncleCount := new(big.Int).SetUint64(uint64(len(uncles))) blockFeeReward := new(big.Int) From 7a2a9e0bbef8d1f79da47da4df34eb4dee157cab Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 10 Mar 2024 09:08:04 +0000 Subject: [PATCH 39/45] Params: Move shanghai fork blocks. --- README.md | 2 +- cmd/utils/flags.go | 5 +---- params/config_hypra.go | 14 ++++++-------- params/confp/configurator.go | 1 - params/mutations/rewards_test.go | 3 ++- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 3cb852b0dc..d6f53c5b63 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Networks supported by the respective go-ethereum packaged `geth` program. | Ticker | Consensus | Network | core-geth | ethereum/go-ethereum | |--------|-------------------|---------------------------------------| --- | --- | -| ETC | :zap: Ethash | Ethereum Classic | :heavy_check_mark: | | +| ETC | :zap: Etchash | Ethereum Classic | :heavy_check_mark: | | | ETH | :zap: Ethash | Ethereum (Foundation) | :heavy_check_mark: | :heavy_check_mark: | | - | :zap: :handshake: | Private chains | :heavy_check_mark: | :heavy_check_mark: | | | :zap: | Mordor (Geth+Parity ETH PoW Testnet) | :heavy_check_mark: | | diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index c7125c1bcf..2f1aea3959 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2604,7 +2604,6 @@ func makeConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Gen ethashConfig.PowMode = ethash.ModePoissonFake } engine = ethconfig.CreateConsensusEngineEthash(stack, ðashConfig, nil, false) - break case ctypes.ConsensusEngineT_EthashB3: ethashb3Config := ethconfig.Defaults.EthashB3 @@ -2614,7 +2613,6 @@ func makeConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Gen ethashb3Config.PowMode = ethashb3.ModePoissonFake } engine = ethconfig.CreateConsensusEngineEthashB3(stack, ðashb3Config, nil, false) - break case ctypes.ConsensusEngineT_Clique: cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec) @@ -2622,7 +2620,6 @@ func makeConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Gen Fatalf("%v", err) } engine = ethconfig.CreateConsensusEngineClique(cliqueConfig, chainDb) - break case ctypes.ConsensusEngineT_Lyra2: var lyra2Config *lyra2.Config @@ -2630,7 +2627,7 @@ func makeConsensusEngine(ctx *cli.Context, stack *node.Node, gspec *genesisT.Gen lyra2Config = &lyra2.Config{} } engine = ethconfig.CreateConsensusEngineLyra2(lyra2Config, nil, false) - break + } return engine diff --git a/params/config_hypra.go b/params/config_hypra.go index d65dd1dc2b..d3e87c70fc 100644 --- a/params/config_hypra.go +++ b/params/config_hypra.go @@ -85,16 +85,15 @@ var ( //Gaspar fork was used to upgrade the EVM to include new opcodes and features. HIPGasparFBlock: big.NewInt(1_600_957), - // London + shanghai EVM upgrade, aka Gaspar - //EIP3855FBlock: big.NewInt(1_600_957), // PUSH0 instruction - //EIP3860FBlock: big.NewInt(1_600_957), // Limit and meter initcode - //EIP3198FBlock: big.NewInt(1_600_957), // BASEFEE Opcode - //EIP3529FBlock: big.NewInt(1_600_957), // Reduction in refunds - - // London chain upgrades, aka Planned Eudora + // London + shanghai chain upgrades, aka Planned Eudora // TODO: move block numbers closer once testing has concluded + //HIPEudoraFBlock: big.NewInt(13_524_557), // Hypra planned TX rewards change //EIP1559FBlock: big.NewInt(13_524_557), // EIP-1559 transactions` //EIP3541FBlock: big.NewInt(13_524_557), // EIP-3541 Reject code starting with 0xEF + //EIP3855FBlock: big.NewInt(13_524_557), // PUSH0 instruction + //EIP3860FBlock: big.NewInt(13_524_557), // Limit and meter initcode + //EIP3198FBlock: big.NewInt(13_524_557), // BASEFEE Opcode + //EIP3529FBlock: big.NewInt(13_524_557), // Reduction in refunds // Unplanned Upgrade, aka Olantis // EIP3651FBlock: big.NewInt(13_524_557), // Warm COINBASE (gas reprice) @@ -107,7 +106,6 @@ var ( // Dummy EIPs, unused by ethashb3 but used by forkid EIP3554FBlock: big.NewInt(13_524_557), - EIP3541FBlock: big.NewInt(13_524_557), //EIP4345FBlock: big.NewInt(27_200_177), //EIP5133FBlock: big.NewInt(40_725_107), diff --git a/params/confp/configurator.go b/params/confp/configurator.go index 6b03cf075b..18657f4a2b 100644 --- a/params/confp/configurator.go +++ b/params/confp/configurator.go @@ -66,7 +66,6 @@ func networkSignalsCompatibility(netId uint64, name string) bool { } } return false - } var ( diff --git a/params/mutations/rewards_test.go b/params/mutations/rewards_test.go index f721326fd8..3f3fce4d4b 100644 --- a/params/mutations/rewards_test.go +++ b/params/mutations/rewards_test.go @@ -386,6 +386,7 @@ func TestAccumulateRewards(t *testing.T) { } var header *types.Header = &types.Header{} + var txs []*types.Transaction = []*types.Transaction{} var uncles []*types.Header = []*types.Header{{}, {}} if i == 0 { @@ -443,7 +444,7 @@ func TestAccumulateRewards(t *testing.T) { totalB.Add(totalB, &blockWinner) - AccumulateRewards(config, stateDB, header, uncles) + AccumulateRewards(config, stateDB, header, uncles, txs) // Check balances. // t.Logf("config=%d block=%d era=%d w:%d u1:%d u2:%d", i, bn, new(big.Int).Add(era, big.NewInt(1)), blockWinner, uncleMiner1, uncleMiner2) From 4ce638dcac6d3ddb6b826ab8a2c3c4abde30aae3 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 10 Mar 2024 09:36:18 +0000 Subject: [PATCH 40/45] Params: unnecessary blank assignment --- params/mutations/rewards_hypra.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/mutations/rewards_hypra.go b/params/mutations/rewards_hypra.go index e1b83a39e8..84a74b25a5 100644 --- a/params/mutations/rewards_hypra.go +++ b/params/mutations/rewards_hypra.go @@ -53,7 +53,7 @@ func GetRewardsHypra(config ctypes.ChainConfigurator, header *types.Header, uncl } uncleRewards := make([]*big.Int, len(uncles)) - for i, _ := range uncles { + for i := range uncles { uncleRewards[i] = uncleReward if config.IsEnabled(config.GetHIPVeldinTransition, header.Number) { From 809bc534d46ee7ca3e2cbc580db2c5ff4e5f64f2 Mon Sep 17 00:00:00 2001 From: Yoshiki Date: Fri, 12 Apr 2024 10:49:57 +0200 Subject: [PATCH 41/45] Update --- .golangci.yml | 3 ++- cmd/devp2p/nodesetcmd.go | 3 ++- cmd/utils/flags.go | 11 ++++++----- consensus/ethashb3/ethash.go | 12 ++++++++---- core/forkid/forkid_test.go | 8 ++++---- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 3a3b4e0fbf..96783dbd6b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,6 +12,7 @@ run: - params/alloc_mintme.go - evmc/* + linters: disable-all: true enable: @@ -29,7 +30,7 @@ linters: - durationcheck - exportloopref - whitespace - + - # - structcheck # lots of false positives # - errcheck #lot of false positives # - contextcheck diff --git a/cmd/devp2p/nodesetcmd.go b/cmd/devp2p/nodesetcmd.go index abca82cb4b..78942217c7 100644 --- a/cmd/devp2p/nodesetcmd.go +++ b/cmd/devp2p/nodesetcmd.go @@ -247,7 +247,8 @@ func ethFilter(args []string) (nodeFilter, error) { gb := core.GenesisToBlock(params.DefaultMintMeGenesisBlock(), nil) filter = forkid.NewStaticFilter(params.MintMeChainConfig, gb) case "hypra": - filter = forkid.NewStaticFilter(params.HypraChainConfig, params.HypraGenesisHash) + gb := core.GenesisToBlock(params.DefaultHypraGenesisBlock(), nil) + filter = forkid.NewStaticFilter(params.HypraChainConfig, gb) default: return nil, fmt.Errorf("unknown network %q", args[0]) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 58cbd497eb..fe0770a127 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -23,9 +23,6 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethashb3" - "github.com/ethereum/go-ethereum/params/types/ctypes" "math" "math/big" "net" @@ -39,6 +36,10 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/ethashb3" + "github.com/ethereum/go-ethereum/params/types/ctypes" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -1227,8 +1228,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls = params.ClassicBootnodes case ctx.Bool(MintMeFlag.Name): urls = params.MintMeBootnodes - case ctx.Bool(HypraFlag.Name): - urls = params.HypraBootnodes + case ctx.Bool(HypraFlag.Name): + urls = params.HypraBootnodes case ctx.Bool(MordorFlag.Name): urls = params.MordorBootnodes case ctx.Bool(SepoliaFlag.Name): diff --git a/consensus/ethashb3/ethash.go b/consensus/ethashb3/ethash.go index a77fd66d36..24c17370b0 100644 --- a/consensus/ethashb3/ethash.go +++ b/consensus/ethashb3/ethash.go @@ -603,7 +603,7 @@ func New(config Config, notify []string, noverify bool) *EthashB3 { caches: newlru(config.CachesInMem, newCache), datasets: newlru(config.DatasetsInMem, newDataset), update: make(chan struct{}), - hashrate: metrics.NewMeterForced(), + hashrate: metrics.NewMeter(), } if config.PowMode == ModeShared { ethash.shared = sharedEthash @@ -789,7 +789,8 @@ func (ethashb3 *EthashB3) SetThreads(threads int) { func (ethashb3 *EthashB3) Hashrate() float64 { // Short circuit if we are run the ethashb3 in normal/test mode. if ethashb3.config.PowMode != ModeNormal && ethashb3.config.PowMode != ModeTest { - return ethashb3.hashrate.Rate1() + ms := ethashb3.hashrate.Snapshot() + return ms.Rate1() } var res = make(chan uint64, 1) @@ -797,11 +798,14 @@ func (ethashb3 *EthashB3) Hashrate() float64 { case ethashb3.remote.fetchRateCh <- res: case <-ethashb3.remote.exitCh: // Return local hashrate only if ethashb3 is stopped. - return ethashb3.hashrate.Rate1() + ms := ethashb3.hashrate.Snapshot() + return ms.Rate1() + } // Gather total submitted hash rate of remote sealers. - return ethashb3.hashrate.Rate1() + float64(<-res) + ms := ethashb3.hashrate.Snapshot() + return ms.Rate1() + float64(<-res) } // APIs implements consensus.Engine, returning the user facing RPC APIs. diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index b77b36a83c..3b701970cf 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -220,10 +220,10 @@ func TestCreation(t *testing.T) { }, }, { - name: "Hypra", - config: params.HypraChainConfig, - genesis: params.HypraGenesisHash, - cases: []testcase{ + "Hypra", + params.HypraChainConfig, + core.GenesisToBlock(params.DefaultHypraGenesisBlock(), nil), + []testcase{ {0, 0, ID{Hash: checksumToBytes(0x61aefa70), Next: 1001}}, {1000, 0, ID{Hash: checksumToBytes(0x61aefa70), Next: 1001}}, {1001, 0, ID{Hash: checksumToBytes(0x7cc30c12), Next: 5503}}, From 2787cb6966a31949fe0424a04fdac0f01db8306f Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 16 Jun 2024 16:17:07 +0100 Subject: [PATCH 42/45] run toml generate --- eth/ethconfig/gen_config.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 11a08d71e6..99413bf7ad 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/consensus/ethashb3" "github.com/ethereum/go-ethereum/core/txpool/blobpool" "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/eth/downloader" @@ -55,6 +56,7 @@ func (c Config) MarshalTOML() (interface{}, error) { FilterLogCacheSize int Miner miner.Config Ethash ethash.Config + EthashB3 ethashb3.Config TxPool legacypool.Config BlobPool blobpool.Config GPO gasprice.Config @@ -111,6 +113,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.FilterLogCacheSize = c.FilterLogCacheSize enc.Miner = c.Miner enc.Ethash = c.Ethash + enc.EthashB3 = c.EthashB3 enc.TxPool = c.TxPool enc.BlobPool = c.BlobPool enc.GPO = c.GPO @@ -171,6 +174,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { FilterLogCacheSize *int Miner *miner.Config Ethash *ethash.Config + EthashB3 *ethashb3.Config TxPool *legacypool.Config BlobPool *blobpool.Config GPO *gasprice.Config @@ -302,6 +306,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.Ethash != nil { c.Ethash = *dec.Ethash } + if dec.EthashB3 != nil { + c.EthashB3 = *dec.EthashB3 + } if dec.TxPool != nil { c.TxPool = *dec.TxPool } From 8170edde1fdd611b1f24fbd1a0a481e64d506da9 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 16 Jun 2024 17:00:26 +0100 Subject: [PATCH 43/45] ethconfig - Fix sync issues due to conflicting ethash and ethhasb3 being created. --- eth/backend.go | 989 ++++++++++++++++++++-------------------- eth/ethconfig/config.go | 623 +++++++++++++------------ 2 files changed, 815 insertions(+), 797 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index fcdde13d8d..30977985a5 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -18,50 +18,48 @@ package eth import ( - "errors" - "fmt" - "math/big" - "runtime" - "sync" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/lyra2" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/pruner" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/txpool/blobpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/shutdowncheck" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/dnsdisc" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/params/types/coregeth" - "github.com/ethereum/go-ethereum/params/types/ctypes" - "github.com/ethereum/go-ethereum/params/types/goethereum" - "github.com/ethereum/go-ethereum/params/vars" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" + "errors" + "fmt" + "math/big" + "runtime" + "sync" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/clique" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state/pruner" + "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/txpool/blobpool" + "github.com/ethereum/go-ethereum/core/txpool/legacypool" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/eth/protocols/eth" + "github.com/ethereum/go-ethereum/eth/protocols/snap" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/internal/shutdowncheck" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/miner" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/dnsdisc" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/params/types/coregeth" + "github.com/ethereum/go-ethereum/params/types/goethereum" + "github.com/ethereum/go-ethereum/params/vars" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" ) // Config contains the configuration options of the ETH protocol. @@ -70,339 +68,340 @@ type Config = ethconfig.Config // Ethereum implements the Ethereum full node service. type Ethereum struct { - config *ethconfig.Config + config *ethconfig.Config - // Handlers - txPool *txpool.TxPool + // Handlers + txPool *txpool.TxPool - blockchain *core.BlockChain - handler *handler - ethDialCandidates enode.Iterator - snapDialCandidates enode.Iterator - merger *consensus.Merger + blockchain *core.BlockChain + handler *handler + ethDialCandidates enode.Iterator + snapDialCandidates enode.Iterator + merger *consensus.Merger - // DB interfaces - chainDb ethdb.Database // Block chain database + // DB interfaces + chainDb ethdb.Database // Block chain database - eventMux *event.TypeMux - engine consensus.Engine - accountManager *accounts.Manager + eventMux *event.TypeMux + engine consensus.Engine + accountManager *accounts.Manager - bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests - bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports - closeBloomHandler chan struct{} + bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests + bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports + closeBloomHandler chan struct{} - APIBackend *EthAPIBackend + APIBackend *EthAPIBackend - miner *miner.Miner - gasPrice *big.Int - etherbase common.Address + miner *miner.Miner + gasPrice *big.Int + etherbase common.Address - networkID uint64 - netRPCService *ethapi.NetAPI + networkID uint64 + netRPCService *ethapi.NetAPI - p2pServer *p2p.Server + p2pServer *p2p.Server - lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) + lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) - shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully + shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully } // New creates a new Ethereum object (including the // initialisation of the common Ethereum object) func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { - // Ensure configuration values are compatible and sane - if config.SyncMode == downloader.LightSync { - return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") - } - if !config.SyncMode.IsValid() { - return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) - } - if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { - log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) - config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) - } - if config.NoPruning && config.TrieDirtyCache > 0 { - if config.SnapshotCache > 0 { - config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 - config.SnapshotCache += config.TrieDirtyCache * 2 / 5 - } else { - config.TrieCleanCache += config.TrieDirtyCache - } - config.TrieDirtyCache = 0 - } - log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) - - // Assemble the Ethereum object - chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false) - if err != nil { - return nil, err - } - scheme, err := rawdb.ParseStateScheme(config.StateScheme, chainDb) - if err != nil { - return nil, err - } - // Try to recover offline state pruning only in hash-based. - if scheme == rawdb.HashScheme { - if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil { - log.Error("Failed to recover state", "error", err) - } - } - // Transfer mining-related config to the ethash config. - ethashConfig := config.Ethash - ethashb3Config := config.EthashB3 - ethashConfig.NotifyFull = config.Miner.NotifyFull - - if config.Genesis != nil && config.Genesis.Config != nil { - ethashConfig.ECIP1099Block = config.Genesis.GetEthashECIP1099Transition() - } - - cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis) - if err != nil { - return nil, err - } - - var lyra2Config *lyra2.Config - if config.Genesis != nil && config.Genesis.Config != nil { - if config.Genesis.Config.GetConsensusEngineType() == ctypes.ConsensusEngineT_Lyra2 { - lyra2Config = &lyra2.Config{} - } - } - - engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, ðashb3Config, cliqueConfig, lyra2Config, config.Miner.Notify, config.Miner.Noverify, chainDb) - - chainConfig, err := core.LoadChainConfig(chainDb, config.Genesis) - if err != nil { - return nil, err - } - networkID := config.NetworkId - if networkID == 0 { - networkID = chainConfig.GetChainID().Uint64() - } - eth := &Ethereum{ - config: config, - merger: consensus.NewMerger(chainDb), - chainDb: chainDb, - eventMux: stack.EventMux(), - accountManager: stack.AccountManager(), - engine: engine, - closeBloomHandler: make(chan struct{}), - networkID: networkID, - gasPrice: config.Miner.GasPrice, - etherbase: config.Miner.Etherbase, - bloomRequests: make(chan chan *bloombits.Retrieval), - bloomIndexer: core.NewBloomIndexer(chainDb, vars.BloomBitsBlocks, vars.BloomConfirms), - p2pServer: stack.Server(), - shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), - } - bcVersion := rawdb.ReadDatabaseVersion(chainDb) - var dbVer = "" - if bcVersion != nil { - dbVer = fmt.Sprintf("%d", *bcVersion) - } - log.Info("Initialising Ethereum protocol", "network", networkID, "dbversion", dbVer) - - if !config.SkipBcVersionCheck { - if bcVersion != nil && *bcVersion > core.BlockChainVersion { - return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) - } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { - if bcVersion != nil { // only print warning on upgrade, not on init - log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) - } - rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) - } - } - var ( - vmConfig = vm.Config{ - EnablePreimageRecording: config.EnablePreimageRecording, - EWASMInterpreter: config.EWASMInterpreter, - EVMInterpreter: config.EVMInterpreter, - } - cacheConfig = &core.CacheConfig{ - TrieCleanLimit: config.TrieCleanCache, - TrieCleanNoPrefetch: config.NoPrefetch, - TrieDirtyLimit: config.TrieDirtyCache, - TrieDirtyDisabled: config.NoPruning, - TrieTimeLimit: config.TrieTimeout, - SnapshotLimit: config.SnapshotCache, - Preimages: config.Preimages, - StateHistory: config.StateHistory, - StateScheme: scheme, - } - ) - // Override the chain config with provided settings. - var overrides core.ChainOverrides - if config.OverrideShanghai != nil { - overrides.OverrideShanghai = config.OverrideShanghai - } - if config.OverrideCancun != nil { - overrides.OverrideCancun = config.OverrideCancun - } - if config.OverrideVerkle != nil { - overrides.OverrideVerkle = config.OverrideVerkle - } - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory) - if err != nil { - return nil, err - } - eth.bloomIndexer.Start(eth.blockchain) - // Handle artificial finality config override cases. - if n := config.OverrideECBP1100; n != nil { - if err := eth.blockchain.Config().SetECBP1100Transition(n); err != nil { - return nil, err - } - } - if n := config.OverrideECBP1100Deactivate; n != nil { - if err := eth.blockchain.Config().SetECBP1100DeactivateTransition(n); err != nil { - return nil, err - } - } - - if config.ECBP1100NoDisable != nil { - if *config.ECBP1100NoDisable { - eth.blockchain.ArtificialFinalityNoDisable(1) - } - } - - if config.BlobPool.Datadir != "" { - config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir) - } - blobPool := blobpool.New(config.BlobPool, eth.blockchain) - - if config.TxPool.Journal != "" { - config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) - } - legacyPool := legacypool.New(config.TxPool, eth.blockchain) - - eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool}) - if err != nil { - return nil, err - } - // Permit the downloader to use the trie cache allowance during fast sync - cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit - checkpoint := config.Checkpoint - if checkpoint == nil { - if p, ok := eth.blockchain.Config().(*coregeth.CoreGethChainConfig); ok { - checkpoint = p.TrustedCheckpoint - } else if p, ok := eth.blockchain.Config().(*goethereum.ChainConfig); ok { - checkpoint = p.TrustedCheckpoint - } - } - if eth.handler, err = newHandler(&handlerConfig{ - Database: chainDb, - Chain: eth.blockchain, - TxPool: eth.txPool, - Merger: eth.merger, - Network: networkID, - Sync: config.SyncMode, - BloomCache: uint64(cacheLimit), - EventMux: eth.eventMux, - Checkpoint: checkpoint, - RequiredBlocks: config.RequiredBlocks, - }); err != nil { - return nil, err - } - - eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock) - eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) - - eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} - if eth.APIBackend.allowUnprotectedTxs { - log.Info("Unprotected transactions allowed") - } - gpoParams := config.GPO - if gpoParams.Default == nil { - gpoParams.Default = config.Miner.GasPrice - } - eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) - - // Setup DNS discovery iterators. - dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) - eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) - if err != nil { - return nil, err - } - eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) - if err != nil { - return nil, err - } - - // Start the RPC service - eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID) - - // Register the backend on the node - stack.RegisterAPIs(eth.APIs()) - stack.RegisterProtocols(eth.Protocols()) - stack.RegisterLifecycle(eth) - - // Successful startup; push a marker and check previous unclean shutdowns. - eth.shutdownTracker.MarkStartup() - - return eth, nil + // Ensure configuration values are compatible and sane + if config.SyncMode == downloader.LightSync { + return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") + } + if !config.SyncMode.IsValid() { + return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) + } + if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { + log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) + config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) + } + if config.NoPruning && config.TrieDirtyCache > 0 { + if config.SnapshotCache > 0 { + config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 + config.SnapshotCache += config.TrieDirtyCache * 2 / 5 + } else { + config.TrieCleanCache += config.TrieDirtyCache + } + config.TrieDirtyCache = 0 + } + log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) + + // Assemble the Ethereum object + chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false) + if err != nil { + return nil, err + } + scheme, err := rawdb.ParseStateScheme(config.StateScheme, chainDb) + if err != nil { + return nil, err + } + // Try to recover offline state pruning only in hash-based. + if scheme == rawdb.HashScheme { + if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil { + log.Error("Failed to recover state", "error", err) + } + } + // // Transfer mining-related config to the ethash config. + // ethashConfig := config.Ethash + // ethashb3Config := config.EthashB3 + // ethashConfig.NotifyFull = config.Miner.NotifyFull + // + // if config.Genesis != nil && config.Genesis.Config != nil { + // ethashConfig.ECIP1099Block = config.Genesis.GetEthashECIP1099Transition() + // } + // + // cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis) + // if err != nil { + // return nil, err + // } + // + // var lyra2Config *lyra2.Config + // if config.Genesis != nil && config.Genesis.Config != nil { + // if config.Genesis.Config.GetConsensusEngineType() == ctypes.ConsensusEngineT_Lyra2 { + // lyra2Config = &lyra2.Config{} + // } + // } + + // engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, ðashb3Config, cliqueConfig, lyra2Config, config.Miner.Notify, config.Miner.Noverify, chainDb) + engine := ethconfig.CreateConsensusEngine(stack, config, chainDb) + + chainConfig, err := core.LoadChainConfig(chainDb, config.Genesis) + if err != nil { + return nil, err + } + networkID := config.NetworkId + if networkID == 0 { + networkID = chainConfig.GetChainID().Uint64() + } + eth := &Ethereum{ + config: config, + merger: consensus.NewMerger(chainDb), + chainDb: chainDb, + eventMux: stack.EventMux(), + accountManager: stack.AccountManager(), + engine: engine, + closeBloomHandler: make(chan struct{}), + networkID: networkID, + gasPrice: config.Miner.GasPrice, + etherbase: config.Miner.Etherbase, + bloomRequests: make(chan chan *bloombits.Retrieval), + bloomIndexer: core.NewBloomIndexer(chainDb, vars.BloomBitsBlocks, vars.BloomConfirms), + p2pServer: stack.Server(), + shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), + } + bcVersion := rawdb.ReadDatabaseVersion(chainDb) + var dbVer = "" + if bcVersion != nil { + dbVer = fmt.Sprintf("%d", *bcVersion) + } + log.Info("Initialising Ethereum protocol", "network", networkID, "dbversion", dbVer) + + if !config.SkipBcVersionCheck { + if bcVersion != nil && *bcVersion > core.BlockChainVersion { + return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) + } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { + if bcVersion != nil { // only print warning on upgrade, not on init + log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) + } + rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) + } + } + var ( + vmConfig = vm.Config{ + EnablePreimageRecording: config.EnablePreimageRecording, + EWASMInterpreter: config.EWASMInterpreter, + EVMInterpreter: config.EVMInterpreter, + } + cacheConfig = &core.CacheConfig{ + TrieCleanLimit: config.TrieCleanCache, + TrieCleanNoPrefetch: config.NoPrefetch, + TrieDirtyLimit: config.TrieDirtyCache, + TrieDirtyDisabled: config.NoPruning, + TrieTimeLimit: config.TrieTimeout, + SnapshotLimit: config.SnapshotCache, + Preimages: config.Preimages, + StateHistory: config.StateHistory, + StateScheme: scheme, + } + ) + // Override the chain config with provided settings. + var overrides core.ChainOverrides + if config.OverrideShanghai != nil { + overrides.OverrideShanghai = config.OverrideShanghai + } + if config.OverrideCancun != nil { + overrides.OverrideCancun = config.OverrideCancun + } + if config.OverrideVerkle != nil { + overrides.OverrideVerkle = config.OverrideVerkle + } + eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory) + if err != nil { + return nil, err + } + eth.bloomIndexer.Start(eth.blockchain) + // Handle artificial finality config override cases. + if n := config.OverrideECBP1100; n != nil { + if err := eth.blockchain.Config().SetECBP1100Transition(n); err != nil { + return nil, err + } + } + if n := config.OverrideECBP1100Deactivate; n != nil { + if err := eth.blockchain.Config().SetECBP1100DeactivateTransition(n); err != nil { + return nil, err + } + } + + if config.ECBP1100NoDisable != nil { + if *config.ECBP1100NoDisable { + eth.blockchain.ArtificialFinalityNoDisable(1) + } + } + + if config.BlobPool.Datadir != "" { + config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir) + } + blobPool := blobpool.New(config.BlobPool, eth.blockchain) + + if config.TxPool.Journal != "" { + config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) + } + legacyPool := legacypool.New(config.TxPool, eth.blockchain) + + eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool}) + if err != nil { + return nil, err + } + // Permit the downloader to use the trie cache allowance during fast sync + cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit + checkpoint := config.Checkpoint + if checkpoint == nil { + if p, ok := eth.blockchain.Config().(*coregeth.CoreGethChainConfig); ok { + checkpoint = p.TrustedCheckpoint + } else if p, ok := eth.blockchain.Config().(*goethereum.ChainConfig); ok { + checkpoint = p.TrustedCheckpoint + } + } + if eth.handler, err = newHandler(&handlerConfig{ + Database: chainDb, + Chain: eth.blockchain, + TxPool: eth.txPool, + Merger: eth.merger, + Network: networkID, + Sync: config.SyncMode, + BloomCache: uint64(cacheLimit), + EventMux: eth.eventMux, + Checkpoint: checkpoint, + RequiredBlocks: config.RequiredBlocks, + }); err != nil { + return nil, err + } + + eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock) + eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) + + eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} + if eth.APIBackend.allowUnprotectedTxs { + log.Info("Unprotected transactions allowed") + } + gpoParams := config.GPO + if gpoParams.Default == nil { + gpoParams.Default = config.Miner.GasPrice + } + eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) + + // Setup DNS discovery iterators. + dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) + eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) + if err != nil { + return nil, err + } + eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) + if err != nil { + return nil, err + } + + // Start the RPC service + eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID) + + // Register the backend on the node + stack.RegisterAPIs(eth.APIs()) + stack.RegisterProtocols(eth.Protocols()) + stack.RegisterLifecycle(eth) + + // Successful startup; push a marker and check previous unclean shutdowns. + eth.shutdownTracker.MarkStartup() + + return eth, nil } func makeExtraData(extra []byte) []byte { - if len(extra) == 0 { - // create default extradata - extra, _ = rlp.EncodeToBytes([]interface{}{ - uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), - "CoreGeth", - runtime.Version(), - runtime.GOOS, - }) - } - if uint64(len(extra)) > vars.MaximumExtraDataSize { - log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", vars.MaximumExtraDataSize) - extra = nil - } - return extra + if len(extra) == 0 { + // create default extradata + extra, _ = rlp.EncodeToBytes([]interface{}{ + uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), + "CoreGeth", + runtime.Version(), + runtime.GOOS, + }) + } + if uint64(len(extra)) > vars.MaximumExtraDataSize { + log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", vars.MaximumExtraDataSize) + extra = nil + } + return extra } // APIs return the collection of RPC services the ethereum package offers. // NOTE, some of these services probably need to be moved to somewhere else. func (s *Ethereum) APIs() []rpc.API { - apis := ethapi.GetAPIs(s.APIBackend) - - // Append any APIs exposed explicitly by the consensus engine - apis = append(apis, s.engine.APIs(s.BlockChain())...) - - // Append all the local APIs and return - return append(apis, []rpc.API{ - { - Namespace: "eth", - Service: NewEthereumAPI(s), - }, { - Namespace: "miner", - Service: NewMinerAPI(s), - }, { - Namespace: "eth", - Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux), - }, { - Namespace: "admin", - Service: NewAdminAPI(s), - }, { - Namespace: "debug", - Service: NewDebugAPI(s), - }, { - Namespace: "net", - Service: s.netRPCService, - }, - }...) + apis := ethapi.GetAPIs(s.APIBackend) + + // Append any APIs exposed explicitly by the consensus engine + apis = append(apis, s.engine.APIs(s.BlockChain())...) + + // Append all the local APIs and return + return append(apis, []rpc.API{ + { + Namespace: "eth", + Service: NewEthereumAPI(s), + }, { + Namespace: "miner", + Service: NewMinerAPI(s), + }, { + Namespace: "eth", + Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux), + }, { + Namespace: "admin", + Service: NewAdminAPI(s), + }, { + Namespace: "debug", + Service: NewDebugAPI(s), + }, { + Namespace: "net", + Service: s.netRPCService, + }, + }...) } func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { - s.blockchain.ResetWithGenesisBlock(gb) + s.blockchain.ResetWithGenesisBlock(gb) } func (s *Ethereum) Etherbase() (eb common.Address, err error) { - s.lock.RLock() - etherbase := s.etherbase - s.lock.RUnlock() - - if etherbase != (common.Address{}) { - return etherbase, nil - } - return common.Address{}, errors.New("etherbase must be explicitly specified") + s.lock.RLock() + etherbase := s.etherbase + s.lock.RUnlock() + + if etherbase != (common.Address{}) { + return etherbase, nil + } + return common.Address{}, errors.New("etherbase must be explicitly specified") } // isLocalBlock checks whether the specified block is mined @@ -411,129 +410,129 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) { // We regard two types of accounts as local miner account: etherbase // and accounts specified via `txpool.locals` flag. func (s *Ethereum) isLocalBlock(header *types.Header) bool { - author, err := s.engine.Author(header) - if err != nil { - log.Warn("Failed to retrieve block author", "number", header.Number.Uint64(), "hash", header.Hash(), "err", err) - return false - } - // Check whether the given address is etherbase. - s.lock.RLock() - etherbase := s.etherbase - s.lock.RUnlock() - if author == etherbase { - return true - } - // Check whether the given address is specified by `txpool.local` - // CLI flag. - for _, account := range s.config.TxPool.Locals { - if account == author { - return true - } - } - return false + author, err := s.engine.Author(header) + if err != nil { + log.Warn("Failed to retrieve block author", "number", header.Number.Uint64(), "hash", header.Hash(), "err", err) + return false + } + // Check whether the given address is etherbase. + s.lock.RLock() + etherbase := s.etherbase + s.lock.RUnlock() + if author == etherbase { + return true + } + // Check whether the given address is specified by `txpool.local` + // CLI flag. + for _, account := range s.config.TxPool.Locals { + if account == author { + return true + } + } + return false } // shouldPreserve checks whether we should preserve the given block // during the chain reorg depending on whether the author of block // is a local account. func (s *Ethereum) shouldPreserve(header *types.Header) bool { - // The reason we need to disable the self-reorg preserving for clique - // is it can be probable to introduce a deadlock. - // - // e.g. If there are 7 available signers - // - // r1 A - // r2 B - // r3 C - // r4 D - // r5 A [X] F G - // r6 [X] - // - // In the round5, the in-turn signer E is offline, so the worst case - // is A, F and G sign the block of round5 and reject the block of opponents - // and in the round6, the last available signer B is offline, the whole - // network is stuck. - if _, ok := s.engine.(*clique.Clique); ok { - return false - } - return s.isLocalBlock(header) + // The reason we need to disable the self-reorg preserving for clique + // is it can be probable to introduce a deadlock. + // + // e.g. If there are 7 available signers + // + // r1 A + // r2 B + // r3 C + // r4 D + // r5 A [X] F G + // r6 [X] + // + // In the round5, the in-turn signer E is offline, so the worst case + // is A, F and G sign the block of round5 and reject the block of opponents + // and in the round6, the last available signer B is offline, the whole + // network is stuck. + if _, ok := s.engine.(*clique.Clique); ok { + return false + } + return s.isLocalBlock(header) } // SetEtherbase sets the mining reward address. func (s *Ethereum) SetEtherbase(etherbase common.Address) { - s.lock.Lock() - s.etherbase = etherbase - s.lock.Unlock() + s.lock.Lock() + s.etherbase = etherbase + s.lock.Unlock() - s.miner.SetEtherbase(etherbase) + s.miner.SetEtherbase(etherbase) } // StartMining starts the miner with the given number of CPU threads. If mining // is already running, this method adjust the number of threads allowed to use // and updates the minimum price required by the transaction pool. func (s *Ethereum) StartMining(threads int) error { - // Update the thread count within the consensus engine - type threaded interface { - SetThreads(threads int) - } - if th, ok := s.engine.(threaded); ok { - log.Info("Updated mining threads", "threads", threads) - if threads == 0 { - threads = -1 // Disable the miner from within - } - th.SetThreads(threads) - } - // If the miner was not running, initialize it - if !s.IsMining() { - // Propagate the initial price point to the transaction pool - s.lock.RLock() - price := s.gasPrice - s.lock.RUnlock() - s.txPool.SetGasTip(price) - - // Configure the local mining address - eb, err := s.Etherbase() - if err != nil { - log.Error("Cannot start mining without etherbase", "err", err) - return fmt.Errorf("etherbase missing: %v", err) - } - var cli *clique.Clique - if c, ok := s.engine.(*clique.Clique); ok { - cli = c - } else if cl, ok := s.engine.(*beacon.Beacon); ok { - if c, ok := cl.InnerEngine().(*clique.Clique); ok { - cli = c - } - } - if cli != nil { - wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) - if wallet == nil || err != nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %v", err) - } - cli.Authorize(eb, wallet.SignData) - } - // If mining is started, we can disable the transaction rejection mechanism - // introduced to speed sync times. - s.handler.enableSyncedFeatures() - - go s.miner.Start() - } - return nil + // Update the thread count within the consensus engine + type threaded interface { + SetThreads(threads int) + } + if th, ok := s.engine.(threaded); ok { + log.Info("Updated mining threads", "threads", threads) + if threads == 0 { + threads = -1 // Disable the miner from within + } + th.SetThreads(threads) + } + // If the miner was not running, initialize it + if !s.IsMining() { + // Propagate the initial price point to the transaction pool + s.lock.RLock() + price := s.gasPrice + s.lock.RUnlock() + s.txPool.SetGasTip(price) + + // Configure the local mining address + eb, err := s.Etherbase() + if err != nil { + log.Error("Cannot start mining without etherbase", "err", err) + return fmt.Errorf("etherbase missing: %v", err) + } + var cli *clique.Clique + if c, ok := s.engine.(*clique.Clique); ok { + cli = c + } else if cl, ok := s.engine.(*beacon.Beacon); ok { + if c, ok := cl.InnerEngine().(*clique.Clique); ok { + cli = c + } + } + if cli != nil { + wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) + if wallet == nil || err != nil { + log.Error("Etherbase account unavailable locally", "err", err) + return fmt.Errorf("signer missing: %v", err) + } + cli.Authorize(eb, wallet.SignData) + } + // If mining is started, we can disable the transaction rejection mechanism + // introduced to speed sync times. + s.handler.enableSyncedFeatures() + + go s.miner.Start() + } + return nil } // StopMining terminates the miner, both at the consensus engine level as well as // at the block creation level. func (s *Ethereum) StopMining() { - // Update the thread count within the consensus engine - type threaded interface { - SetThreads(threads int) - } - if th, ok := s.engine.(threaded); ok { - th.SetThreads(-1) - } - // Stop the block creating itself - s.miner.Stop() + // Update the thread count within the consensus engine + type threaded interface { + SetThreads(threads int) + } + if th, ok := s.engine.(threaded); ok { + th.SetThreads(-1) + } + // Stop the block creating itself + s.miner.Stop() } func (s *Ethereum) IsMining() bool { return s.miner.Mining() } @@ -547,7 +546,7 @@ func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) EthVersion() int { - return int(eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.config.ProtocolVersions, s.ethDialCandidates)[0].Version) + return int(eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.config.ProtocolVersions, s.ethDialCandidates)[0].Version) } func (s *Ethereum) NetVersion() uint64 { return s.networkID } func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } @@ -557,65 +556,65 @@ func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruni func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } func (s *Ethereum) Merger() *consensus.Merger { return s.merger } func (s *Ethereum) SyncMode() downloader.SyncMode { - mode, _ := s.handler.chainSync.modeAndLocalHead() - return mode + mode, _ := s.handler.chainSync.modeAndLocalHead() + return mode } // Protocols returns all the currently configured // network protocols to start. func (s *Ethereum) Protocols() []p2p.Protocol { - protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.config.ProtocolVersions, s.ethDialCandidates) - if s.config.SnapshotCache > 0 { - protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) - } - return protos + protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.config.ProtocolVersions, s.ethDialCandidates) + if s.config.SnapshotCache > 0 { + protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) + } + return protos } // Start implements node.Lifecycle, starting all internal goroutines needed by the // Ethereum protocol implementation. func (s *Ethereum) Start() error { - eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode()) - - // Start the bloom bits servicing goroutines - s.startBloomHandlers(vars.BloomBitsBlocks) - - // Regularly update shutdown marker - s.shutdownTracker.Start() - - // Figure out a max peers count based on the server limits - maxPeers := s.p2pServer.MaxPeers - if s.config.LightServ > 0 { - if s.config.LightPeers >= s.p2pServer.MaxPeers { - return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers) - } - maxPeers -= s.config.LightPeers - } - // Start the networking layer and the light server if requested - s.handler.Start(maxPeers) - return nil + eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode()) + + // Start the bloom bits servicing goroutines + s.startBloomHandlers(vars.BloomBitsBlocks) + + // Regularly update shutdown marker + s.shutdownTracker.Start() + + // Figure out a max peers count based on the server limits + maxPeers := s.p2pServer.MaxPeers + if s.config.LightServ > 0 { + if s.config.LightPeers >= s.p2pServer.MaxPeers { + return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers) + } + maxPeers -= s.config.LightPeers + } + // Start the networking layer and the light server if requested + s.handler.Start(maxPeers) + return nil } // Stop implements node.Lifecycle, terminating all internal goroutines used by the // Ethereum protocol. func (s *Ethereum) Stop() error { - // Stop all the peer-related stuff first. - s.ethDialCandidates.Close() - s.snapDialCandidates.Close() - s.handler.Stop() - - // Then stop everything else. - s.bloomIndexer.Close() - close(s.closeBloomHandler) - s.txPool.Close() - s.miner.Close() - s.blockchain.Stop() - s.engine.Close() - - // Clean shutdown marker as the last thing before closing db - s.shutdownTracker.Stop() - - s.chainDb.Close() - s.eventMux.Stop() - - return nil + // Stop all the peer-related stuff first. + s.ethDialCandidates.Close() + s.snapDialCandidates.Close() + s.handler.Stop() + + // Then stop everything else. + s.bloomIndexer.Close() + close(s.closeBloomHandler) + s.txPool.Close() + s.miner.Close() + s.blockchain.Stop() + s.engine.Close() + + // Clean shutdown marker as the last thing before closing db + s.shutdownTracker.Stop() + + s.chainDb.Close() + s.eventMux.Stop() + + return nil } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 4725b2f58c..5c7ba63afa 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -18,368 +18,387 @@ package ethconfig import ( - "github.com/ethereum/go-ethereum/consensus/ethashb3" - "os" - "os/user" - "path/filepath" - "runtime" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/consensus/lyra2" - "github.com/ethereum/go-ethereum/core/txpool/blobpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params/types/ctypes" - "github.com/ethereum/go-ethereum/params/types/genesisT" - "github.com/ethereum/go-ethereum/params/vars" + "github.com/ethereum/go-ethereum/consensus/ethashb3" + "github.com/ethereum/go-ethereum/core" + "os" + "os/user" + "path/filepath" + "runtime" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/clique" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/consensus/lyra2" + "github.com/ethereum/go-ethereum/core/txpool/blobpool" + "github.com/ethereum/go-ethereum/core/txpool/legacypool" + "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/miner" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params/types/ctypes" + "github.com/ethereum/go-ethereum/params/types/genesisT" + "github.com/ethereum/go-ethereum/params/vars" ) // FullNodeGPO contains default gasprice oracle settings for full node. var FullNodeGPO = gasprice.Config{ - Blocks: 20, - Percentile: 60, - MaxHeaderHistory: 1024, - MaxBlockHistory: 1024, - MaxPrice: gasprice.DefaultMaxPrice, - IgnorePrice: gasprice.DefaultIgnorePrice, + Blocks: 20, + Percentile: 60, + MaxHeaderHistory: 1024, + MaxBlockHistory: 1024, + MaxPrice: gasprice.DefaultMaxPrice, + IgnorePrice: gasprice.DefaultIgnorePrice, } // LightClientGPO contains default gasprice oracle settings for light client. var LightClientGPO = gasprice.Config{ - Blocks: 2, - Percentile: 60, - MaxHeaderHistory: 300, - MaxBlockHistory: 5, - MaxPrice: gasprice.DefaultMaxPrice, - IgnorePrice: gasprice.DefaultIgnorePrice, + Blocks: 2, + Percentile: 60, + MaxHeaderHistory: 300, + MaxBlockHistory: 5, + MaxPrice: gasprice.DefaultMaxPrice, + IgnorePrice: gasprice.DefaultIgnorePrice, } // Defaults contains default settings for use on the Ethereum main net. var Defaults = Config{ - SyncMode: downloader.SnapSync, - Ethash: ethash.Config{ - CacheDir: "ethash", - CachesInMem: 2, - CachesOnDisk: 3, - CachesLockMmap: false, - DatasetsInMem: 1, - DatasetsOnDisk: 2, - DatasetsLockMmap: false, - }, - - EthashB3: ethashb3.Config{ - CacheDir: "ethashb3", - CachesInMem: 2, - CachesOnDisk: 3, - CachesLockMmap: false, - DatasetsInMem: 1, - DatasetsOnDisk: 2, - DatasetsLockMmap: false, - }, - - NetworkId: 0, // enable auto configuration of networkID == chainID - ProtocolVersions: vars.DefaultProtocolVersions, - TxLookupLimit: 2350000, - TransactionHistory: 2350000, - StateHistory: vars.FullImmutabilityThreshold, - LightPeers: 100, - UltraLightFraction: 75, - DatabaseCache: 512, - TrieCleanCache: 154, - TrieDirtyCache: 256, - TrieTimeout: 60 * time.Minute, - SnapshotCache: 102, - FilterLogCacheSize: 32, - Miner: miner.DefaultConfig, - TxPool: legacypool.DefaultConfig, - BlobPool: blobpool.DefaultConfig, - RPCGasCap: 50000000, - RPCEVMTimeout: 5 * time.Second, - GPO: FullNodeGPO, - RPCTxFeeCap: 1, // 1 ether + SyncMode: downloader.SnapSync, + Ethash: ethash.Config{ + CacheDir: "ethash", + CachesInMem: 2, + CachesOnDisk: 3, + CachesLockMmap: false, + DatasetsInMem: 1, + DatasetsOnDisk: 2, + DatasetsLockMmap: false, + }, + + EthashB3: ethashb3.Config{ + CacheDir: "ethashb3", + CachesInMem: 2, + CachesOnDisk: 3, + CachesLockMmap: false, + DatasetsInMem: 1, + DatasetsOnDisk: 2, + DatasetsLockMmap: false, + }, + + NetworkId: 0, // enable auto configuration of networkID == chainID + ProtocolVersions: vars.DefaultProtocolVersions, + TxLookupLimit: 2350000, + TransactionHistory: 2350000, + StateHistory: vars.FullImmutabilityThreshold, + LightPeers: 100, + UltraLightFraction: 75, + DatabaseCache: 512, + TrieCleanCache: 154, + TrieDirtyCache: 256, + TrieTimeout: 60 * time.Minute, + SnapshotCache: 102, + FilterLogCacheSize: 32, + Miner: miner.DefaultConfig, + TxPool: legacypool.DefaultConfig, + BlobPool: blobpool.DefaultConfig, + RPCGasCap: 50000000, + RPCEVMTimeout: 5 * time.Second, + GPO: FullNodeGPO, + RPCTxFeeCap: 1, // 1 ether } func init() { - home := os.Getenv("HOME") - if home == "" { - if user, err := user.Current(); err == nil { - home = user.HomeDir - } - } - if runtime.GOOS == "darwin" { - Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "Ethash") - Defaults.EthashB3.DatasetDir = filepath.Join(home, "Library", "EthashB3") - } else if runtime.GOOS == "windows" { - localappdata := os.Getenv("LOCALAPPDATA") - if localappdata != "" { - Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "Ethash") - Defaults.EthashB3.DatasetDir = filepath.Join(localappdata, "EthashB3") - } else { - Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "Ethash") - Defaults.EthashB3.DatasetDir = filepath.Join(home, "AppData", "Local", "EthashB3") - } - } else { - Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethash") - Defaults.EthashB3.DatasetDir = filepath.Join(home, ".ethashb3") - } + home := os.Getenv("HOME") + if home == "" { + if user, err := user.Current(); err == nil { + home = user.HomeDir + } + } + if runtime.GOOS == "darwin" { + Defaults.Ethash.DatasetDir = filepath.Join(home, "Library", "Ethash") + Defaults.EthashB3.DatasetDir = filepath.Join(home, "Library", "EthashB3") + } else if runtime.GOOS == "windows" { + localappdata := os.Getenv("LOCALAPPDATA") + if localappdata != "" { + Defaults.Ethash.DatasetDir = filepath.Join(localappdata, "Ethash") + Defaults.EthashB3.DatasetDir = filepath.Join(localappdata, "EthashB3") + } else { + Defaults.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "Ethash") + Defaults.EthashB3.DatasetDir = filepath.Join(home, "AppData", "Local", "EthashB3") + } + } else { + Defaults.Ethash.DatasetDir = filepath.Join(home, ".ethash") + Defaults.EthashB3.DatasetDir = filepath.Join(home, ".ethashb3") + } } //go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go // Config contains configuration options for ETH and LES protocols. type Config struct { - // The genesis block, which is inserted if the database is empty. - // If nil, the Ethereum main net block is used. - Genesis *genesisT.Genesis `toml:",omitempty"` - - // Protocol options - NetworkId uint64 // Network ID to use for selecting peers to connect to. When 0, chainID is used. - ProtocolVersions []uint // Protocol versions are the supported versions of the eth protocol (first is primary). - SyncMode downloader.SyncMode - - // This can be set to list of enrtree:// URLs which will be queried for - // for nodes to connect to. - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - - NoPruning bool // Whether to disable pruning and flush everything to disk - NoPrefetch bool // Whether to disable prefetching and only load state on demand - - // Deprecated, use 'TransactionHistory' instead. - TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. - TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. - StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved. + // The genesis block, which is inserted if the database is empty. + // If nil, the Ethereum main net block is used. + Genesis *genesisT.Genesis `toml:",omitempty"` + + // Protocol options + NetworkId uint64 // Network ID to use for selecting peers to connect to. When 0, chainID is used. + ProtocolVersions []uint // Protocol versions are the supported versions of the eth protocol (first is primary). + SyncMode downloader.SyncMode + + // This can be set to list of enrtree:// URLs which will be queried for + // for nodes to connect to. + EthDiscoveryURLs []string + SnapDiscoveryURLs []string + + NoPruning bool // Whether to disable pruning and flush everything to disk + NoPrefetch bool // Whether to disable prefetching and only load state on demand + + // Deprecated, use 'TransactionHistory' instead. + TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. + TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. + StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved. - // State scheme represents the scheme used to store ethereum states and trie - // nodes on top. It can be 'hash', 'path', or none which means use the scheme - // consistent with persistent state. - StateScheme string `toml:",omitempty"` + // State scheme represents the scheme used to store ethereum states and trie + // nodes on top. It can be 'hash', 'path', or none which means use the scheme + // consistent with persistent state. + StateScheme string `toml:",omitempty"` - // RequiredBlocks is a set of block number -> hash mappings which must be in the - // canonical chain of all remote peers. Setting the option makes geth verify the - // presence of these blocks for every new peer connection. - RequiredBlocks map[uint64]common.Hash `toml:"-"` + // RequiredBlocks is a set of block number -> hash mappings which must be in the + // canonical chain of all remote peers. Setting the option makes geth verify the + // presence of these blocks for every new peer connection. + RequiredBlocks map[uint64]common.Hash `toml:"-"` - // Light client options - LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests - LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers - LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers - LightPeers int `toml:",omitempty"` // Maximum number of LES client peers - LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning - LightNoSyncServe bool `toml:",omitempty"` // Whether to serve light clients before syncing - SyncFromCheckpoint bool `toml:",omitempty"` // Whether to sync the header chain from the configured checkpoint + // Light client options + LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests + LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers + LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers + LightPeers int `toml:",omitempty"` // Maximum number of LES client peers + LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning + LightNoSyncServe bool `toml:",omitempty"` // Whether to serve light clients before syncing + SyncFromCheckpoint bool `toml:",omitempty"` // Whether to sync the header chain from the configured checkpoint - // Ultra Light client options - UltraLightServers []string `toml:",omitempty"` // List of trusted ultra light servers - UltraLightFraction int `toml:",omitempty"` // Percentage of trusted servers to accept an announcement - UltraLightOnlyAnnounce bool `toml:",omitempty"` // Whether to only announce headers, or also serve them + // Ultra Light client options + UltraLightServers []string `toml:",omitempty"` // List of trusted ultra light servers + UltraLightFraction int `toml:",omitempty"` // Percentage of trusted servers to accept an announcement + UltraLightOnlyAnnounce bool `toml:",omitempty"` // Whether to only announce headers, or also serve them - // Database options - SkipBcVersionCheck bool `toml:"-"` - DatabaseHandles int `toml:"-"` - DatabaseCache int - DatabaseFreezer string - DatabaseFreezerRemote string + // Database options + SkipBcVersionCheck bool `toml:"-"` + DatabaseHandles int `toml:"-"` + DatabaseCache int + DatabaseFreezer string + DatabaseFreezerRemote string - TrieCleanCache int - TrieDirtyCache int - TrieTimeout time.Duration - SnapshotCache int - Preimages bool + TrieCleanCache int + TrieDirtyCache int + TrieTimeout time.Duration + SnapshotCache int + Preimages bool - // This is the number of blocks for which logs will be cached in the filter system. - FilterLogCacheSize int + // This is the number of blocks for which logs will be cached in the filter system. + FilterLogCacheSize int - // Mining options - Miner miner.Config + // Mining options + Miner miner.Config - // Ethash options - Ethash ethash.Config + // Ethash options + Ethash ethash.Config - // EthashB3 options - EthashB3 ethashb3.Config + // EthashB3 options + EthashB3 ethashb3.Config - // Transaction pool options - TxPool legacypool.Config - BlobPool blobpool.Config + // Transaction pool options + TxPool legacypool.Config + BlobPool blobpool.Config - // Gas Price Oracle options - GPO gasprice.Config + // Gas Price Oracle options + GPO gasprice.Config - // Enables tracking of SHA3 preimages in the VM - EnablePreimageRecording bool + // Enables tracking of SHA3 preimages in the VM + EnablePreimageRecording bool - // Miscellaneous options - DocRoot string `toml:"-"` + // Miscellaneous options + DocRoot string `toml:"-"` - // Type of the EWASM interpreter ("" for default) - EWASMInterpreter string + // Type of the EWASM interpreter ("" for default) + EWASMInterpreter string - // Type of the EVM interpreter ("" for default) - EVMInterpreter string + // Type of the EVM interpreter ("" for default) + EVMInterpreter string - // RPCGasCap is the global gas cap for eth-call variants. - RPCGasCap uint64 + // RPCGasCap is the global gas cap for eth-call variants. + RPCGasCap uint64 - // RPCEVMTimeout is the global timeout for eth-call. - RPCEVMTimeout time.Duration + // RPCEVMTimeout is the global timeout for eth-call. + RPCEVMTimeout time.Duration - // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for - // send-transaction variants. The unit is ether. - RPCTxFeeCap float64 + // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for + // send-transaction variants. The unit is ether. + RPCTxFeeCap float64 - // Checkpoint is a hardcoded checkpoint which can be nil. - Checkpoint *ctypes.TrustedCheckpoint `toml:",omitempty"` + // Checkpoint is a hardcoded checkpoint which can be nil. + Checkpoint *ctypes.TrustedCheckpoint `toml:",omitempty"` - // CheckpointOracle is the configuration for checkpoint oracle. - CheckpointOracle *ctypes.CheckpointOracleConfig `toml:",omitempty"` + // CheckpointOracle is the configuration for checkpoint oracle. + CheckpointOracle *ctypes.CheckpointOracleConfig `toml:",omitempty"` - // Manual configuration field for ECBP1100 activation number. Used for modifying genesis config via CLI flag. - OverrideECBP1100 *uint64 `toml:",omitempty"` - // Manual configuration field for ECBP1100's disablement block number. Used for modifying genesis config via CLI flag. - OverrideECBP1100Deactivate *uint64 `toml:",omitempty"` + // Manual configuration field for ECBP1100 activation number. Used for modifying genesis config via CLI flag. + OverrideECBP1100 *uint64 `toml:",omitempty"` + // Manual configuration field for ECBP1100's disablement block number. Used for modifying genesis config via CLI flag. + OverrideECBP1100Deactivate *uint64 `toml:",omitempty"` - // ECBP1100NoDisable overrides - // When this value is *true, ECBP100 will not (ever) be disabled; when *false, it will never be enabled. - ECBP1100NoDisable *bool `toml:",omitempty"` + // ECBP1100NoDisable overrides + // When this value is *true, ECBP100 will not (ever) be disabled; when *false, it will never be enabled. + ECBP1100NoDisable *bool `toml:",omitempty"` - // OverrideShanghai (TODO: remove after the fork) - OverrideShanghai *uint64 `toml:",omitempty"` + // OverrideShanghai (TODO: remove after the fork) + OverrideShanghai *uint64 `toml:",omitempty"` - // OverrideCancun (TODO: remove after the fork) - OverrideCancun *uint64 `toml:",omitempty"` + // OverrideCancun (TODO: remove after the fork) + OverrideCancun *uint64 `toml:",omitempty"` - // OverrideVerkle (TODO: remove after the fork) - OverrideVerkle *uint64 `toml:",omitempty"` + // OverrideVerkle (TODO: remove after the fork) + OverrideVerkle *uint64 `toml:",omitempty"` } // CreateConsensusEngine creates a consensus engine for the given chain configuration. -func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, ethashb3Config *ethashb3.Config, cliqueConfig *ctypes.CliqueConfig, lyra2Config *lyra2.Config, 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 lyra2Config != nil { - engine = lyra2.New(lyra2Config, notify, noverify) - } else if ethashb3Config != nil { - engine = CreateConsensusEngineEthashB3(stack, ethashb3Config, notify, noverify) - } else { - switch ethashConfig.PowMode { - case ethash.ModeFake: - log.Warn("Ethash used in fake mode") - engine = ethash.NewFaker() - case ethash.ModeTest: - log.Warn("Ethash used in test mode") - engine = ethash.NewTester(nil, noverify) - case ethash.ModeShared: - log.Warn("Ethash used in shared mode") - engine = ethash.NewShared() - case ethash.ModePoissonFake: - log.Warn("Ethash used in fake Poisson mode") - engine = ethash.NewPoissonFaker() - default: - engine = ethash.New(ethash.Config{ - PowMode: ethashConfig.PowMode, - CacheDir: stack.ResolvePath(ethashConfig.CacheDir), - CachesInMem: ethashConfig.CachesInMem, - CachesOnDisk: ethashConfig.CachesOnDisk, - CachesLockMmap: ethashConfig.CachesLockMmap, - DatasetDir: ethashConfig.DatasetDir, - DatasetsInMem: ethashConfig.DatasetsInMem, - DatasetsOnDisk: ethashConfig.DatasetsOnDisk, - DatasetsLockMmap: ethashConfig.DatasetsLockMmap, - NotifyFull: ethashConfig.NotifyFull, - ECIP1099Block: ethashConfig.ECIP1099Block, - }, notify, noverify) - engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining - } - } - - return beacon.New(engine) +// func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, ethashb3Config *ethashb3.Config, cliqueConfig *ctypes.CliqueConfig, lyra2Config *lyra2.Config, 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 lyra2Config != nil { +// engine = lyra2.New(lyra2Config, notify, noverify) +// } else if ethashb3Config != nil { +// engine = CreateConsensusEngineEthashB3(stack, ethashb3Config, notify, noverify) +// } else { +// switch ethashConfig.PowMode { +// case ethash.ModeFake: +// log.Warn("Ethash used in fake mode") +// engine = ethash.NewFaker() +// case ethash.ModeTest: +// log.Warn("Ethash used in test mode") +// engine = ethash.NewTester(nil, noverify) +// case ethash.ModeShared: +// log.Warn("Ethash used in shared mode") +// engine = ethash.NewShared() +// case ethash.ModePoissonFake: +// log.Warn("Ethash used in fake Poisson mode") +// engine = ethash.NewPoissonFaker() +// default: +// engine = ethash.New(ethash.Config{ +// PowMode: ethashConfig.PowMode, +// CacheDir: stack.ResolvePath(ethashConfig.CacheDir), +// CachesInMem: ethashConfig.CachesInMem, +// CachesOnDisk: ethashConfig.CachesOnDisk, +// CachesLockMmap: ethashConfig.CachesLockMmap, +// DatasetDir: ethashConfig.DatasetDir, +// DatasetsInMem: ethashConfig.DatasetsInMem, +// DatasetsOnDisk: ethashConfig.DatasetsOnDisk, +// DatasetsLockMmap: ethashConfig.DatasetsLockMmap, +// NotifyFull: ethashConfig.NotifyFull, +// ECIP1099Block: ethashConfig.ECIP1099Block, +// }, notify, noverify) +// engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining +// } +// } +// +// return beacon.New(engine) +// } + +func CreateConsensusEngine(stack *node.Node, config *Config, db ethdb.Database) consensus.Engine { + // If proof-of-authority is requested, set it up + var engine consensus.Engine + engineType := config.Genesis.Config.GetConsensusEngineType() + if engineType == ctypes.ConsensusEngineT_Clique { + cliqueConfig, _ := core.LoadCliqueConfig(db, config.Genesis) + engine = clique.New(cliqueConfig, db) + } else if engineType == ctypes.ConsensusEngineT_Lyra2 { + engine = lyra2.New(&lyra2.Config{}, config.Miner.Notify, config.Miner.Noverify) + } else if engineType == ctypes.ConsensusEngineT_EthashB3 { + engine = CreateConsensusEngineEthashB3(stack, &config.EthashB3, config.Miner.Notify, config.Miner.Noverify) + } else { + engine = CreateConsensusEngineEthash(stack, &config.Ethash, config.Miner.Notify, config.Miner.Noverify) + } + + return engine } func CreateConsensusEngineEthash(stack *node.Node, ethashConfig *ethash.Config, notify []string, noverify bool) (engine consensus.Engine) { - switch ethashConfig.PowMode { - case ethash.ModeFake: - log.Warn("Ethash used in fake mode") - engine = ethash.NewFaker() - case ethash.ModeTest: - log.Warn("Ethash used in test mode") - engine = ethash.NewTester(nil, noverify) - case ethash.ModeShared: - log.Warn("Ethash used in shared mode") - engine = ethash.NewShared() - case ethash.ModePoissonFake: - log.Warn("Ethash used in fake Poisson mode") - engine = ethash.NewPoissonFaker() - default: - engine = ethash.New(ethash.Config{ - PowMode: ethashConfig.PowMode, - CacheDir: stack.ResolvePath(ethashConfig.CacheDir), - CachesInMem: ethashConfig.CachesInMem, - CachesOnDisk: ethashConfig.CachesOnDisk, - CachesLockMmap: ethashConfig.CachesLockMmap, - DatasetDir: ethashConfig.DatasetDir, - DatasetsInMem: ethashConfig.DatasetsInMem, - DatasetsOnDisk: ethashConfig.DatasetsOnDisk, - DatasetsLockMmap: ethashConfig.DatasetsLockMmap, - NotifyFull: ethashConfig.NotifyFull, - ECIP1099Block: ethashConfig.ECIP1099Block, - }, notify, noverify) - engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining - } - engine = beacon.New(engine) - return + switch ethashConfig.PowMode { + case ethash.ModeFake: + log.Warn("Ethash used in fake mode") + engine = ethash.NewFaker() + case ethash.ModeTest: + log.Warn("Ethash used in test mode") + engine = ethash.NewTester(nil, noverify) + case ethash.ModeShared: + log.Warn("Ethash used in shared mode") + engine = ethash.NewShared() + case ethash.ModePoissonFake: + log.Warn("Ethash used in fake Poisson mode") + engine = ethash.NewPoissonFaker() + default: + engine = ethash.New(ethash.Config{ + PowMode: ethashConfig.PowMode, + CacheDir: stack.ResolvePath(ethashConfig.CacheDir), + CachesInMem: ethashConfig.CachesInMem, + CachesOnDisk: ethashConfig.CachesOnDisk, + CachesLockMmap: ethashConfig.CachesLockMmap, + DatasetDir: ethashConfig.DatasetDir, + DatasetsInMem: ethashConfig.DatasetsInMem, + DatasetsOnDisk: ethashConfig.DatasetsOnDisk, + DatasetsLockMmap: ethashConfig.DatasetsLockMmap, + NotifyFull: ethashConfig.NotifyFull, + ECIP1099Block: ethashConfig.ECIP1099Block, + }, notify, noverify) + engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining + } + engine = beacon.New(engine) + return } func CreateConsensusEngineEthashB3(stack *node.Node, ethashb3Config *ethashb3.Config, notify []string, noverify bool) (engine consensus.Engine) { - switch ethashb3Config.PowMode { - case ethashb3.ModeFake: - log.Warn("EthashB3 used in fake mode") - engine = ethashb3.NewFaker() - case ethashb3.ModeTest: - log.Warn("EthashB3 used in test mode") - engine = ethashb3.NewTester(nil, noverify) - case ethashb3.ModeShared: - log.Warn("EthashB3 used in shared mode") - engine = ethashb3.NewShared() - case ethashb3.ModePoissonFake: - log.Warn("EthashB3 used in fake Poisson mode") - engine = ethashb3.NewPoissonFaker() - default: - engine = ethashb3.New(ethashb3.Config{ - PowMode: ethashb3Config.PowMode, - CacheDir: stack.ResolvePath(ethashb3Config.CacheDir), - CachesInMem: ethashb3Config.CachesInMem, - CachesOnDisk: ethashb3Config.CachesOnDisk, - CachesLockMmap: ethashb3Config.CachesLockMmap, - DatasetDir: ethashb3Config.DatasetDir, - DatasetsInMem: ethashb3Config.DatasetsInMem, - DatasetsOnDisk: ethashb3Config.DatasetsOnDisk, - DatasetsLockMmap: ethashb3Config.DatasetsLockMmap, - NotifyFull: ethashb3Config.NotifyFull, - }, notify, noverify) - engine.(*ethashb3.EthashB3).SetThreads(-1) // Disable CPU mining - } - return + switch ethashb3Config.PowMode { + case ethashb3.ModeFake: + log.Warn("EthashB3 used in fake mode") + engine = ethashb3.NewFaker() + case ethashb3.ModeTest: + log.Warn("EthashB3 used in test mode") + engine = ethashb3.NewTester(nil, noverify) + case ethashb3.ModeShared: + log.Warn("EthashB3 used in shared mode") + engine = ethashb3.NewShared() + case ethashb3.ModePoissonFake: + log.Warn("EthashB3 used in fake Poisson mode") + engine = ethashb3.NewPoissonFaker() + default: + engine = ethashb3.New(ethashb3.Config{ + PowMode: ethashb3Config.PowMode, + CacheDir: stack.ResolvePath(ethashb3Config.CacheDir), + CachesInMem: ethashb3Config.CachesInMem, + CachesOnDisk: ethashb3Config.CachesOnDisk, + CachesLockMmap: ethashb3Config.CachesLockMmap, + DatasetDir: ethashb3Config.DatasetDir, + DatasetsInMem: ethashb3Config.DatasetsInMem, + DatasetsOnDisk: ethashb3Config.DatasetsOnDisk, + DatasetsLockMmap: ethashb3Config.DatasetsLockMmap, + NotifyFull: ethashb3Config.NotifyFull, + }, notify, noverify) + engine.(*ethashb3.EthashB3).SetThreads(-1) // Disable CPU mining + } + return } func CreateConsensusEngineClique(cliqueConfig *ctypes.CliqueConfig, db ethdb.Database) (engine consensus.Engine) { - engine = clique.New(cliqueConfig, db) - return + engine = clique.New(cliqueConfig, db) + return } func CreateConsensusEngineLyra2(lyra2Config *lyra2.Config, notify []string, noverify bool) (engine consensus.Engine) { - engine = lyra2.New(lyra2Config, notify, noverify) - return + engine = lyra2.New(lyra2Config, notify, noverify) + return } From 0b9754177907458b73c919f84fc3ec6e3aa50212 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Sun, 16 Jun 2024 17:43:25 +0100 Subject: [PATCH 44/45] les - fix les client --- eth/ethconfig/config.go | 2 +- les/client.go | 658 ++++++++++++++++++++-------------------- 2 files changed, 329 insertions(+), 331 deletions(-) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 5c7ba63afa..9bf22debc2 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -310,7 +310,6 @@ type Config struct { // } func CreateConsensusEngine(stack *node.Node, config *Config, db ethdb.Database) consensus.Engine { - // If proof-of-authority is requested, set it up var engine consensus.Engine engineType := config.Genesis.Config.GetConsensusEngineType() if engineType == ctypes.ConsensusEngineT_Clique { @@ -321,6 +320,7 @@ func CreateConsensusEngine(stack *node.Node, config *Config, db ethdb.Database) } else if engineType == ctypes.ConsensusEngineT_EthashB3 { engine = CreateConsensusEngineEthashB3(stack, &config.EthashB3, config.Miner.Notify, config.Miner.Noverify) } else { + // If no engine type is found, default to ethash - Beacon chain engine = CreateConsensusEngineEthash(stack, &config.Ethash, config.Miner.Notify, config.Miner.Noverify) } diff --git a/les/client.go b/les/client.go index fcdd481651..2c3585dd7b 100644 --- a/les/client.go +++ b/les/client.go @@ -18,334 +18,332 @@ package les import ( - "errors" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/lyra2" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/shutdowncheck" - "github.com/ethereum/go-ethereum/les/downloader" - "github.com/ethereum/go-ethereum/les/vflux" - vfc "github.com/ethereum/go-ethereum/les/vflux/client" - "github.com/ethereum/go-ethereum/light" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/params/confp" - "github.com/ethereum/go-ethereum/params/types/coregeth" - "github.com/ethereum/go-ethereum/params/types/ctypes" - "github.com/ethereum/go-ethereum/params/types/goethereum" - "github.com/ethereum/go-ethereum/params/vars" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/trie" + "errors" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/internal/shutdowncheck" + "github.com/ethereum/go-ethereum/les/downloader" + "github.com/ethereum/go-ethereum/les/vflux" + vfc "github.com/ethereum/go-ethereum/les/vflux/client" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/params/confp" + "github.com/ethereum/go-ethereum/params/types/coregeth" + "github.com/ethereum/go-ethereum/params/types/goethereum" + "github.com/ethereum/go-ethereum/params/vars" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" ) type LightEthereum struct { - lesCommons - - peers *serverPeerSet - reqDist *requestDistributor - retriever *retrieveManager - odr *LesOdr - relay *lesTxRelay - handler *clientHandler - txPool *light.TxPool - blockchain *light.LightChain - serverPool *vfc.ServerPool - serverPoolIterator enode.Iterator - pruner *pruner - merger *consensus.Merger - - bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests - bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports - - ApiBackend *LesApiBackend - eventMux *event.TypeMux - engine consensus.Engine - accountManager *accounts.Manager - netRPCService *ethapi.NetAPI - - p2pServer *p2p.Server - p2pConfig *p2p.Config - udpEnabled bool - - shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully + lesCommons + + peers *serverPeerSet + reqDist *requestDistributor + retriever *retrieveManager + odr *LesOdr + relay *lesTxRelay + handler *clientHandler + txPool *light.TxPool + blockchain *light.LightChain + serverPool *vfc.ServerPool + serverPoolIterator enode.Iterator + pruner *pruner + merger *consensus.Merger + + bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests + bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports + + ApiBackend *LesApiBackend + eventMux *event.TypeMux + engine consensus.Engine + accountManager *accounts.Manager + netRPCService *ethapi.NetAPI + + p2pServer *p2p.Server + p2pConfig *p2p.Config + udpEnabled bool + + shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully } // New creates an instance of the light client. func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) { - chainDb, err := stack.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/", false) - if err != nil { - return nil, err - } - lesDb, err := stack.OpenDatabase("les.client", 0, 0, "eth/db/lesclient/", false) - if err != nil { - return nil, err - } - var overrides core.ChainOverrides - if config.OverrideShanghai != nil { - overrides.OverrideShanghai = config.OverrideShanghai - } - if config.OverrideCancun != nil { - overrides.OverrideCancun = config.OverrideCancun - } - if config.OverrideVerkle != nil { - overrides.OverrideVerkle = config.OverrideVerkle - } - triedb := trie.NewDatabase(chainDb, trie.HashDefaults) - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, triedb, config.Genesis, &overrides) - if _, isCompat := genesisErr.(*confp.ConfigCompatError); genesisErr != nil && !isCompat { - return nil, genesisErr - } - log.Info("") - log.Info(strings.Repeat("-", 153)) - for _, line := range strings.Split(chainConfig.String(), "\n") { - log.Info(line) - } - log.Info(strings.Repeat("-", 153)) - log.Info("") - - var cliqueConfig *ctypes.CliqueConfig - var lyra2Config *lyra2.Config - if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Clique { - cliqueConfig = &ctypes.CliqueConfig{ - Period: chainConfig.GetCliquePeriod(), - Epoch: chainConfig.GetCliqueEpoch(), - } - } else if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Lyra2 { - lyra2Config = &lyra2.Config{} - } else if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Ethash { - config.Ethash.ECIP1099Block = chainConfig.GetEthashECIP1099Transition() - } - - peers := newServerPeerSet() - merger := consensus.NewMerger(chainDb) - leth := &LightEthereum{ - lesCommons: lesCommons{ - genesis: genesisHash, - config: config, - chainConfig: chainConfig, - iConfig: light.DefaultClientIndexerConfig, - chainDb: chainDb, - lesDb: lesDb, - closeCh: make(chan struct{}), - }, - peers: peers, - eventMux: stack.EventMux(), - reqDist: newRequestDistributor(peers, &mclock.System{}), - accountManager: stack.AccountManager(), - merger: merger, - engine: ethconfig.CreateConsensusEngine(stack, &config.Ethash, &config.EthashB3, cliqueConfig, lyra2Config, nil, false, chainDb), - bloomRequests: make(chan chan *bloombits.Retrieval), - bloomIndexer: core.NewBloomIndexer(chainDb, vars.BloomBitsBlocksClient, vars.HelperTrieConfirmations), - p2pServer: stack.Server(), - p2pConfig: &stack.Config().P2P, - udpEnabled: stack.Config().P2P.DiscoveryV5, - shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), - } - - var prenegQuery vfc.QueryFunc - if leth.udpEnabled { - prenegQuery = leth.prenegQuery - } - leth.serverPool, leth.serverPoolIterator = vfc.NewServerPool(lesDb, []byte("serverpool:"), time.Second, prenegQuery, &mclock.System{}, config.UltraLightServers, requestList) - leth.serverPool.AddMetrics(suggestedTimeoutGauge, totalValueGauge, serverSelectableGauge, serverConnectedGauge, sessionValueMeter, serverDialedMeter) - - leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool.GetTimeout) - leth.relay = newLesTxRelay(peers, leth.retriever) - - leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.peers, leth.retriever) - leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, vars.CHTFrequency, vars.HelperTrieConfirmations, config.LightNoPrune) - leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, vars.BloomBitsBlocksClient, vars.BloomTrieFrequency, config.LightNoPrune) - leth.odr.SetIndexers(leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer) - - checkpoint := config.Checkpoint - if checkpoint == nil { - if p, ok := chainConfig.(*coregeth.CoreGethChainConfig); ok { - checkpoint = p.TrustedCheckpoint - } else if p, ok := chainConfig.(*goethereum.ChainConfig); ok { - checkpoint = p.TrustedCheckpoint - } - } - // Note: NewLightChain adds the trusted checkpoint so it needs an ODR with - // indexers already set but not started yet - if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, checkpoint); err != nil { - return nil, err - } - leth.chainReader = leth.blockchain - leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) - - // Note: AddChildIndexer starts the update process for the child - leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) - leth.chtIndexer.Start(leth.blockchain) - leth.bloomIndexer.Start(leth.blockchain) - - // Start a light chain pruner to delete useless historical data. - leth.pruner = newPruner(chainDb, leth.chtIndexer, leth.bloomTrieIndexer) - - // Rewind the chain in case of an incompatible config upgrade. - if compat, ok := genesisErr.(*confp.ConfigCompatError); ok { - log.Warn("Rewinding chain to upgrade configuration", "err", compat) - if compat.RewindToTime > 0 { - leth.blockchain.SetHeadWithTimestamp(compat.RewindToTime) - } else { - leth.blockchain.SetHead(compat.RewindToBlock) - } - rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) - } - - leth.ApiBackend = &LesApiBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, leth, nil} - gpoParams := config.GPO - if gpoParams.Default == nil { - gpoParams.Default = config.Miner.GasPrice - } - leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) - - leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, leth) - if leth.handler.ulc != nil { - log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.handler.ulc.keys), "minTrustedFraction", leth.handler.ulc.fraction) - leth.blockchain.DisableCheckFreq() - } - leth.netRPCService = ethapi.NewNetAPI(leth.p2pServer, leth.config.NetworkId) - - // Register the backend on the node - stack.RegisterAPIs(leth.APIs()) - stack.RegisterProtocols(leth.Protocols()) - stack.RegisterLifecycle(leth) - - // Successful startup; push a marker and check previous unclean shutdowns. - leth.shutdownTracker.MarkStartup() - - return leth, nil + chainDb, err := stack.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/", false) + if err != nil { + return nil, err + } + lesDb, err := stack.OpenDatabase("les.client", 0, 0, "eth/db/lesclient/", false) + if err != nil { + return nil, err + } + var overrides core.ChainOverrides + if config.OverrideShanghai != nil { + overrides.OverrideShanghai = config.OverrideShanghai + } + if config.OverrideCancun != nil { + overrides.OverrideCancun = config.OverrideCancun + } + if config.OverrideVerkle != nil { + overrides.OverrideVerkle = config.OverrideVerkle + } + triedb := trie.NewDatabase(chainDb, trie.HashDefaults) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, triedb, config.Genesis, &overrides) + if _, isCompat := genesisErr.(*confp.ConfigCompatError); genesisErr != nil && !isCompat { + return nil, genesisErr + } + log.Info("") + log.Info(strings.Repeat("-", 153)) + for _, line := range strings.Split(chainConfig.String(), "\n") { + log.Info(line) + } + log.Info(strings.Repeat("-", 153)) + log.Info("") + + // var cliqueConfig *ctypes.CliqueConfig + // var lyra2Config *lyra2.Config + // if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Clique { + // cliqueConfig = &ctypes.CliqueConfig{ + // Period: chainConfig.GetCliquePeriod(), + // Epoch: chainConfig.GetCliqueEpoch(), + // } + // } else if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Lyra2 { + // lyra2Config = &lyra2.Config{} + // } else if chainConfig.GetConsensusEngineType() == ctypes.ConsensusEngineT_Ethash { + // config.Ethash.ECIP1099Block = chainConfig.GetEthashECIP1099Transition() + // } + + peers := newServerPeerSet() + merger := consensus.NewMerger(chainDb) + leth := &LightEthereum{ + lesCommons: lesCommons{ + genesis: genesisHash, + config: config, + chainConfig: chainConfig, + iConfig: light.DefaultClientIndexerConfig, + chainDb: chainDb, + lesDb: lesDb, + closeCh: make(chan struct{}), + }, + peers: peers, + eventMux: stack.EventMux(), + reqDist: newRequestDistributor(peers, &mclock.System{}), + accountManager: stack.AccountManager(), + merger: merger, + engine: ethconfig.CreateConsensusEngine(stack, config, chainDb), + bloomRequests: make(chan chan *bloombits.Retrieval), + bloomIndexer: core.NewBloomIndexer(chainDb, vars.BloomBitsBlocksClient, vars.HelperTrieConfirmations), + p2pServer: stack.Server(), + p2pConfig: &stack.Config().P2P, + udpEnabled: stack.Config().P2P.DiscoveryV5, + shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), + } + + var prenegQuery vfc.QueryFunc + if leth.udpEnabled { + prenegQuery = leth.prenegQuery + } + leth.serverPool, leth.serverPoolIterator = vfc.NewServerPool(lesDb, []byte("serverpool:"), time.Second, prenegQuery, &mclock.System{}, config.UltraLightServers, requestList) + leth.serverPool.AddMetrics(suggestedTimeoutGauge, totalValueGauge, serverSelectableGauge, serverConnectedGauge, sessionValueMeter, serverDialedMeter) + + leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool.GetTimeout) + leth.relay = newLesTxRelay(peers, leth.retriever) + + leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.peers, leth.retriever) + leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, vars.CHTFrequency, vars.HelperTrieConfirmations, config.LightNoPrune) + leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, vars.BloomBitsBlocksClient, vars.BloomTrieFrequency, config.LightNoPrune) + leth.odr.SetIndexers(leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer) + + checkpoint := config.Checkpoint + if checkpoint == nil { + if p, ok := chainConfig.(*coregeth.CoreGethChainConfig); ok { + checkpoint = p.TrustedCheckpoint + } else if p, ok := chainConfig.(*goethereum.ChainConfig); ok { + checkpoint = p.TrustedCheckpoint + } + } + // Note: NewLightChain adds the trusted checkpoint so it needs an ODR with + // indexers already set but not started yet + if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, checkpoint); err != nil { + return nil, err + } + leth.chainReader = leth.blockchain + leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) + + // Note: AddChildIndexer starts the update process for the child + leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) + leth.chtIndexer.Start(leth.blockchain) + leth.bloomIndexer.Start(leth.blockchain) + + // Start a light chain pruner to delete useless historical data. + leth.pruner = newPruner(chainDb, leth.chtIndexer, leth.bloomTrieIndexer) + + // Rewind the chain in case of an incompatible config upgrade. + if compat, ok := genesisErr.(*confp.ConfigCompatError); ok { + log.Warn("Rewinding chain to upgrade configuration", "err", compat) + if compat.RewindToTime > 0 { + leth.blockchain.SetHeadWithTimestamp(compat.RewindToTime) + } else { + leth.blockchain.SetHead(compat.RewindToBlock) + } + rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) + } + + leth.ApiBackend = &LesApiBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, leth, nil} + gpoParams := config.GPO + if gpoParams.Default == nil { + gpoParams.Default = config.Miner.GasPrice + } + leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) + + leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, leth) + if leth.handler.ulc != nil { + log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.handler.ulc.keys), "minTrustedFraction", leth.handler.ulc.fraction) + leth.blockchain.DisableCheckFreq() + } + leth.netRPCService = ethapi.NewNetAPI(leth.p2pServer, leth.config.NetworkId) + + // Register the backend on the node + stack.RegisterAPIs(leth.APIs()) + stack.RegisterProtocols(leth.Protocols()) + stack.RegisterLifecycle(leth) + + // Successful startup; push a marker and check previous unclean shutdowns. + leth.shutdownTracker.MarkStartup() + + return leth, nil } // VfluxRequest sends a batch of requests to the given node through discv5 UDP TalkRequest and returns the responses func (s *LightEthereum) VfluxRequest(n *enode.Node, reqs vflux.Requests) vflux.Replies { - if !s.udpEnabled { - return nil - } - reqsEnc, _ := rlp.EncodeToBytes(&reqs) - repliesEnc, _ := s.p2pServer.DiscV5.TalkRequest(s.serverPool.DialNode(n), "vfx", reqsEnc) - var replies vflux.Replies - if len(repliesEnc) == 0 || rlp.DecodeBytes(repliesEnc, &replies) != nil { - return nil - } - return replies + if !s.udpEnabled { + return nil + } + reqsEnc, _ := rlp.EncodeToBytes(&reqs) + repliesEnc, _ := s.p2pServer.DiscV5.TalkRequest(s.serverPool.DialNode(n), "vfx", reqsEnc) + var replies vflux.Replies + if len(repliesEnc) == 0 || rlp.DecodeBytes(repliesEnc, &replies) != nil { + return nil + } + return replies } // vfxVersion returns the version number of the "les" service subdomain of the vflux UDP // service, as advertised in the ENR record func (s *LightEthereum) vfxVersion(n *enode.Node) uint { - if n.Seq() == 0 { - var err error - if !s.udpEnabled { - return 0 - } - if n, err = s.p2pServer.DiscV5.RequestENR(n); n != nil && err == nil && n.Seq() != 0 { - s.serverPool.Persist(n) - } else { - return 0 - } - } - - var les []rlp.RawValue - if err := n.Load(enr.WithEntry("les", &les)); err != nil || len(les) < 1 { - return 0 - } - var version uint - rlp.DecodeBytes(les[0], &version) // Ignore additional fields (for forward compatibility). - return version + if n.Seq() == 0 { + var err error + if !s.udpEnabled { + return 0 + } + if n, err = s.p2pServer.DiscV5.RequestENR(n); n != nil && err == nil && n.Seq() != 0 { + s.serverPool.Persist(n) + } else { + return 0 + } + } + + var les []rlp.RawValue + if err := n.Load(enr.WithEntry("les", &les)); err != nil || len(les) < 1 { + return 0 + } + var version uint + rlp.DecodeBytes(les[0], &version) // Ignore additional fields (for forward compatibility). + return version } // prenegQuery sends a capacity query to the given server node to determine whether // a connection slot is immediately available func (s *LightEthereum) prenegQuery(n *enode.Node) int { - if s.vfxVersion(n) < 1 { - // UDP query not supported, always try TCP connection - return 1 - } - - var requests vflux.Requests - requests.Add("les", vflux.CapacityQueryName, vflux.CapacityQueryReq{ - Bias: 180, - AddTokens: []vflux.IntOrInf{{}}, - }) - replies := s.VfluxRequest(n, requests) - var cqr vflux.CapacityQueryReply - if replies.Get(0, &cqr) != nil || len(cqr) != 1 { // Note: Get returns an error if replies is nil - return -1 - } - if cqr[0] > 0 { - return 1 - } - return 0 + if s.vfxVersion(n) < 1 { + // UDP query not supported, always try TCP connection + return 1 + } + + var requests vflux.Requests + requests.Add("les", vflux.CapacityQueryName, vflux.CapacityQueryReq{ + Bias: 180, + AddTokens: []vflux.IntOrInf{{}}, + }) + replies := s.VfluxRequest(n, requests) + var cqr vflux.CapacityQueryReply + if replies.Get(0, &cqr) != nil || len(cqr) != 1 { // Note: Get returns an error if replies is nil + return -1 + } + if cqr[0] > 0 { + return 1 + } + return 0 } type LightDummyAPI struct{} // Etherbase is the address that mining rewards will be sent to func (s *LightDummyAPI) Etherbase() (common.Address, error) { - return common.Address{}, errors.New("mining is not supported in light mode") + return common.Address{}, errors.New("mining is not supported in light mode") } // Coinbase is the address that mining rewards will be sent to (alias for Etherbase) func (s *LightDummyAPI) Coinbase() (common.Address, error) { - return common.Address{}, errors.New("mining is not supported in light mode") + return common.Address{}, errors.New("mining is not supported in light mode") } // Hashrate returns the POW hashrate func (s *LightDummyAPI) Hashrate() hexutil.Uint { - return 0 + return 0 } // Mining returns an indication if this node is currently mining. func (s *LightDummyAPI) Mining() bool { - return false + return false } // APIs returns the collection of RPC services the ethereum package offers. // NOTE, some of these services probably need to be moved to somewhere else. func (s *LightEthereum) APIs() []rpc.API { - apis := ethapi.GetAPIs(s.ApiBackend) - apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...) - return append(apis, []rpc.API{ - { - Namespace: "eth", - Service: &LightDummyAPI{}, - }, { - Namespace: "eth", - Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux), - }, { - Namespace: "net", - Service: s.netRPCService, - }, { - Namespace: "les", - Service: NewLightAPI(&s.lesCommons), - }, { - Namespace: "vflux", - Service: s.serverPool.API(), - }, - }...) + apis := ethapi.GetAPIs(s.ApiBackend) + apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...) + return append(apis, []rpc.API{ + { + Namespace: "eth", + Service: &LightDummyAPI{}, + }, { + Namespace: "eth", + Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux), + }, { + Namespace: "net", + Service: s.netRPCService, + }, { + Namespace: "les", + Service: NewLightAPI(&s.lesCommons), + }, { + Namespace: "vflux", + Service: s.serverPool.API(), + }, + }...) } func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) { - s.blockchain.ResetWithGenesisBlock(gb) + s.blockchain.ResetWithGenesisBlock(gb) } func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } @@ -358,63 +356,63 @@ func (s *LightEthereum) Merger() *consensus.Merger { return s.merger } // Protocols returns all the currently configured network protocols to start. func (s *LightEthereum) Protocols() []p2p.Protocol { - return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { - if p := s.peers.peer(id.String()); p != nil { - return p.Info() - } - return nil - }, s.serverPoolIterator) + return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { + if p := s.peers.peer(id.String()); p != nil { + return p.Info() + } + return nil + }, s.serverPoolIterator) } // Start implements node.Lifecycle, starting all internal goroutines needed by the // light ethereum protocol implementation. func (s *LightEthereum) Start() error { - log.Warn("Light client mode is an experimental feature") - - // Regularly update shutdown marker - s.shutdownTracker.Start() - - if s.udpEnabled && s.p2pServer.DiscV5 == nil { - s.udpEnabled = false - log.Error("Discovery v5 is not initialized") - } - discovery, err := s.setupDiscovery() - if err != nil { - return err - } - s.serverPool.AddSource(discovery) - s.serverPool.Start() - // Start bloom request workers. - s.wg.Add(bloomServiceThreads) - s.startBloomHandlers(vars.BloomBitsBlocksClient) - s.handler.start() - - return nil + log.Warn("Light client mode is an experimental feature") + + // Regularly update shutdown marker + s.shutdownTracker.Start() + + if s.udpEnabled && s.p2pServer.DiscV5 == nil { + s.udpEnabled = false + log.Error("Discovery v5 is not initialized") + } + discovery, err := s.setupDiscovery() + if err != nil { + return err + } + s.serverPool.AddSource(discovery) + s.serverPool.Start() + // Start bloom request workers. + s.wg.Add(bloomServiceThreads) + s.startBloomHandlers(vars.BloomBitsBlocksClient) + s.handler.start() + + return nil } // Stop implements node.Lifecycle, terminating all internal goroutines used by the // Ethereum protocol. func (s *LightEthereum) Stop() error { - close(s.closeCh) - s.serverPool.Stop() - s.peers.close() - s.reqDist.close() - s.odr.Stop() - s.relay.Stop() - s.bloomIndexer.Close() - s.chtIndexer.Close() - s.blockchain.Stop() - s.handler.stop() - s.txPool.Stop() - s.engine.Close() - s.pruner.close() - s.eventMux.Stop() - // Clean shutdown marker as the last thing before closing db - s.shutdownTracker.Stop() - - s.chainDb.Close() - s.lesDb.Close() - s.wg.Wait() - log.Info("Light ethereum stopped") - return nil + close(s.closeCh) + s.serverPool.Stop() + s.peers.close() + s.reqDist.close() + s.odr.Stop() + s.relay.Stop() + s.bloomIndexer.Close() + s.chtIndexer.Close() + s.blockchain.Stop() + s.handler.stop() + s.txPool.Stop() + s.engine.Close() + s.pruner.close() + s.eventMux.Stop() + // Clean shutdown marker as the last thing before closing db + s.shutdownTracker.Stop() + + s.chainDb.Close() + s.lesDb.Close() + s.wg.Wait() + log.Info("Light ethereum stopped") + return nil } From 437774acd473f5fc6415d99f28c0ec43daa38bc7 Mon Sep 17 00:00:00 2001 From: Jake Birchall Date: Wed, 19 Jun 2024 07:52:00 +0100 Subject: [PATCH 45/45] idea comment --- eth/ethconfig/config.go | 58 ++++++++++++----------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 9bf22debc2..25ae4e7a35 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -265,50 +265,24 @@ type Config struct { } // CreateConsensusEngine creates a consensus engine for the given chain configuration. -// func CreateConsensusEngine(stack *node.Node, ethashConfig *ethash.Config, ethashb3Config *ethashb3.Config, cliqueConfig *ctypes.CliqueConfig, lyra2Config *lyra2.Config, 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 lyra2Config != nil { -// engine = lyra2.New(lyra2Config, notify, noverify) -// } else if ethashb3Config != nil { -// engine = CreateConsensusEngineEthashB3(stack, ethashb3Config, notify, noverify) -// } else { -// switch ethashConfig.PowMode { -// case ethash.ModeFake: -// log.Warn("Ethash used in fake mode") -// engine = ethash.NewFaker() -// case ethash.ModeTest: -// log.Warn("Ethash used in test mode") -// engine = ethash.NewTester(nil, noverify) -// case ethash.ModeShared: -// log.Warn("Ethash used in shared mode") -// engine = ethash.NewShared() -// case ethash.ModePoissonFake: -// log.Warn("Ethash used in fake Poisson mode") -// engine = ethash.NewPoissonFaker() -// default: -// engine = ethash.New(ethash.Config{ -// PowMode: ethashConfig.PowMode, -// CacheDir: stack.ResolvePath(ethashConfig.CacheDir), -// CachesInMem: ethashConfig.CachesInMem, -// CachesOnDisk: ethashConfig.CachesOnDisk, -// CachesLockMmap: ethashConfig.CachesLockMmap, -// DatasetDir: ethashConfig.DatasetDir, -// DatasetsInMem: ethashConfig.DatasetsInMem, -// DatasetsOnDisk: ethashConfig.DatasetsOnDisk, -// DatasetsLockMmap: ethashConfig.DatasetsLockMmap, -// NotifyFull: ethashConfig.NotifyFull, -// ECIP1099Block: ethashConfig.ECIP1099Block, -// }, notify, noverify) -// engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining -// } -// } +// Option for simplifying this would be the following code, but would require changed to each consensus engine to accept a config struct. +// ``` +// type EngineCreator func(*node.Node, *Config, ethdb.Database) consensus.Engine // -// return beacon.New(engine) +// var engineCreators = map[ctypes.ConsensusEngineT]EngineCreator{ +// ctypes.ConsensusEngineT_Clique: CreateConsensusEngineClique, +// ctypes.ConsensusEngineT_Lyra2: CreateConsensusEngineLyra2, +// ctypes.ConsensusEngineT_EthashB3: CreateConsensusEngineEthashB3, +// ctypes.ConsensusEngineT_Ethash: CreateConsensusEngineEthash, // } - +// +// func CreateConsensusEngine(stack *node.Node, config *Config, db ethdb.Database) consensus.Engine { +// engineType := config.Genesis.Config.GetConsensusEngineType() +// if createEngine, ok := engineCreators[engineType]; ok { +// return createEngine(stack, config, db) +// } +// } +// ``` func CreateConsensusEngine(stack *node.Node, config *Config, db ethdb.Database) consensus.Engine { var engine consensus.Engine engineType := config.Genesis.Config.GetConsensusEngineType()