aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2019-08-12 18:10:03 -0400
committerDeterminant <[email protected]>2019-08-12 18:10:03 -0400
commitbc9539a1b60dc80946bc867681eb32ecae4f0d66 (patch)
tree0d691d52fecd2e3a52482d3420310e12aec95580
parentfd39e6b30af5d855dce23899394e6ef80a2c0a41 (diff)
make the basic demo work
-rw-r--r--consensus/dummy/consensus.go234
-rw-r--r--coreth.go245
-rw-r--r--eth/backend.go50
-rw-r--r--examples/payments/main.go35
-rw-r--r--miner/miner.go51
5 files changed, 312 insertions, 303 deletions
diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go
new file mode 100644
index 0000000..a496262
--- /dev/null
+++ b/consensus/dummy/consensus.go
@@ -0,0 +1,234 @@
+package dummy
+
+import (
+ "fmt"
+ "time"
+ "errors"
+ "runtime"
+ "math/big"
+ "golang.org/x/crypto/sha3"
+
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+type DummyEngine struct {
+}
+
+var (
+ allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks
+)
+
+var (
+ errZeroBlockTime = errors.New("timestamp equals parent's")
+)
+
+// modified from consensus.go
+func (self *DummyEngine) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
+ // Ensure that the header's extra-data section is of a reasonable size
+ if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
+ return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
+ }
+ // Verify the header's timestamp
+ if !uncle {
+ if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) {
+ return consensus.ErrFutureBlock
+ }
+ }
+ if header.Time <= parent.Time {
+ return errZeroBlockTime
+ }
+ // Verify that the gas limit is <= 2^63-1
+ cap := uint64(0x7fffffffffffffff)
+ if header.GasLimit > cap {
+ return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
+ }
+ // 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 that the gas limit remains within allowed bounds
+ diff := int64(parent.GasLimit) - int64(header.GasLimit)
+ if diff < 0 {
+ diff *= -1
+ }
+ limit := parent.GasLimit / params.GasLimitBoundDivisor
+
+ if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
+ return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
+ }
+ // 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 := self.VerifySeal(chain, header); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (self *DummyEngine) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) 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
+ }
+ if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
+ return nil // known block
+ }
+ return self.verifyHeader(chain, headers[index], parent, false, seals[index])
+}
+
+func (self *DummyEngine) Author(header *types.Header) (common.Address, error) {
+ addr := common.Address{}
+ return addr, nil
+}
+
+func (self *DummyEngine) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
+ // Short circuit if the header is known, or it's parent not
+ number := header.Number.Uint64()
+ if chain.GetHeader(header.Hash(), number) != nil {
+ return nil
+ }
+ parent := chain.GetHeader(header.ParentHash, number-1)
+ if parent == nil {
+ return consensus.ErrUnknownAncestor
+ }
+ // Sanity checks passed, do a proper verification
+ return self.verifyHeader(chain, header, parent, false, seal)
+}
+
+func (self *DummyEngine) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
+ // 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{})
+ )
+ for i := 0; i < workers; i++ {
+ go func() {
+ for index := range inputs {
+ errors[index] = self.verifyHeaderWorker(chain, headers, seals, index)
+ 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 (self *DummyEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
+ return nil
+}
+
+func (self *DummyEngine) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
+ return nil
+}
+
+func (self *DummyEngine) Prepare(chain consensus.ChainReader, header *types.Header) error {
+ header.Difficulty = big.NewInt(0)
+ return nil
+}
+
+func (self *DummyEngine) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
+uncles []*types.Header) {
+ // commit the final state root
+ header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
+}
+
+func (self *DummyEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
+uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
+ // commit the final state root
+ header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
+
+ // Header seems complete, assemble into a block and return
+ return types.NewBlock(header, txs, uncles, receipts), nil
+}
+
+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())
+ results <- block
+ return nil
+}
+
+func (self *DummyEngine) SealHash(header *types.Header) (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+
+ rlp.Encode(hasher, []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,
+ })
+ hasher.Sum(hash[:0])
+ return hash
+}
+
+func (self *DummyEngine) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
+ return big.NewInt(0)
+}
+
+func (self *DummyEngine) APIs(chain consensus.ChainReader) []rpc.API {
+ return nil
+}
+
+func (self *DummyEngine) Close() error {
+ return nil
+}
diff --git a/coreth.go b/coreth.go
index ec60ce6..74aabcb 100644
--- a/coreth.go
+++ b/coreth.go
@@ -1,26 +1,14 @@
package coreth
import (
- "math/big"
- "fmt"
- "time"
- "errors"
- "runtime"
"io"
"crypto/ecdsa"
- "golang.org/x/crypto/sha3"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
//"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/consensus"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/Determinant/coreth/miner"
"github.com/Determinant/coreth/eth"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc"
"github.com/Determinant/coreth/node"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -30,262 +18,39 @@ type Block = types.Block
type Hash = common.Hash
type ETHChain struct {
- mux *event.TypeMux
backend *eth.Ethereum
- worker *miner.Worker
}
-type DummyEngine struct {
-}
-
-var (
- allowedFutureBlockTime = 15 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks
-)
-
-var (
- errZeroBlockTime = errors.New("timestamp equals parent's")
-)
-
-// modified from consensus.go
-func (self *DummyEngine) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
- // Ensure that the header's extra-data section is of a reasonable size
- if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
- return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
- }
- // Verify the header's timestamp
- if !uncle {
- if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) {
- return consensus.ErrFutureBlock
- }
- }
- if header.Time <= parent.Time {
- return errZeroBlockTime
- }
- // Verify that the gas limit is <= 2^63-1
- cap := uint64(0x7fffffffffffffff)
- if header.GasLimit > cap {
- return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
- }
- // 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 that the gas limit remains within allowed bounds
- diff := int64(parent.GasLimit) - int64(header.GasLimit)
- if diff < 0 {
- diff *= -1
- }
- limit := parent.GasLimit / params.GasLimitBoundDivisor
-
- if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
- return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
- }
- // 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 := self.VerifySeal(chain, header); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (self *DummyEngine) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) 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
- }
- if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
- return nil // known block
- }
- return self.verifyHeader(chain, headers[index], parent, false, seals[index])
-}
-
-func (self *DummyEngine) Author(header *types.Header) (common.Address, error) {
- addr := common.Address{}
- return addr, nil
-}
-
-func (self *DummyEngine) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
- // Short circuit if the header is known, or it's parent not
- number := header.Number.Uint64()
- if chain.GetHeader(header.Hash(), number) != nil {
- return nil
- }
- parent := chain.GetHeader(header.ParentHash, number-1)
- if parent == nil {
- return consensus.ErrUnknownAncestor
- }
- // Sanity checks passed, do a proper verification
- return self.verifyHeader(chain, header, parent, false, seal)
-}
-
-func (self *DummyEngine) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
- // 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{})
- )
- for i := 0; i < workers; i++ {
- go func() {
- for index := range inputs {
- errors[index] = self.verifyHeaderWorker(chain, headers, seals, index)
- 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 (self *DummyEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
- return nil
-}
-
-func (self *DummyEngine) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
- return nil
-}
-
-func (self *DummyEngine) Prepare(chain consensus.ChainReader, header *types.Header) error {
- header.Difficulty = big.NewInt(0)
- return nil
-}
-
-func (self *DummyEngine) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
-uncles []*types.Header) {
- // commit the final state root
- header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
-}
-
-func (self *DummyEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
-uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
- // commit the final state root
- header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
-
- // Header seems complete, assemble into a block and return
- return types.NewBlock(header, txs, uncles, receipts), nil
-}
-
-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())
- results <- block
- return nil
-}
-
-func (self *DummyEngine) SealHash(header *types.Header) (hash common.Hash) {
- hasher := sha3.NewLegacyKeccak256()
-
- rlp.Encode(hasher, []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,
- })
- hasher.Sum(hash[:0])
- return hash
-}
-
-func (self *DummyEngine) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
- return big.NewInt(0)
-}
-
-func (self *DummyEngine) APIs(chain consensus.ChainReader) []rpc.API {
- return nil
-}
-
-func (self *DummyEngine) Close() error {
- return nil
-}
func isLocalBlock(block *types.Block) bool {
return false
}
-func NewETHChain(config *eth.Config, chainConfig *params.ChainConfig, etherBase *common.Address) *ETHChain {
+func NewETHChain(config *eth.Config, etherBase *common.Address) *ETHChain {
if config == nil {
config = &eth.DefaultConfig
}
- if chainConfig == nil {
- chainConfig = params.MainnetChainConfig
- }
mux := new(event.TypeMux)
ctx := node.NewServiceContext(mux)
backend, _ := eth.New(&ctx, config)
- chain := &ETHChain {
- mux: mux,
- backend: backend,
- worker: miner.NewWorker(&config.Miner, chainConfig, &DummyEngine{}, backend, mux, isLocalBlock),
- }
+ chain := &ETHChain { backend: backend }
if etherBase == nil {
etherBase = &common.Address{
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
}
- chain.worker.SetEtherbase(*etherBase)
+ backend.SetEtherbase(*etherBase)
return chain
}
func (self *ETHChain) Start() {
- self.worker.Start()
+ self.backend.StartMining(0)
}
func (self *ETHChain) Stop() {
- self.worker.Stop()
+ self.backend.Stop()
}
func (self *ETHChain) AddRemoteTxs(txs []*types.Transaction) []error {
diff --git a/eth/backend.go b/eth/backend.go
index 048074d..dd91405 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
mycore "github.com/Determinant/coreth/core"
+ "github.com/Determinant/coreth/consensus/dummy"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
@@ -45,7 +46,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/Determinant/coreth/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
- "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/enr"
@@ -245,33 +246,7 @@ 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 {
- // If proof-of-authority is requested, set it up
- if chainConfig.Clique != nil {
- return clique.New(chainConfig.Clique, db)
- }
- // Otherwise assume proof-of-work
- switch config.PowMode {
- case ethash.ModeFake:
- log.Warn("Ethash used in fake mode")
- return ethash.NewFaker()
- case ethash.ModeTest:
- log.Warn("Ethash used in test mode")
- return ethash.NewTester(nil, noverify)
- case ethash.ModeShared:
- log.Warn("Ethash used in shared mode")
- return ethash.NewShared()
- default:
- engine := ethash.New(ethash.Config{
- CacheDir: ctx.ResolvePath(config.CacheDir),
- CachesInMem: config.CachesInMem,
- CachesOnDisk: config.CachesOnDisk,
- DatasetDir: config.DatasetDir,
- DatasetsInMem: config.DatasetsInMem,
- DatasetsOnDisk: config.DatasetsOnDisk,
- }, notify, noverify)
- engine.SetThreads(-1) // Disable CPU mining
- return engine
- }
+ return new(dummy.DummyEngine)
}
// APIs return the collection of RPC services the ethereum package offers.
@@ -434,17 +409,6 @@ func (s *Ethereum) SetEtherbase(etherbase common.Address) {
// 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
@@ -459,14 +423,6 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
}
- if clique, ok := s.engine.(*clique.Clique); ok {
- 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)
- }
- clique.Authorize(eb, wallet.SignData)
- }
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
diff --git a/examples/payments/main.go b/examples/payments/main.go
index d5d10b4..76306b0 100644
--- a/examples/payments/main.go
+++ b/examples/payments/main.go
@@ -1,7 +1,7 @@
package main
import (
- //"time"
+ "time"
"os"
"os/signal"
"syscall"
@@ -16,6 +16,7 @@ import (
"github.com/Determinant/coreth"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/common"
)
func checkError(err error) {
@@ -25,14 +26,29 @@ func checkError(err error) {
func main() {
log.Root().SetHandler(log.StderrHandler)
config := eth.DefaultConfig
- chainConfig := params.MainnetChainConfig
+ chainConfig := &params.ChainConfig {
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: big.NewInt(0),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: nil,
+ Ethash: nil,
+ }
genBalance := big.NewInt(1000000000000000000)
genKey, _ := coreth.NewKey(rand.Reader)
config.Genesis = &core.Genesis{
- Config: params.MainnetChainConfig,
+ Config: chainConfig,
Nonce: 0,
+ Number: 0,
ExtraData: hexutil.MustDecode("0x00"),
GasLimit: 100000000,
Difficulty: big.NewInt(0),
@@ -45,12 +61,17 @@ func main() {
gasLimit := 21000
gasPrice := big.NewInt(1000)
bob, err := coreth.NewKey(rand.Reader); checkError(err)
- tx := types.NewTransaction(nonce, bob.Address, value, uint64(gasLimit), gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), genKey.PrivateKey); checkError(err)
- chain := coreth.NewETHChain(&config, chainConfig, nil)
+ chain := coreth.NewETHChain(&config, nil)
chain.Start()
- chain.AddLocalTxs([]*types.Transaction{signedTx})
+
+ 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(5000 * time.Millisecond)
+ nonce++
+ }
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
diff --git a/miner/miner.go b/miner/miner.go
index b55d4fc..56440cd 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -18,6 +18,8 @@
package miner
import (
+ "fmt"
+ "time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -25,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
eminer "github.com/ethereum/go-ethereum/miner"
)
@@ -37,20 +40,50 @@ type Backend interface {
// Config is the configuration parameters of mining.
type Config = eminer.Config
-type Worker = worker
+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) *Miner {
+ return &Miner {
+ w: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock),
+ }
+}
+
+func (self *Miner) SetEtherbase(addr common.Address) {
+ self.w.setEtherbase(addr)
+}
+
+func (self *Miner) Start(coinbase common.Address) {
+ self.w.start()
+}
+
+func (self *Miner) Stop() {
+ self.w.stop()
+}
-func NewWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool) *Worker {
- return newWorker(config, chainConfig, engine, eth, mux, isLocalBlock)
+func (self *Miner) SetExtra(extra []byte) error {
+ if uint64(len(extra)) > params.MaximumExtraDataSize {
+ return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize)
+ }
+ self.w.setExtra(extra)
+ return nil
}
-func (self *Worker) SetEtherbase(addr common.Address) {
- self.setEtherbase(addr)
+func (self *Miner) Mining() bool {
+ return false
}
-func (self *Worker) Start() {
- self.start()
+func (self *Miner) HashRate() uint64 {
+ return 0
+}
+
+func (self *Miner) SetRecommitInterval(interval time.Duration) {}
+
+func (self *Miner) PendingBlock() *types.Block {
+ return self.w.pendingBlock()
}
-func (self *Worker) Stop() {
- self.stop()
+func (self *Miner) Pending() (*types.Block, *state.StateDB) {
+ return self.w.pending()
}