From 03513e267d25b5086b3f905b6d1bc5635fcda845 Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 14 Aug 2019 23:55:12 -0400 Subject: ... --- cmd/utils/flags.go | 5 +++-- consensus/dummy/consensus.go | 14 ++++++++++++-- coreth.go | 12 +++++++++--- eth/backend.go | 10 +++++----- examples/payments/main.go | 19 +++++++++++++------ miner/miner.go | 5 +++-- miner/worker.go | 20 +++++++++++++++----- 7 files changed, 60 insertions(+), 25 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 54dc9cd..d9f0b41 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/consensus" + "github.com/Determinant/coreth/consensus/dummy" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -49,7 +50,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics/influxdb" - "github.com/ethereum/go-ethereum/miner" + "github.com/Determinant/coreth/miner" "github.com/Determinant/coreth/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discv5" @@ -1481,7 +1482,7 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) { panic("not supported") } else { err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - fullNode, err := eth.New(ctx, cfg) + fullNode, err := eth.New(ctx, cfg, &dummy.ConsensusCallbacks{}) if fullNode != nil && cfg.LightServ > 0 { panic("not supported") } diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go index 6b03844..0086581 100644 --- a/consensus/dummy/consensus.go +++ b/consensus/dummy/consensus.go @@ -17,7 +17,16 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +type ConsensusCallbacks struct { + OnSeal func(*types.Block) +} + type DummyEngine struct { + cb *ConsensusCallbacks +} + +func NewDummyEngine(cb *ConsensusCallbacks) *DummyEngine { + return &DummyEngine { cb: cb } } var ( @@ -192,8 +201,9 @@ uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { } func (self *DummyEngine) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - //time.Sleep(1000 * time.Millisecond) - fmt.Printf("sealed %s\n", block.ParentHash().String()) + if self.cb.OnSeal != nil { + self.cb.OnSeal(block) + } results <- block return nil } diff --git a/coreth.go b/coreth.go index e769d06..e5bbef9 100644 --- a/coreth.go +++ b/coreth.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/Determinant/coreth/eth" "github.com/Determinant/coreth/node" + "github.com/Determinant/coreth/consensus/dummy" "github.com/ethereum/go-ethereum/crypto" ) @@ -19,10 +20,10 @@ type Hash = common.Hash type ETHChain struct { backend *eth.Ethereum + cb *dummy.ConsensusCallbacks } - func isLocalBlock(block *types.Block) bool { return false } @@ -33,8 +34,9 @@ func NewETHChain(config *eth.Config, etherBase *common.Address) *ETHChain { } mux := new(event.TypeMux) ctx := node.NewServiceContext(mux) - backend, _ := eth.New(&ctx, config) - chain := ÐChain { backend: backend } + cb := new(dummy.ConsensusCallbacks) + backend, _ := eth.New(&ctx, config, cb) + chain := ÐChain { backend: backend, cb: cb } if etherBase == nil { etherBase = &common.Address{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -65,6 +67,10 @@ func (self *ETHChain) AddLocalTxs(txs []*types.Transaction) []error { return self.backend.TxPool().AddLocals(txs) } +func (self *ETHChain) SetOnSeal(cb func(*types.Block)) { + self.cb.OnSeal = cb +} + type Key struct { Address common.Address PrivateKey *ecdsa.PrivateKey diff --git a/eth/backend.go b/eth/backend.go index d99c099..a2cda02 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -116,7 +116,7 @@ func (s *Ethereum) SetContractBackend(backend bind.ContractBackend) { // New creates a new Ethereum object (including the // initialisation of the common Ethereum object) -func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { +func New(ctx *node.ServiceContext, config *Config, cb *dummy.ConsensusCallbacks) (*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") @@ -150,7 +150,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { chainDb: chainDb, eventMux: ctx.EventMux, accountManager: ctx.AccountManager, - engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb), + engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb, cb), shutdownChan: make(chan bool), networkID: config.NetworkId, gasPrice: config.Miner.GasPrice, @@ -214,7 +214,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if eth.protocolManager, err = NewProtocolManager(chainConfig, checkpoint, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, cacheLimit, config.Whitelist); err != nil { return nil, err } - eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock, config.Miner.ManualMining) + eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil} @@ -245,8 +245,8 @@ func makeExtraData(extra []byte) []byte { } // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service -func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { - return new(dummy.DummyEngine) +func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database, cb *dummy.ConsensusCallbacks) consensus.Engine { + return dummy.NewDummyEngine(cb) } // APIs return the collection of RPC services the ethereum package offers. diff --git a/examples/payments/main.go b/examples/payments/main.go index 46e4e58..8a1dca8 100644 --- a/examples/payments/main.go +++ b/examples/payments/main.go @@ -9,7 +9,6 @@ import ( "math/big" //"encoding/hex" "github.com/ethereum/go-ethereum/core/types" - //"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/Determinant/coreth/eth" @@ -42,7 +41,7 @@ func main() { Ethash: nil, } - genBalance := big.NewInt(1000000000000000000) + genBalance := big.NewInt(100000000000000000) genKey, _ := coreth.NewKey(rand.Reader) config.Genesis = &core.Genesis{ @@ -56,24 +55,32 @@ func main() { } config.Miner.ManualMining = true + config.Miner.ManualUncle = true chainID := chainConfig.ChainID nonce := uint64(0) value := big.NewInt(1000000000000) gasLimit := 21000 - gasPrice := big.NewInt(1000) + gasPrice := big.NewInt(1000000000) bob, err := coreth.NewKey(rand.Reader); checkError(err) chain := coreth.NewETHChain(&config, nil) + chain.SetOnSeal(func(block *types.Block) { + go func() { + time.Sleep(1000 * time.Millisecond) + chain.GenBlock() + }() + }) chain.Start() + chain.GenBlock() for i := 0; i < 10; i++ { tx := types.NewTransaction(nonce, bob.Address, value, uint64(gasLimit), gasPrice, nil) signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), genKey.PrivateKey); checkError(err) - chain.AddLocalTxs([]*types.Transaction{signedTx}) - time.Sleep(2000 * time.Millisecond) + _ = signedTx + chain.AddRemoteTxs([]*types.Transaction{signedTx}) + time.Sleep(1000 * time.Millisecond) nonce++ - chain.GenBlock() } c := make(chan os.Signal, 1) diff --git a/miner/miner.go b/miner/miner.go index 4e36fed..53a37b0 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -49,15 +49,16 @@ type Config struct { Recommit time.Duration // The time interval for miner to re-create mining work. Noverify bool // Disable remote mining solution verification(only useful in ethash). ManualMining bool + ManualUncle bool } type Miner struct { w *worker } -func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(block *types.Block) bool, manualMining bool) *Miner { +func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(block *types.Block) bool) *Miner { return &Miner { - w: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, manualMining), + w: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock), } } diff --git a/miner/worker.go b/miner/worker.go index cb0ec7b..c1a82ce 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -181,9 +181,10 @@ type worker struct { fullTaskHook func() // Method to call before pushing the full sealing task. resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. manualMining bool + manualUncle bool } -func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool, manualMining bool) *worker { +func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool) *worker { worker := &worker{ config: config, chainConfig: chainConfig, @@ -206,7 +207,8 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus startCh: make(chan struct{}, 1), resubmitIntervalCh: make(chan time.Duration), resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize), - manualMining: manualMining, + manualMining: config.ManualMining, + manualUncle: config.ManualUncle, } // Subscribe NewTxsEvent for tx pool worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh) @@ -361,6 +363,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { clearPending(w.chain.CurrentBlock().NumberU64()) timestamp = time.Now().Unix() if !w.manualMining { + log.Warn("commit ch") commit(false, commitInterruptNewHead) } @@ -368,6 +371,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { clearPending(head.Block.NumberU64()) timestamp = time.Now().Unix() if !w.manualMining { + log.Warn("commit update") commit(false, commitInterruptNewHead) } @@ -380,6 +384,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { timer.Reset(recommit) continue } + log.Warn("commit resubmit") commit(true, commitInterruptResubmit) } @@ -445,7 +450,8 @@ func (w *worker) mainLoop() { } // If our mining block contains less than 2 uncle blocks, // add the new uncle block if valid and regenerate a mining block. - if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 { + if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 && !w.manualUncle { + log.Warn("wtf") start := time.Now() if err := w.commitUncle(w.current, ev.Block.Header()); err == nil { var uncles []*types.Header @@ -611,7 +617,9 @@ func (w *worker) resultLoop() { logs = append(logs, receipt.Logs...) } // Commit block and state to database. + //fmt.Printf("parent1: %s\n", w.chain.CurrentBlock().Hash().String()) stat, err := w.chain.WriteBlockWithState(block, receipts, task.state) + //fmt.Printf("parent2: %s\n", w.chain.CurrentBlock().Hash().String()) if err != nil { log.Error("Failed writing block to chain", "err", err) continue @@ -938,9 +946,10 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) commitUncles(w.localUncles) commitUncles(w.remoteUncles) - if !noempty { + if !noempty && !w.manualUncle { // Create an empty block based on temporary copied state for sealing in advance without waiting block // execution finished. + log.Warn("commit n1") w.commit(uncles, nil, false, tstart) } @@ -951,7 +960,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) return } // Short circuit if there is no available pending transactions - if len(pending) == 0 { + if len(pending) == 0 && !w.manualMining { w.updateSnapshot() return } @@ -975,6 +984,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) return } } + log.Warn("commit n2") w.commit(uncles, w.fullTaskHook, true, tstart) } -- cgit v1.2.3-70-g09d2