aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--blockpool/blockpool.go3
-rw-r--r--blockpool/peers.go46
-rw-r--r--blockpool/section.go4
-rw-r--r--blockpool/status.go6
-rw-r--r--cmd/ethereum/main.go2
-rw-r--r--cmd/evm/main.go58
-rw-r--r--eth/backend.go5
-rw-r--r--miner/miner.go8
-rw-r--r--rpc/api.go23
-rw-r--r--rpc/miner_agest.go70
-rw-r--r--xeth/xeth.go2
11 files changed, 162 insertions, 65 deletions
diff --git a/blockpool/blockpool.go b/blockpool/blockpool.go
index 09b9e7b0b..1ca97e0ca 100644
--- a/blockpool/blockpool.go
+++ b/blockpool/blockpool.go
@@ -757,6 +757,9 @@ func (self *BlockPool) checkTD(nodes ...*node) {
plog.DebugDetailf("peer td %v =?= block td %v", n.td, n.block.Td)
if n.td.Cmp(n.block.Td) != 0 {
self.peers.peerError(n.blockBy, ErrIncorrectTD, "on block %x", n.hash)
+ self.status.lock.Lock()
+ self.status.badPeers[n.blockBy]++
+ self.status.lock.Unlock()
}
}
}
diff --git a/blockpool/peers.go b/blockpool/peers.go
index 80168b206..6bff38e87 100644
--- a/blockpool/peers.go
+++ b/blockpool/peers.go
@@ -46,7 +46,8 @@ type peer struct {
// timers for head section process
blockHashesRequestTimer <-chan time.Time
blocksRequestTimer <-chan time.Time
- suicideC <-chan time.Time
+ headInfoTimer <-chan time.Time
+ bestIdleTimer <-chan time.Time
addToBlacklist func(id string)
@@ -256,8 +257,10 @@ func (self *peers) addPeer(
plog.Debugf("addPeer: <%s> already the best peer. Request new head section info from %s", id, hex(currentBlockHash))
if (previousBlockHash != common.Hash{}) {
+ plog.DebugDetailf("addPeer: <%s> head changed: %s -> %s ", id, hex(previousBlockHash), hex(currentBlockHash))
+ p.headSectionC <- nil
if entry := self.bp.get(previousBlockHash); entry != nil {
- p.headSectionC <- nil
+ plog.DebugDetailf("addPeer: <%s> previous head : %v found in pool, activate", id, hex(previousBlockHash))
self.bp.activateChain(entry.section, p, nil)
p.sections = append(p.sections, previousBlockHash)
}
@@ -410,7 +413,8 @@ func (self *peer) handleSection(sec *section) {
self.bp.syncing()
}
- self.suicideC = time.After(self.bp.Config.BlockHashesTimeout)
+ self.headInfoTimer = time.After(self.bp.Config.BlockHashesTimeout)
+ self.bestIdleTimer = nil
plog.DebugDetailf("HeadSection: <%s> head block hash changed (mined block received). New head %s", self.id, hex(self.currentBlockHash))
} else {
@@ -418,8 +422,10 @@ func (self *peer) handleSection(sec *section) {
self.idle = true
self.bp.wg.Done()
}
- plog.DebugDetailf("HeadSection: <%s> (head: %s) head section [%s] created", self.id, hex(self.currentBlockHash), sectionhex(sec))
- self.suicideC = time.After(self.bp.Config.IdleBestPeerTimeout)
+
+ self.headInfoTimer = nil
+ self.bestIdleTimer = time.After(self.bp.Config.IdleBestPeerTimeout)
+ plog.DebugDetailf("HeadSection: <%s> (head: %s) head section [%s] created. Idle...", self.id, hex(self.currentBlockHash), sectionhex(sec))
}
}
@@ -452,14 +458,13 @@ func (self *peer) getCurrentBlock(currentBlock *types.Block) {
self.blocksRequestTimer = nil
}
-func (self *peer) getBlockHashes() {
+func (self *peer) getBlockHashes() bool {
//if connecting parent is found
if self.bp.hasBlock(self.parentHash) {
plog.DebugDetailf("HeadSection: <%s> parent block %s found in blockchain", self.id, hex(self.parentHash))
err := self.bp.insertChain(types.Blocks([]*types.Block{self.currentBlock}))
self.bp.status.lock.Lock()
- self.bp.status.badPeers[self.id]++
self.bp.status.values.BlocksInChain++
self.bp.status.values.BlocksInPool--
if err != nil {
@@ -469,18 +474,18 @@ func (self *peer) getBlockHashes() {
if self.currentBlock.Td != nil {
if self.td.Cmp(self.currentBlock.Td) != 0 {
self.addError(ErrIncorrectTD, "on block %x", self.currentBlockHash)
+ self.bp.status.badPeers[self.id]++
}
}
- headKey := self.parentHash.Str()
+ headKey := self.parentHash
height := self.bp.status.chain[headKey] + 1
- self.bp.status.chain[self.currentBlockHash.Str()] = height
+ self.bp.status.chain[self.currentBlockHash] = height
if height > self.bp.status.values.LongestChain {
self.bp.status.values.LongestChain = height
}
delete(self.bp.status.chain, headKey)
}
self.bp.status.lock.Unlock()
-
} else {
if parent := self.bp.get(self.parentHash); parent != nil {
if self.bp.get(self.currentBlockHash) == nil {
@@ -501,15 +506,17 @@ func (self *peer) getBlockHashes() {
plog.DebugDetailf("HeadSection: <%s> section [%s] requestBlockHashes", self.id, sectionhex(self.headSection))
self.requestBlockHashes(self.currentBlockHash)
self.blockHashesRequestTimer = time.After(self.bp.Config.BlockHashesRequestInterval)
- return
+ return false
}
}
self.blockHashesRequestTimer = nil
if !self.idle {
self.idle = true
- self.suicideC = nil
+ self.headInfoTimer = nil
+ self.bestIdleTimer = time.After(self.bp.Config.IdleBestPeerTimeout)
self.bp.wg.Done()
}
+ return true
}
// main loop for head section process
@@ -522,9 +529,7 @@ func (self *peer) run() {
self.blockHashesRequestTimer = nil
self.blocksRequestTimer = time.After(0)
- self.suicideC = time.After(self.bp.Config.BlockHashesTimeout)
-
- var quit <-chan time.Time
+ self.headInfoTimer = time.After(self.bp.Config.BlockHashesTimeout)
var ping = time.NewTicker(5 * time.Second)
@@ -539,13 +544,6 @@ LOOP:
// if sec == nil, it signals that chain info has updated (new block message)
case sec := <-self.headSectionC:
self.handleSection(sec)
- if sec == nil {
- plog.Debugf("HeadSection: <%s> (headsection [%s], received: [%s]) quit channel set to nil, catchup happening", self.id, sectionhex(self.headSection), sectionhex(sec))
- quit = nil
- } else {
- plog.Debugf("HeadSection: <%s> (headsection [%s], received: [%s]) quit channel set to go off in IdleBestPeerTimeout", self.id, sectionhex(self.headSection), sectionhex(sec))
- quit = time.After(self.bp.Config.IdleBestPeerTimeout)
- }
// periodic check for block hashes or parent block/section
case <-self.blockHashesRequestTimer:
@@ -560,7 +558,7 @@ LOOP:
self.getCurrentBlock(nil)
// quitting on timeout
- case <-self.suicideC:
+ case <-self.headInfoTimer:
self.peerError(self.bp.peers.errors.New(ErrInsufficientChainInfo, "timed out without providing block hashes or head block (td: %v, head: %s)", self.td, hex(self.currentBlockHash)))
self.bp.status.lock.Lock()
@@ -583,7 +581,7 @@ LOOP:
break LOOP
// quit
- case <-quit:
+ case <-self.bestIdleTimer:
self.peerError(self.bp.peers.errors.New(ErrIdleTooLong, "timed out without providing new blocks (td: %v, head: %s)...quitting", self.td, hex(self.currentBlockHash)))
self.bp.status.lock.Lock()
diff --git a/blockpool/section.go b/blockpool/section.go
index bcbd71cfc..14e91cf33 100644
--- a/blockpool/section.go
+++ b/blockpool/section.go
@@ -176,9 +176,9 @@ func (self *section) addSectionToBlockChain(p *peer) {
self.bp.status.lock.Lock()
if err == nil {
- headKey := blocks[0].ParentHash().Str()
+ headKey := blocks[0].ParentHash()
height := self.bp.status.chain[headKey] + len(blocks)
- self.bp.status.chain[blocks[len(blocks)-1].Hash().Str()] = height
+ self.bp.status.chain[blocks[len(blocks)-1].Hash()] = height
if height > self.bp.status.values.LongestChain {
self.bp.status.values.LongestChain = height
}
diff --git a/blockpool/status.go b/blockpool/status.go
index 4529c77fe..02e358510 100644
--- a/blockpool/status.go
+++ b/blockpool/status.go
@@ -3,6 +3,8 @@ package blockpool
import (
"fmt"
"sync"
+
+ "github.com/ethereum/go-ethereum/common"
)
type statusValues struct {
@@ -26,7 +28,7 @@ type statusValues struct {
type status struct {
lock sync.Mutex
values statusValues
- chain map[string]int
+ chain map[common.Hash]int
peers map[string]int
bestPeers map[string]int
badPeers map[string]int
@@ -35,7 +37,7 @@ type status struct {
func newStatus() *status {
return &status{
- chain: make(map[string]int),
+ chain: make(map[common.Hash]int),
peers: make(map[string]int),
bestPeers: make(map[string]int),
badPeers: make(map[string]int),
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 17dcbb59e..e351453b1 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -42,7 +42,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
- Version = "0.9.1"
+ Version = "0.9.2"
)
var (
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index af15dd4d4..17137e4bb 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -30,10 +30,10 @@ import (
"runtime"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
@@ -60,12 +60,12 @@ func main() {
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))
db, _ := ethdb.NewMemDatabase()
- statedb := state.New(nil, db)
- sender := statedb.NewStateObject([]byte("sender"))
- receiver := statedb.NewStateObject([]byte("receiver"))
+ statedb := state.New(common.Hash{}, db)
+ sender := statedb.NewStateObject(common.StringToAddress("sender"))
+ receiver := statedb.NewStateObject(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(*code))
- vmenv := NewEnv(statedb, []byte("evmuser"), common.Big(*value))
+ vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value))
tstart := time.Now()
@@ -98,7 +98,7 @@ type VMEnv struct {
state *state.StateDB
block *types.Block
- transactor []byte
+ transactor *common.Address
value *big.Int
depth int
@@ -106,33 +106,32 @@ type VMEnv struct {
time int64
}
-func NewEnv(state *state.StateDB, transactor []byte, value *big.Int) *VMEnv {
+func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VMEnv {
return &VMEnv{
state: state,
- transactor: transactor,
+ transactor: &transactor,
value: value,
time: time.Now().Unix(),
}
}
-func (self *VMEnv) State() *state.StateDB { return self.state }
-func (self *VMEnv) Origin() []byte { return self.transactor }
-func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
-func (self *VMEnv) PrevHash() []byte { return make([]byte, 32) }
-func (self *VMEnv) Coinbase() []byte { return self.transactor }
-func (self *VMEnv) Time() int64 { return self.time }
-func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
-func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
-func (self *VMEnv) Value() *big.Int { return self.value }
-func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
-func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
-func (self *VMEnv) Depth() int { return 0 }
-func (self *VMEnv) SetDepth(i int) { self.depth = i }
-func (self *VMEnv) GetHash(n uint64) []byte {
+func (self *VMEnv) State() *state.StateDB { return self.state }
+func (self *VMEnv) Origin() common.Address { return *self.transactor }
+func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
+func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
+func (self *VMEnv) Time() int64 { return self.time }
+func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
+func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
+func (self *VMEnv) Value() *big.Int { return self.value }
+func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
+func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
+func (self *VMEnv) Depth() int { return 0 }
+func (self *VMEnv) SetDepth(i int) { self.depth = i }
+func (self *VMEnv) GetHash(n uint64) common.Hash {
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
return self.block.Hash()
}
- return nil
+ return common.Hash{}
}
func (self *VMEnv) AddLog(log state.Log) {
self.state.AddLog(log)
@@ -141,23 +140,24 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
-func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution {
+func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution {
return core.NewExecution(self, addr, data, gas, price, value)
}
-func (self *VMEnv) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
- exe := self.vm(addr, data, gas, price, value)
+func (self *VMEnv) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
+ exe := self.vm(&addr, data, gas, price, value)
ret, err := exe.Call(addr, caller)
self.Gas = exe.Gas
return ret, err
}
-func (self *VMEnv) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
- exe := self.vm(caller.Address(), data, gas, price, value)
+func (self *VMEnv) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
+ a := caller.Address()
+ exe := self.vm(&a, data, gas, price, value)
return exe.Call(addr, caller)
}
-func (self *VMEnv) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
+func (self *VMEnv) Create(caller vm.ContextRef, addr *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
exe := self.vm(addr, data, gas, price, value)
return exe.Create(caller)
}
diff --git a/eth/backend.go b/eth/backend.go
index c253a064e..06c3cbd17 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -303,8 +303,9 @@ func (s *Ethereum) StartMining() error {
return nil
}
-func (s *Ethereum) StopMining() { s.miner.Stop() }
-func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
+func (s *Ethereum) StopMining() { s.miner.Stop() }
+func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
+func (s *Ethereum) Miner() *miner.Miner { return s.miner }
// func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
func (s *Ethereum) Name() string { return s.net.Name }
diff --git a/miner/miner.go b/miner/miner.go
index ccc19c754..d46fabc1e 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -26,7 +26,7 @@ type Miner struct {
func New(eth core.Backend, pow pow.PoW, minerThreads int) *Miner {
// note: minerThreads is currently ignored because
// ethash is not thread safe.
- return &Miner{eth: eth, pow: pow}
+ return &Miner{eth: eth, pow: pow, worker: newWorker(common.Address{}, eth)}
}
func (self *Miner) Mining() bool {
@@ -35,7 +35,7 @@ func (self *Miner) Mining() bool {
func (self *Miner) Start(coinbase common.Address) {
self.mining = true
- self.worker = newWorker(coinbase, self.eth)
+ self.worker.coinbase = coinbase
self.worker.register(NewCpuMiner(0, self.pow))
self.pow.(*ethash.Ethash).UpdateDAG()
@@ -44,6 +44,10 @@ func (self *Miner) Start(coinbase common.Address) {
self.worker.commitNewWork()
}
+func (self *Miner) Register(agent Agent) {
+ self.worker.register(agent)
+}
+
func (self *Miner) Stop() {
self.mining = false
self.worker.stop()
diff --git a/rpc/api.go b/rpc/api.go
index 34d4ff0fc..d5e18eec8 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -17,15 +17,20 @@ type EthereumApi struct {
eth *xeth.XEth
xethMu sync.RWMutex
db common.Database
+
+ // Miner agent
+ agent *Agent
}
func NewEthereumApi(eth *xeth.XEth, dataDir string) *EthereumApi {
// What about when dataDir is empty?
db, _ := ethdb.NewLDBDatabase(path.Join(dataDir, "dapps"))
api := &EthereumApi{
- eth: eth,
- db: db,
+ eth: eth,
+ db: db,
+ agent: NewAgent(),
}
+ eth.Backend().Miner().Register(api.agent)
return api
}
@@ -342,7 +347,13 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
}
opts := toFilterOptions(args)
*reply = NewLogsRes(p.xeth().AllLogs(opts))
- case "eth_getWork", "eth_submitWork":
+ case "eth_getWork":
+ *reply = p.getWork()
+ case "eth_submitWork":
+ // TODO what is the reply here?
+ // TODO what are the arguments?
+ p.agent.SetResult(0, common.Hash{}, common.Hash{})
+
return NewNotImplementedError(req.Method)
case "db_putString":
args := new(DbArgs)
@@ -427,6 +438,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
*reply = p.xeth().Whisper().Messages(args.Id)
+
// case "eth_register":
// // Placeholder for actual type
// args := new(HashIndexArgs)
@@ -454,6 +466,11 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return nil
}
+func (p *EthereumApi) getWork() string {
+ p.xeth().SetMining(true)
+ return p.agent.GetWork().Hex()
+}
+
func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
var opts core.FilterOptions
diff --git a/rpc/miner_agest.go b/rpc/miner_agest.go
new file mode 100644
index 000000000..64dba82a6
--- /dev/null
+++ b/rpc/miner_agest.go
@@ -0,0 +1,70 @@
+package rpc
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/miner"
+)
+
+type Agent struct {
+ work *types.Block
+ currentWork *types.Block
+
+ quit chan struct{}
+ workCh chan *types.Block
+ returnCh chan<- miner.Work
+}
+
+func NewAgent() *Agent {
+ agent := &Agent{}
+ go agent.run()
+
+ return agent
+}
+
+func (a *Agent) Work() chan<- *types.Block {
+ return a.workCh
+}
+
+func (a *Agent) SetWorkCh(returnCh chan<- miner.Work) {
+ a.returnCh = returnCh
+}
+
+func (a *Agent) Start() {
+ a.quit = make(chan struct{})
+ a.workCh = make(chan *types.Block, 1)
+}
+
+func (a *Agent) Stop() {
+ close(a.quit)
+ close(a.workCh)
+}
+
+func (a *Agent) GetHashRate() int64 { return 0 }
+
+func (a *Agent) run() {
+out:
+ for {
+ select {
+ case <-a.quit:
+ break out
+ case work := <-a.workCh:
+ a.work = work
+ }
+ }
+}
+
+func (a *Agent) GetWork() common.Hash {
+ // XXX Wait here untill work != nil ?.
+ if a.work != nil {
+ return a.work.HashNoNonce()
+ }
+ return common.Hash{}
+}
+
+func (a *Agent) SetResult(nonce uint64, mixDigest, seedHash common.Hash) {
+ // Make sure the external miner was working on the right hash
+ if a.currentWork != nil && a.work != nil && a.currentWork.Hash() == a.work.Hash() {
+ a.returnCh <- miner.Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()}
+ }
+}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 9f183aa61..d3c3131d4 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper"
@@ -43,6 +44,7 @@ type Backend interface {
ExtraDb() common.Database
EventMux() *event.TypeMux
Whisper() *whisper.Whisper
+ Miner() *miner.Miner
IsMining() bool
StartMining() error