From bbfc8c8dd291e0f47737fb497ab46a2c9502cc0e Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Sat, 16 Mar 2019 08:01:18 +0000 Subject: [PATCH 1/7] synchronous mining to prevent uncles --- consensus/ethash/sealer.go | 28 ++++++ metadium/admin.go | 3 +- miner/worker.go | 198 ++++++++++++++++++++++++++++--------- 3 files changed, 179 insertions(+), 50 deletions(-) diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index 3a0919ca9947..277d2a1444bd 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + metaminer "github.com/ethereum/go-ethereum/metadium/miner" ) const ( @@ -49,6 +50,33 @@ var ( // Seal implements consensus.Engine, attempting to find a nonce that satisfies // the block's difficulty requirements. func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + if !metaminer.IsPoW() { + // In Metadium, return immediately + ethash.lock.Lock() + 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() + abort := make(chan struct{}) + found := make(chan *types.Block) + go ethash.mine(block, 0, uint64(ethash.rand.Int63()), abort, found) + var result *types.Block + select { + case result = <-found: + select { + case results <- result: + default: + log.Warn("Sealing result is not read by miner", "sealhash", ethash.SealHash(block.Header())) + } + } + return nil + } + // 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() diff --git a/metadium/admin.go b/metadium/admin.go index 330a6e5ce3c6..3fa99027e863 100644 --- a/metadium/admin.go +++ b/metadium/admin.go @@ -1002,8 +1002,7 @@ func (ma *metaAdmin) amPartner() bool { if admin == nil { return false } - return (admin.nodeInfo != nil && admin.nodeInfo.ID == admin.bootNodeId) || - admin.self != nil + return admin.self != nil || (admin.nodeInfo != nil && admin.nodeInfo.ID == admin.bootNodeId) } func AmPartner() bool { diff --git a/miner/worker.go b/miner/worker.go index 9eb0395333e8..8d56fbe609d7 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -360,17 +360,19 @@ func (w *worker) newWorkLoop(recommit time.Duration) { commit(false, commitInterruptNewHead) case <-timer.C: + if !metaminer.IsPoW() { + // In metadium, this timer is repurposed to generate empty + // blocks periodically + commit(false, commitInterruptNone) + continue + } + // If mining is running resubmit a new work cycle periodically to pull in // higher priced transactions. Disable this overhead for pending blocks. if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) { // Short circuit if no new transaction arrives. if atomic.LoadInt32(&w.newTxs) == 0 { - // Metadium: to generate an empty block after maxBlockInterval - if !metaminer.IsPoW() && w.eth.TxPool().PendingEmpty() { - commit(false, commitInterruptNone) - } else { - timer.Reset(recommit) - } + timer.Reset(recommit) continue } commit(true, commitInterruptResubmit) @@ -420,7 +422,11 @@ func (w *worker) mainLoop() { for { select { case req := <-w.newWorkCh: - w.commitNewWork(req.interrupt, req.noempty, req.timestamp) + if metaminer.AmPartner() { + // In metadium, costly interrupt / resubmit is disabled + //w.commitNewWork(req.interrupt, req.noempty, req.timestamp) + w.commitNewWork(nil, req.noempty, req.timestamp) + } case ev := <-w.chainSideCh: // Short circuit for duplicate side blocks @@ -457,7 +463,7 @@ func (w *worker) mainLoop() { uncles = append(uncles, uncle.Header()) return false }) - w.commit(uncles, nil, true, start) + w.commitEx(uncles, nil, true, start) } } @@ -483,9 +489,9 @@ func (w *worker) mainLoop() { } else { // If we're mining, but nothing is being processed, wake on new transactions if w.config.Clique != nil && w.config.Clique.Period == 0 { - w.commitNewWork(nil, false, time.Now().Unix()) - } else if !metaminer.IsPoW() && w.eth.TxPool().PendingOne() && atomic.LoadInt32(&w.newTxs) == 0 { - w.commitNewWork(nil, false, time.Now().Unix()) + if metaminer.AmPartner() { + w.commitNewWork(nil, false, time.Now().Unix()) + } } } atomic.AddInt32(&w.newTxs, int32(len(ev.Txs))) @@ -993,47 +999,34 @@ func (w *worker) ancestorTimes(num *big.Int) []int64 { return ts } -// returns throttle delay if necessary in seconds +// returns throttle delay if necessary in seconds & seconds from the parent // blocks seconds seconds per // 10 1 0.1 // 50 10 0.2 // 100 50 0.5 // 500 500 1 // 1000 2000 2 -func (w *worker) throttleMining(ts []int64) int64 { +func (w *worker) throttleMining(ts []int64) (int64, int64) { t := time.Now().Unix() - var dt int64 + var dt, pt int64 = 0, t - ts[0] // 1000th if dt = t - ts[5]; ts[5] > 0 && dt < 2000 { - return 2000 - dt + return 2000 - dt, pt } if dt = t - ts[4]; ts[4] > 0 && dt < 500 { - return 500 - dt + return 500 - dt, pt } if dt = t - ts[3]; ts[3] > 0 && dt < 50 { - return 50 - dt + return 50 - dt, pt } if dt = t - ts[2]; ts[2] > 0 && dt < 10 { - return 10 - dt + return 10 - dt, pt } - return 0 + return 0, pt } func (w *worker) commitTransactionsEx(num *big.Int, interrupt *int32, tstart time.Time) bool { - if !metaminer.IsMiner(int(num.Int64())) { - log.Debug("Not a miner.") - return true - } else if w.eth.TxPool().PendingEmpty() && time.Now().Unix()-w.chain.CurrentBlock().Time().Int64() < int64(params.MaxIdleBlockInterval) { - log.Debug("No pending transactions.") - return true - } - - log.Debug("Was the miner for", "number", num) - - ts := w.ancestorTimes(num) - throttleCleared := false - // committed transactions in this round committedTxs := map[common.Hash]*types.Transaction{} round := 0 @@ -1087,25 +1080,14 @@ func (w *worker) commitTransactionsEx(num *big.Int, interrupt *int32, tstart tim } n = len(committedTxs) - n } + round++ // less than 500 ms elapsed, transactions are less than 500 and // all handled, then try to get more transactions if time.Since(tstart).Nanoseconds()/1000000 < 500 && 0 < n && n < 500 { - round++ - continue - } else if dt := w.throttleMining(ts); !throttleCleared && dt > 0 { - throttleCleared = true - drt := dt - if drt > 5 { - drt = 5 - } - log.Error("Metadium: too many blocks", "ahead", dt, "sleeping", drt, "pending", len(pending)) - time.Sleep(time.Duration(drt) * time.Second) - round++ continue } else { - round++ break } } @@ -1116,8 +1098,19 @@ func (w *worker) commitTransactionsEx(num *big.Int, interrupt *int32, tstart tim return false } +var busyMining int32 + // commitNewWork generates several new sealing tasks based on the parent block. func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) { + if !metaminer.AmPartner() { + return + } + if atomic.CompareAndSwapInt32(&busyMining, 0, 1) { + defer atomic.StoreInt32(&busyMining, 0) + } else { + return + } + w.mu.RLock() defer w.mu.RUnlock() @@ -1125,6 +1118,23 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) timestamp = tstart.Unix() parent := w.chain.CurrentBlock() + if !metaminer.IsMiner(int(parent.Number().Int64() + 1)) { + return + } + + num := parent.Number() + num.Add(num, common.Big1) + ts := w.ancestorTimes(num) + if dt, pt := w.throttleMining(ts); dt > 0 && pt < int64(params.MaxIdleBlockInterval) { + log.Info("Metadium: too many blocks", "ahead", dt) + return + } else if w.eth.TxPool().PendingEmpty() { + if pt < int64(params.MaxIdleBlockInterval) { + log.Debug("No pending transactions.") + return + } + } + if metaminer.IsPoW() { if parent.Time().Cmp(new(big.Int).SetInt64(timestamp)) >= 0 { timestamp = parent.Time().Int64() + 1 @@ -1137,10 +1147,9 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) } } - num := parent.Number() header := &types.Header{ ParentHash: parent.Hash(), - Number: num.Add(num, common.Big1), + Number: num, GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil), Extra: w.extra, Time: big.NewInt(timestamp), @@ -1206,9 +1215,9 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) commitUncles(w.localUncles) commitUncles(w.remoteUncles) - if !metaminer.IsPoW() { + if !metaminer.IsPoW() { // Metadium if !w.commitTransactionsEx(num, interrupt, tstart) { - w.commit(uncles, w.fullTaskHook, true, tstart) + w.commitEx(uncles, w.fullTaskHook, true, tstart) } return } @@ -1256,6 +1265,8 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) // commit runs any post-transaction state modifications, assembles the final block // and commits new work if consensus engine is running. func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { + panic("None should come here") + if !metaminer.IsMiner(int(w.current.header.Number.Int64())) { return errors.New("Not Miner") } @@ -1297,3 +1308,94 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st } return nil } + +// In Metadium, uncles are not welcome and difficulty is so low, +// there's no reason to run miners asynchronously. +func (w *worker) commitEx(uncles []*types.Header, interval func(), update bool, start time.Time) error { + if !metaminer.IsMiner(int(w.current.header.Number.Int64())) { + return errors.New("Not Miner") + } + // Deep copy receipts here to avoid interaction between different tasks. + receipts := make([]*types.Receipt, len(w.current.receipts)) + for i, l := range w.current.receipts { + receipts[i] = new(types.Receipt) + *receipts[i] = *l + } + s := w.current.state.Copy() + block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) + if err != nil { + return err + } + if w.isRunning() { + createdAt := time.Now() + w.unconfirmed.Shift(block.NumberU64() - 1) + + feesWei := new(big.Int) + for i, tx := range block.Transactions() { + feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), tx.GasPrice())) + } + feesEth := new(big.Float).Quo(new(big.Float).SetInt(feesWei), new(big.Float).SetInt(big.NewInt(params.Ether))) + + log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()), + "uncles", len(uncles), "txs", w.current.tcount, "gas", block.GasUsed(), "fees", feesEth, "elapsed", common.PrettyDuration(time.Since(start))) + + var sealedBlock *types.Block + stopCh := make(chan struct{}) + resultCh := make(chan *types.Block, 1) + if err := w.engine.Seal(w.chain, block, resultCh, stopCh); err != nil { + log.Warn("Block sealing failed", "err", err) + } else { + select { + case sealedBlock = <-resultCh: + } + } + close(stopCh) + close(resultCh) + + if sealedBlock != nil && !w.chain.HasBlock(sealedBlock.Hash(), sealedBlock.NumberU64()) { + var ( + sealhash = w.engine.SealHash(sealedBlock.Header()) + hash = sealedBlock.Hash() + rcpts = make([]*types.Receipt, len(receipts)) + logs []*types.Log + ) + for i, receipt := range receipts { + rcpts[i] = new(types.Receipt) + *rcpts[i] = *receipt + // Update the block hash in all logs since it is now available and not when the + // receipt/log of individual transactions were created. + for _, log := range receipt.Logs { + log.BlockHash = hash + } + logs = append(logs, receipt.Logs...) + } + // Commit block and state to database. + stat, err := w.chain.WriteBlockWithState(sealedBlock, rcpts, s) + if err != nil { + log.Error("Failed writing block to chain", "err", err) + return err + } + log.Info("Successfully sealed new block", "number", sealedBlock.Number(), "sealhash", sealhash, "hash", hash, "elapsed", common.PrettyDuration(time.Since(createdAt))) + + // Broadcast the block and announce chain insertion event + w.mux.Post(core.NewMinedBlockEvent{Block: sealedBlock}) + + var events []interface{} + switch stat { + case core.CanonStatTy: + events = append(events, core.ChainEvent{Block: sealedBlock, Hash: sealedBlock.Hash(), Logs: logs}) + events = append(events, core.ChainHeadEvent{Block: sealedBlock}) + case core.SideStatTy: + events = append(events, core.ChainSideEvent{Block: sealedBlock}) + } + w.chain.PostChainEvents(events, logs) + + // Insert the block into the set of pending ones to resultLoop for confirmations + w.unconfirmed.Insert(sealedBlock.NumberU64(), sealedBlock.Hash()) + } + } + if update { + w.updateSnapshot() + } + return nil +} From db36ea808e880e140fa3bbc3db2f57daa6f7da91 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Sat, 16 Mar 2019 23:00:27 +0000 Subject: [PATCH 2/7] increased worker.newWorkCh channel size to 2 --- miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index 8d56fbe609d7..36cdf15402b8 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -196,7 +196,7 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, txsCh: make(chan core.NewTxsEvent, txChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), chainSideCh: make(chan core.ChainSideEvent, chainSideChanSize), - newWorkCh: make(chan *newWorkReq), + newWorkCh: make(chan *newWorkReq, 2), taskCh: make(chan *task), resultCh: make(chan *types.Block, resultQueueSize), exitCh: make(chan struct{}), From 68d80bcadf73e4fdc3ddaf75ae53c1ca57fa3721 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Sun, 17 Mar 2019 01:52:18 +0000 Subject: [PATCH 3/7] header.Fees is big.Int now, not uint64 to avoid overflow --- consensus/ethash/consensus.go | 4 ++-- core/block_validator.go | 7 ++++--- core/chain_makers.go | 2 +- core/state_processor.go | 14 ++++++++------ core/types.go | 6 ++++-- core/types/block.go | 6 +++--- core/types/gen_header_json.go | 8 ++++---- internal/ethapi/api.go | 2 +- miner/worker.go | 3 ++- 9 files changed, 29 insertions(+), 23 deletions(-) diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 93926b2b7002..875014840346 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -651,7 +651,7 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header } else { blockReward = MetadiumBlockReward coinbase, rewards, err := metaminer.CalculateRewards( - header.Number, blockReward, big.NewInt(int64(header.Fees)), + header.Number, blockReward, header.Fees, func(addr common.Address, amt *big.Int) { state.AddBalance(addr, amt) }) @@ -663,7 +663,7 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header } else { // upon error, rewards go to the coinbase reward := new(big.Int) - reward.Add(blockReward, big.NewInt(int64(header.Fees))) + reward.Add(blockReward, header.Fees) state.AddBalance(header.Coinbase, reward) } } diff --git a/core/block_validator.go b/core/block_validator.go index 3913db226da3..899539b09514 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "math/big" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/state" @@ -77,13 +78,13 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // transition, such as amount of used gas, the receipt roots and the state root // itself. ValidateState returns a database batch if the validation was a success // otherwise nil and an error is returned. -func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas, fees uint64) error { +func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, fees *big.Int) error { header := block.Header() if block.GasUsed() != usedGas { return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) } - if block.Fees() != fees { - return fmt.Errorf("invalid fees collected (remote: %d local: %d)", block.Fees(), fees) + if block.Fees().Cmp(fees) != 0 { + return fmt.Errorf("invalid fees collected (remote: %v local: %v)", block.Fees(), fees) } // Validate the received block's bloom with the one derived from the generated receipts. diff --git a/core/chain_makers.go b/core/chain_makers.go index 2687ebfebc95..f8b3169bb91a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -96,7 +96,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.SetCoinbase(common.Address{}) } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - fees := new(uint64) + fees := new(big.Int) receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, fees, vm.Config{}) if err != nil { panic(err) diff --git a/core/state_processor.go b/core/state_processor.go index bdc478d1cb64..5c5ca04f8aa6 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -17,6 +17,8 @@ package core import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -53,11 +55,11 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. -func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, uint64, error) { +func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, *big.Int, error) { var ( receipts types.Receipts usedGas = new(uint64) - fees = new(uint64) + fees = new(big.Int) header = block.Header() allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()) @@ -71,7 +73,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg statedb.Prepare(tx.Hash(), block.Hash(), i) receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, fees, cfg) if err != nil { - return nil, nil, 0, 0, err + return nil, nil, 0, big.NewInt(0), err } receipts = append(receipts, receipt) allLogs = append(allLogs, receipt.Logs...) @@ -79,14 +81,14 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) - return receipts, allLogs, *usedGas, *fees, nil + return receipts, allLogs, *usedGas, fees, nil } // ApplyTransaction attempts to apply a transaction to the given state database // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, fees *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, fees *big.Int, cfg vm.Config) (*types.Receipt, uint64, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { return nil, 0, err @@ -109,7 +111,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() } *usedGas += gas - *fees += fee + fees.Add(fees, big.NewInt(int64(fee))) // Create a new receipt for the transaction, storing the intermediate root and gas used by the tx // based on the eip phase, we're passing whether the root touch-delete accounts. diff --git a/core/types.go b/core/types.go index b491a0dd3143..4ecef6c52778 100644 --- a/core/types.go +++ b/core/types.go @@ -17,6 +17,8 @@ package core import ( + "math/big" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -32,7 +34,7 @@ type Validator interface { // ValidateState validates the given statedb and optionally the receipts and // gas used. - ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas, fees uint64) error + ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64, fees *big.Int) error } // Processor is an interface for processing blocks using a given initial state. @@ -42,5 +44,5 @@ type Validator interface { // of gas used in the process and return an error if any of the internal rules // failed. type Processor interface { - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, uint64, error) + Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, *big.Int, error) } diff --git a/core/types/block.go b/core/types/block.go index 3a7153f3fdae..d12c326177bf 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -79,7 +79,7 @@ type Header struct { Number *big.Int `json:"number" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Fees uint64 `json:"fees" gencodec:"required"` + Fees *big.Int `json:"fees" gencodec:"required"` Time *big.Int `json:"timestamp" gencodec:"required"` Extra []byte `json:"extraData" gencodec:"required"` Rewards []byte `json:"rewards" gencodec:"required"` @@ -95,7 +95,7 @@ type headerMarshaling struct { Number *hexutil.Big GasLimit hexutil.Uint64 GasUsed hexutil.Uint64 - Fees hexutil.Uint64 + Fees *hexutil.Big Time *hexutil.Big Extra hexutil.Bytes Rewards hexutil.Bytes @@ -297,7 +297,7 @@ func (b *Block) Transaction(hash common.Hash) *Transaction { func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } func (b *Block) GasLimit() uint64 { return b.header.GasLimit } func (b *Block) GasUsed() uint64 { return b.header.GasUsed } -func (b *Block) Fees() uint64 { return b.header.Fees } +func (b *Block) Fees() *big.Int { return b.header.Fees } func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index d78f6d264a32..87981f4ff80c 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -27,7 +27,7 @@ func (h Header) MarshalJSON() ([]byte, error) { Number *hexutil.Big `json:"number" gencodec:"required"` GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Fees hexutil.Uint64 `json:"fees" gencodec:"required"` + Fees *hexutil.Big `json:"fees" gencodec:"required"` Time *hexutil.Big `json:"timestamp" gencodec:"required"` Extra hexutil.Bytes `json:"extraData" gencodec:"required"` Rewards []byte `json:"rewards" gencodec:"required"` @@ -49,7 +49,7 @@ func (h Header) MarshalJSON() ([]byte, error) { enc.Number = (*hexutil.Big)(h.Number) enc.GasLimit = hexutil.Uint64(h.GasLimit) enc.GasUsed = hexutil.Uint64(h.GasUsed) - enc.Fees = hexutil.Uint64(h.Fees) + enc.Fees = (*hexutil.Big)(h.Fees) enc.Time = (*hexutil.Big)(h.Time) enc.Extra = h.Extra enc.Rewards = h.Rewards @@ -75,7 +75,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { Number *hexutil.Big `json:"number" gencodec:"required"` GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Fees *hexutil.Uint64 `json:"fees" gencodec:"required"` + Fees *hexutil.Big `json:"fees" gencodec:"required"` Time *hexutil.Big `json:"timestamp" gencodec:"required"` Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` Rewards *hexutil.Bytes `json:"rewards" gencodec:"required"` @@ -135,7 +135,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { if dec.Fees == nil { return errors.New("missing required field 'fees' for Header") } - h.Fees = uint64(*dec.Fees) + h.Fees = (*big.Int)(dec.Fees) if dec.Time == nil { return errors.New("missing required field 'timestamp' for Header") } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f9964016a0aa..266752a231a3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -894,7 +894,7 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter "size": hexutil.Uint64(b.Size()), "gasLimit": hexutil.Uint64(head.GasLimit), "gasUsed": hexutil.Uint64(head.GasUsed), - "fees": hexutil.Uint64(head.Fees), + "fees": (*hexutil.Big)(head.Fees), "timestamp": (*hexutil.Big)(head.Time), "transactionsRoot": head.TxHash, "receiptsRoot": head.ReceiptHash, diff --git a/miner/worker.go b/miner/worker.go index 36cdf15402b8..4f075450fcce 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -715,7 +715,7 @@ func (w *worker) updateSnapshot() { func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() - receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, &w.current.header.Fees, *w.chain.GetVMConfig()) + receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, w.current.header.Fees, *w.chain.GetVMConfig()) if err != nil { w.current.state.RevertToSnapshot(snap) return nil, err @@ -1153,6 +1153,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil), Extra: w.extra, Time: big.NewInt(timestamp), + Fees: big.NewInt(0), } // Only set the coinbase if our consensus engine is running (avoid spurious block rewards) if w.isRunning() { From ed77e140b4915aa2bff593844bb19a9af9b30695 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Sun, 17 Mar 2019 07:23:05 +0000 Subject: [PATCH 4/7] simplified worker workflow --- metadium/admin.go | 15 +------ metadium/miner/miner.go | 6 +-- metadium/sync.go | 11 +----- miner/worker.go | 88 ++++++++++++++++++++++++++++------------- 4 files changed, 67 insertions(+), 53 deletions(-) diff --git a/metadium/admin.go b/metadium/admin.go index 3fa99027e863..2e3ae54d07b9 100644 --- a/metadium/admin.go +++ b/metadium/admin.go @@ -1352,20 +1352,7 @@ func (ma *metaAdmin) getTxPoolStatus() (pending, queued uint, err error) { } func requirePendingTxs() bool { - if admin == nil { - return false - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - block, err := admin.cli.HeaderByNumber(ctx, nil) - if err != nil { - return false - } - height := int(block.Number.Int64()) - - if !IsMiner(height + 1) { + if !IsMiner() { return false } diff --git a/metadium/miner/miner.go b/metadium/miner/miner.go index 6c9b7a418566..5313344bf404 100644 --- a/metadium/miner/miner.go +++ b/metadium/miner/miner.go @@ -11,7 +11,7 @@ import ( ) var ( - IsMinerFunc func(int) bool + IsMinerFunc func() bool AmPartnerFunc func() bool IsPartnerFunc func(string) bool LogBlockFunc func(int64) @@ -24,11 +24,11 @@ var ( SuggestGasPriceFunc func() *big.Int ) -func IsMiner(height int) bool { +func IsMiner() bool { if IsMinerFunc == nil { return false } else { - return IsMinerFunc(height) + return IsMinerFunc() } } diff --git a/metadium/sync.go b/metadium/sync.go index c092e07a13ab..b554fe1e4e09 100644 --- a/metadium/sync.go +++ b/metadium/sync.go @@ -108,7 +108,7 @@ func (ma *metaAdmin) updateMiner(locked bool) { } } -func IsMiner(height int) bool { +func IsMiner() bool { if params.ConsensusMethod == params.ConsensusPoW { return true } else if params.ConsensusMethod == params.ConsensusETCD { @@ -124,15 +124,8 @@ func IsMiner(height int) bool { } } - /* Sadoc: predictably caused cyclic deadlock. - if height != admin.lastBlock { - admin.update() - } - */ - - admin.updateMiner(false) - if admin.etcdIsLeader() { + admin.updateMiner(false) return true } else { admin.blocksMined = 0 diff --git a/miner/worker.go b/miner/worker.go index 4f075450fcce..aece76b46b98 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -217,7 +217,7 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, } go worker.mainLoop() - go worker.newWorkLoop(recommit) + go worker.newWorkLoopEx(recommit) go worker.resultLoop() go worker.taskLoop() @@ -289,10 +289,6 @@ func (w *worker) close() { // newWorkLoop is a standalone goroutine to submit new mining work upon received events. func (w *worker) newWorkLoop(recommit time.Duration) { - // In metadium, we don't do recommit, so recommit timer is just a simple timer - if !metaminer.IsPoW() { - recommit = time.Second - } var ( interrupt *int32 minRecommit = recommit // minimal resubmit interval specified by user. @@ -314,9 +310,6 @@ func (w *worker) newWorkLoop(recommit time.Duration) { } // recalcRecommit recalculates the resubmitting interval upon feedback. recalcRecommit := func(target float64, inc bool) { - if !metaminer.IsPoW() { - return - } var ( prev = float64(recommit.Nanoseconds()) next float64 @@ -360,13 +353,6 @@ func (w *worker) newWorkLoop(recommit time.Duration) { commit(false, commitInterruptNewHead) case <-timer.C: - if !metaminer.IsPoW() { - // In metadium, this timer is repurposed to generate empty - // blocks periodically - commit(false, commitInterruptNone) - continue - } - // If mining is running resubmit a new work cycle periodically to pull in // higher priced transactions. Disable this overhead for pending blocks. if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) { @@ -413,6 +399,52 @@ func (w *worker) newWorkLoop(recommit time.Duration) { } } +// newWorkLoopEx is Metadium's standalone goroutine to submit new mining work upon received events. +func (w *worker) newWorkLoopEx(recommit time.Duration) { + timer := time.NewTimer(1 * time.Second) + + // commitSimple just starts a new commitNewWork + commitSimple := func() { + if isBusyMining() { + return + } else { + w.newWorkCh <- &newWorkReq{interrupt: nil, noempty: false, timestamp: time.Now().Unix()} + atomic.StoreInt32(&w.newTxs, 0) + } + } + // clearPending cleans the stale pending tasks. + clearPending := func(number uint64) { + w.pendingMu.Lock() + for h, t := range w.pendingTasks { + if t.block.NumberU64()+staleThreshold <= number { + delete(w.pendingTasks, h) + } + } + w.pendingMu.Unlock() + } + + for { + select { + case <-w.startCh: + clearPending(w.chain.CurrentBlock().NumberU64()) + commitSimple() + + case head := <-w.chainHeadCh: + clearPending(head.Block.NumberU64()) + commitSimple() + + case <-timer.C: + commitSimple() + timer.Reset(time.Second) + + case <-w.resubmitIntervalCh: + case <-w.resubmitAdjustCh: + case <-w.exitCh: + return + } + } +} + // mainLoop is a standalone goroutine to regenerate the sealing task based on the received event. func (w *worker) mainLoop() { defer w.txsSub.Unsubscribe() @@ -422,7 +454,7 @@ func (w *worker) mainLoop() { for { select { case req := <-w.newWorkCh: - if metaminer.AmPartner() { + if !isBusyMining() && metaminer.AmPartner() { // In metadium, costly interrupt / resubmit is disabled //w.commitNewWork(req.interrupt, req.noempty, req.timestamp) w.commitNewWork(nil, req.noempty, req.timestamp) @@ -489,9 +521,9 @@ func (w *worker) mainLoop() { } else { // If we're mining, but nothing is being processed, wake on new transactions if w.config.Clique != nil && w.config.Clique.Period == 0 { - if metaminer.AmPartner() { - w.commitNewWork(nil, false, time.Now().Unix()) - } + w.commitNewWork(nil, false, time.Now().Unix()) + } else if !metaminer.IsPoW() && !isBusyMining() && metaminer.AmPartner() { + w.commitNewWork(nil, false, time.Now().Unix()) } } atomic.AddInt32(&w.newTxs, int32(len(ev.Txs))) @@ -1100,9 +1132,13 @@ func (w *worker) commitTransactionsEx(num *big.Int, interrupt *int32, tstart tim var busyMining int32 +func isBusyMining() bool { + return atomic.LoadInt32(&busyMining) != 0 +} + // commitNewWork generates several new sealing tasks based on the parent block. func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) { - if !metaminer.AmPartner() { + if !metaminer.AmPartner() || !metaminer.IsMiner() { return } if atomic.CompareAndSwapInt32(&busyMining, 0, 1) { @@ -1118,15 +1154,13 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) timestamp = tstart.Unix() parent := w.chain.CurrentBlock() - if !metaminer.IsMiner(int(parent.Number().Int64() + 1)) { - return - } - num := parent.Number() num.Add(num, common.Big1) ts := w.ancestorTimes(num) - if dt, pt := w.throttleMining(ts); dt > 0 && pt < int64(params.MaxIdleBlockInterval) { + if dt, pt := w.throttleMining(ts); dt > 0 && pt < 5 { + // sleep 1 second here to prevent unnecessary checks log.Info("Metadium: too many blocks", "ahead", dt) + time.Sleep(time.Second) return } else if w.eth.TxPool().PendingEmpty() { if pt < int64(params.MaxIdleBlockInterval) { @@ -1268,7 +1302,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { panic("None should come here") - if !metaminer.IsMiner(int(w.current.header.Number.Int64())) { + if !metaminer.IsMiner() { return errors.New("Not Miner") } @@ -1313,7 +1347,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st // In Metadium, uncles are not welcome and difficulty is so low, // there's no reason to run miners asynchronously. func (w *worker) commitEx(uncles []*types.Header, interval func(), update bool, start time.Time) error { - if !metaminer.IsMiner(int(w.current.header.Number.Int64())) { + if !metaminer.IsMiner() { return errors.New("Not Miner") } // Deep copy receipts here to avoid interaction between different tasks. From 50d8b42cfdafeac6daba2d8899500d824b092a90 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Mon, 18 Mar 2019 07:56:15 +0000 Subject: [PATCH 5/7] initialize pending state for non-mining nodes --- miner/worker.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/miner/worker.go b/miner/worker.go index aece76b46b98..c90f5c779a22 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -427,6 +427,7 @@ func (w *worker) newWorkLoopEx(recommit time.Duration) { select { case <-w.startCh: clearPending(w.chain.CurrentBlock().NumberU64()) + w.initPending() commitSimple() case head := <-w.chainHeadCh: @@ -1297,6 +1298,38 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) w.commit(uncles, w.fullTaskHook, true, tstart) } +// initPending initialize pending state +func (w *worker) initPending() { + if atomic.CompareAndSwapInt32(&busyMining, 0, 1) { + defer atomic.StoreInt32(&busyMining, 0) + } else { + return + } + + w.mu.RLock() + defer w.mu.RUnlock() + + parent := w.chain.CurrentBlock() + + num := parent.Number() + num.Add(num, common.Big1) + header := &types.Header{ + ParentHash: parent.Hash(), + Number: num, + GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil), + Extra: w.extra, + Time: big.NewInt(time.Now().Unix()), + Fees: big.NewInt(0), + } + header.Coinbase = w.coinbase + if err := w.engine.Prepare(w.chain, header); err != nil { + log.Error("Failed to prepare header for mining", "err", err) + return + } + w.makeCurrent(parent, header) + w.updateSnapshot() +} + // commit runs any post-transaction state modifications, assembles the final block // and commits new work if consensus engine is running. func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { From bf4db612f682dc312c86ae8c586bbeef94f01976 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Mon, 18 Mar 2019 08:28:23 +0000 Subject: [PATCH 6/7] updated mainnet genesis --- metadium/scripts/mainnet-config.json | 36 +++++++++++++-------------- metadium/scripts/mainnet-genesis.json | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/metadium/scripts/mainnet-config.json b/metadium/scripts/mainnet-config.json index b3cd4e121a7d..b358981a2d3f 100644 --- a/metadium/scripts/mainnet-config.json +++ b/metadium/scripts/mainnet-config.json @@ -2,77 +2,77 @@ "extraData": "Our vision is to create a free world through self-sovereign identity. / When I discover who I am, I'll be free. -- Ralph Ellison, Invisible Man", "members": [ { - "addr": "0x7eA34544DFA38F6614281adA30af1259c9BCA9Ec", + "addr": "0x880a74d68b09418136c4442d1ea0f5cc72e5325a", "stake": 39840000, "name": "meta1", "ip": "10.140.0.202", "port": 8589, - "id": "0xfa51cf4a0807d233025a4eddf6b469647ab7b2560a31916be5900ada5c145949b61fb550f61a24b1f427448c6b9bf8aeb682969e11643546fdb3b588441241ac", + "id": "0x1ec261dbce3ce00226b797e300ba56863ff65c138263b98145dcd97b4ea3a4c7a8d20414e7a0185f32cc708d0c1c995a877e6c7876f50abc13f7740b9ac307bf", "bootnode": true }, { - "addr": "0xC03B19F95D409c26b64B44292827a26989D2E8d0", + "addr": "0xbdf9acd85b579ea271f91e292ec6e67ad78652f2", "stake": 4980000, "name": "meta2", "ip": "10.140.0.82", "port": 8589, - "id": "0x727c4813c68ecec028bc7323d756043257fd41ef9d13d89a4df4757020b752d1b9bc39ca764cb8560fe70164ced77fe507f9d4e5bcf2746dc2ff82a64cfd29e4" + "id": "0xa4925993136b84a1212244f85da9d8dc4f4e52bd06e2c79961298ee3c5da883552ce5756b5b0e8b29ac5b004793fc415117c0b36ca62e8516248e03324268b1b" }, { - "addr": "0xcFFf678CAfa652227c7A98ec6BcBFba0E3d1da19", + "addr": "0xd8f5272ef21a50c5adb0fcef31eb9e91ac4eb2f5", "stake": 4980000, "name": "meta3", "ip": "10.140.0.185", "port": 8589, - "id": "0x51fb43d83599e03b973d7f7207bbcf890a191739ee0e62ce878e619a6951ff4696181876c7f9f5b525609d698fd65747f9b25afa7e98a1755d39e36e2ea470c6" + "id": "0xd90e1d46b1118fae52b6b1fb6f83a51846f22cfa639b4ba441002f68d8798abc79b19ce13868b5998a75715a8c2abc9d34594733be59961e5a2a79a42391b430" }, { - "addr": "0x2d74530C0C196De44d3906822053bf336F18a16e", + "addr": "0xe7080384c22aa9b232993e2011b8c16585570524", "stake": 4980000, "name": "meta4", "ip": "10.141.0.143", "port": 8589, - "id": "0xff78400000e02d65f6e02f236efdfbda48f01644cfe456307f117f51e3038cbf34a63e85b77151a40271ec27691f834f670b56682bd39d61d9c7efe13c6331b4" + "id": "0x9ea9aa7a040d33d595ccec7ac10ead26712629dfebd85d563deb606aa0b6a0782684ae43584e4eed40635e054ca2abadd8e658fbbc760d88d7f60f48cfcf3d5d" }, { - "addr": "0x1B892F4bf95b25375D7E83A7D2E2641A4bdf3bfB", + "addr": "0xa4a3a5b308d2319af64def1568cc80a82f40ea86", "stake": 4980000, "name": "meta5", "ip": "10.141.0.81", "port": 8589, - "id": "0xcd5367698e8ed214f02908cb0b5bb29df2a17365bb8de931881b1e2a6dd22418a09166fdd136039795cdb4bf2469690f3eb8c4e02b3146e4c1278c41cedb14e5" + "id": "0x54eb3f5c1016f35971a6e0e6906ac5f4927827c18b100ac1ec486d7461c31b09daa9c5319968c46997a784e0757b086c55780c7b49a9ed8fb4b4caa00b6b13d0" }, { - "addr": "0xcD8491486c39a72F0e02E0248b5E768260a34199", + "addr": "0x6ce8328a6460d6fe4c17fdbbf6faa88120dd65b8", "stake": 4980000, "name": "meta6", "ip": "10.141.0.95", "port": 8589, - "id": "0x7471c90d2cd38bd386a4f231c48dce49fcf311169c5d4d1f7e38c2b7259d8e0333ecaa7a6ae2fbfa2e1957e24c7079ed95041ba936a6265320721b8ac483ed72" + "id": "0x5417d5cc1fd5d75cd15852d06a5f39e834407564543c70ea2ccebb49289a8bd9fba096aa48ff3c8696ba1cae8921166ed6370a8876dc7220525b636ced1d5504" }, { - "addr": "0x6cB313cb0cA94FC7061075F7Cc7EBcE60d8cb113", + "addr": "0xfb0a7d2536b9e42b627315c5bb938f1a6524f4e3", "stake": 4980000, "name": "meta7", "ip": "10.142.0.26", "port": 8589, - "id": "0xb89545c704b35777c8e357435b48028c46543692db0798b8911135751a2340d915ba7f126780e0f508a8569b01d98467f260b6b86975a11900a7aede1330a1c0" + "id": "0xe3693591cf9cb3dd3af0da665f31d59b47335c00770bc76c930fc7cfa3f3771c094c5b94fba4784d8229c8ecf23ab4e4fdec269145b0a52da3bae3cdfe75b171" }, { - "addr": "0xcC16B5A6e2c851D023e8654EacD9b9Fa9fe41B86", + "addr": "0x2dc152f7c9cacdffbfefe5774af1fdf14df0c6f6", "stake": 4980000, "name": "meta8", "ip": "10.142.0.63", "port": 8589, - "id": "0x71efa945303640b68040b1d17b0f49ff7eb24e80fcf0432025a4776b6def8ff956997d60ba4e83a131b016475a9e90d4d5fb226a8c04375a1dd4f73ad95a5528" + "id": "0x05fd80d533ad47efbd80b024c4c7778c5887f6eae6e46a6dd9b8d7c0a111881b46f1dcf4d6515d3338efc6a4e645610d01600143975a6338662c945afb24c868" }, { - "addr": "0x71a5FFB0f3fA62D32aD9010E10284E11F392dED4", + "addr": "0xa996eeffe2d9d3cffdce5b7fc51c357da7abea6d", "stake": 4980000, "name": "meta9", "ip": "10.142.0.20", "port": 8589, - "id": "0x9765d6119aca8cae63ee2278680929ba6c4ff066da86ff5125c6aa326306bf341b34c32cc8f26b35340959d8cb3cb037829411fd9f87f579fbc69f12f18fbccc" + "id": "0xea8cb242d728c81843c03fda500fa67ce03d49741b36c357a43558c1a74aac039c296985feb37dc54670131f657d7d0f94f5ce87e83d87bb4e09f4f60051130e" } ], "accounts": [ diff --git a/metadium/scripts/mainnet-genesis.json b/metadium/scripts/mainnet-genesis.json index d0256803ef2a..c4fd21773897 100644 --- a/metadium/scripts/mainnet-genesis.json +++ b/metadium/scripts/mainnet-genesis.json @@ -12280,7 +12280,7 @@ "balance": "0x3f514193abb840000" } }, - "coinbase": "0x7eA34544DFA38F6614281adA30af1259c9BCA9Ec", + "coinbase": "0x880a74d68b09418136c4442D1eA0f5cC72E5325A", "config": { "byzantiumBlock": 0, "chainId": 11, @@ -12289,7 +12289,7 @@ "homesteadBlock": 0 }, "difficulty": "0x1", - "extraData": "0x4f757220766973696f6e20697320746f206372656174652061206672656520776f726c64207468726f7567682073656c662d736f7665726569676e206964656e746974792e202f205768656e204920646973636f7665722077686f204920616d2c2049276c6c20626520667265652e202d2d2052616c706820456c6c69736f6e2c20496e76697369626c65204d616e0a30786661353163663461303830376432333330323561346564646636623436393634376162376232353630613331393136626535393030616461356331343539343962363166623535306636316132346231663432373434386336623962663861656236383239363965313136343335343666646233623538383434313234316163", + "extraData": "0x4f757220766973696f6e20697320746f206372656174652061206672656520776f726c64207468726f7567682073656c662d736f7665726569676e206964656e746974792e202f205768656e204920646973636f7665722077686f204920616d2c2049276c6c20626520667265652e202d2d2052616c706820456c6c69736f6e2c20496e76697369626c65204d616e0a30783165633236316462636533636530303232366237393765333030626135363836336666363563313338323633623938313435646364393762346561336134633761386432303431346537613031383566333263633730386430633163393935613837376536633738373666353061626331336637373430623961633330376266", "gasLimit": "0x10000000", "minerNodeId": "0x0", "minerNodeSig": "0x0", From 7f4a4ab0688932a7c469e2133534d106b7faa7f5 Mon Sep 17 00:00:00 2001 From: Uh Sado Date: Mon, 18 Mar 2019 22:11:41 +0000 Subject: [PATCH 7/7] updated embedded mainnet genesis --- core/metadium_genesis.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/metadium_genesis.go b/core/metadium_genesis.go index 606ebcf2b2d6..9a5ffb10f496 100644 --- a/core/metadium_genesis.go +++ b/core/metadium_genesis.go @@ -12286,7 +12286,7 @@ var ( "balance": "0x3f514193abb840000" } }, - "coinbase": "0x7eA34544DFA38F6614281adA30af1259c9BCA9Ec", + "coinbase": "0x880a74d68b09418136c4442D1eA0f5cC72E5325A", "config": { "byzantiumBlock": 0, "chainId": 11, @@ -12295,7 +12295,7 @@ var ( "homesteadBlock": 0 }, "difficulty": "0x1", - "extraData": "0x4f757220766973696f6e20697320746f206372656174652061206672656520776f726c64207468726f7567682073656c662d736f7665726569676e206964656e746974792e202f205768656e204920646973636f7665722077686f204920616d2c2049276c6c20626520667265652e202d2d2052616c706820456c6c69736f6e2c20496e76697369626c65204d616e0a30786661353163663461303830376432333330323561346564646636623436393634376162376232353630613331393136626535393030616461356331343539343962363166623535306636316132346231663432373434386336623962663861656236383239363965313136343335343666646233623538383434313234316163", + "extraData": "0x4f757220766973696f6e20697320746f206372656174652061206672656520776f726c64207468726f7567682073656c662d736f7665726569676e206964656e746974792e202f205768656e204920646973636f7665722077686f204920616d2c2049276c6c20626520667265652e202d2d2052616c706820456c6c69736f6e2c20496e76697369626c65204d616e0a30783165633236316462636533636530303232366237393765333030626135363836336666363563313338323633623938313435646364393762346561336134633761386432303431346537613031383566333263633730386430633163393935613837376536633738373666353061626331336637373430623961633330376266", "gasLimit": "0x10000000", "minerNodeId": "0x0", "minerNodeSig": "0x0",