aboutsummaryrefslogtreecommitdiffstats
path: root/xeth
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2015-11-03 18:47:07 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-11-03 18:47:07 +0800
commite5532154a50114d5ffb1ffd850b746cab00cb899 (patch)
tree0042cc997ccf4166b9b52464339d52d37d7a8ad6 /xeth
parent9666db2a442887ccf8ec2d81f5e2fedc1a3a3d3e (diff)
parentf75becc264f8bde0f58391fc226243d03e78aa7b (diff)
downloadgo-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.gz
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.bz2
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.lz
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.xz
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.zst
go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.zip
Merge branch 'release/1.3.0'
Conflicts: VERSION cmd/geth/main.go
Diffstat (limited to 'xeth')
-rw-r--r--xeth/frontend.go4
-rw-r--r--xeth/xeth.go176
2 files changed, 97 insertions, 83 deletions
diff --git a/xeth/frontend.go b/xeth/frontend.go
index e89282242..70d99ebc4 100644
--- a/xeth/frontend.go
+++ b/xeth/frontend.go
@@ -19,6 +19,9 @@ package xeth
// Frontend should be implemented by users of XEth. Its methods are
// called whenever XEth makes a decision that requires user input.
type Frontend interface {
+ // AskPassword is called when a new account is created or updated
+ AskPassword() (string, bool)
+
// UnlockAccount is called when a transaction needs to be signed
// but the key corresponding to the transaction's sender is
// locked.
@@ -40,5 +43,6 @@ type Frontend interface {
// transactions but cannot not unlock any keys.
type dummyFrontend struct{}
+func (dummyFrontend) AskPassword() (string, bool) { return "", false }
func (dummyFrontend) UnlockAccount([]byte) bool { return false }
func (dummyFrontend) ConfirmTransaction(string) bool { return true }
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 623b3a963..35e6dd52d 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -33,9 +33,10 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/event/filter"
+ "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/miner"
@@ -58,24 +59,8 @@ const (
LogFilterTy
)
-func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
-
-func (self *XEth) DefaultGasPrice() *big.Int {
- if self.gpo == nil {
- self.gpo = eth.NewGasPriceOracle(self.backend)
- }
- return self.gpo.SuggestPrice()
-}
-
type XEth struct {
- backend *eth.Ethereum
- frontend Frontend
-
- state *State
- whisper *Whisper
-
- quit chan struct{}
- filterManager *filter.FilterManager
+ quit chan struct{}
logMu sync.RWMutex
logQueue map[int]*logQueue
@@ -91,16 +76,18 @@ type XEth struct {
transactMu sync.Mutex
- agent *miner.RemoteAgent
-
- gpo *eth.GasPriceOracle
+ // read-only fields
+ backend *eth.Ethereum
+ frontend Frontend
+ agent *miner.RemoteAgent
+ gpo *eth.GasPriceOracle
+ state *State
+ whisper *Whisper
+ filterManager *filters.FilterSystem
}
func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
- return &XEth{
- backend: eth,
- frontend: frontend,
- }
+ return &XEth{backend: eth, frontend: frontend}
}
// New creates an XEth that uses the given frontend.
@@ -111,12 +98,13 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
backend: ethereum,
frontend: frontend,
quit: make(chan struct{}),
- filterManager: filter.NewFilterManager(ethereum.EventMux()),
+ filterManager: filters.NewFilterSystem(ethereum.EventMux()),
logQueue: make(map[int]*logQueue),
blockQueue: make(map[int]*hashQueue),
transactionQueue: make(map[int]*hashQueue),
messages: make(map[int]*whisperFilter),
agent: miner.NewRemoteAgent(),
+ gpo: eth.NewGasPriceOracle(ethereum),
}
if ethereum.Whisper() != nil {
xeth.whisper = NewWhisper(ethereum.Whisper())
@@ -125,16 +113,15 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
if frontend == nil {
xeth.frontend = dummyFrontend{}
}
- xeth.state = NewState(xeth, xeth.backend.ChainManager().State())
-
+ state, _ := xeth.backend.BlockChain().State()
+ xeth.state = NewState(xeth, state)
go xeth.start()
- go xeth.filterManager.Start()
-
return xeth
}
func (self *XEth) start() {
timer := time.NewTicker(2 * time.Second)
+ defer timer.Stop()
done:
for {
select {
@@ -142,7 +129,7 @@ done:
self.logMu.Lock()
for id, filter := range self.logQueue {
if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.UninstallFilter(id)
+ self.filterManager.Remove(id)
delete(self.logQueue, id)
}
}
@@ -151,7 +138,7 @@ done:
self.blockMu.Lock()
for id, filter := range self.blockQueue {
if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.UninstallFilter(id)
+ self.filterManager.Remove(id)
delete(self.blockQueue, id)
}
}
@@ -160,7 +147,7 @@ done:
self.transactionMu.Lock()
for id, filter := range self.transactionQueue {
if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.UninstallFilter(id)
+ self.filterManager.Remove(id)
delete(self.transactionQueue, id)
}
}
@@ -180,8 +167,12 @@ done:
}
}
-func (self *XEth) stop() {
+// Stop releases any resources associated with self.
+// It may not be called more than once.
+func (self *XEth) Stop() {
close(self.quit)
+ self.filterManager.Stop()
+ self.backend.Miner().Unregister(self.agent)
}
func cAddress(a []string) []common.Address {
@@ -203,18 +194,31 @@ func cTopics(t [][]string) [][]common.Hash {
return topics
}
+func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
+
+func (self *XEth) DefaultGasPrice() *big.Int {
+ return self.gpo.SuggestPrice()
+}
+
func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent }
func (self *XEth) AtStateNum(num int64) *XEth {
var st *state.StateDB
+ var err error
switch num {
case -2:
st = self.backend.Miner().PendingState().Copy()
default:
if block := self.getBlockByHeight(num); block != nil {
- st = state.New(block.Root(), self.backend.ChainDb())
+ st, err = state.New(block.Root(), self.backend.ChainDb())
+ if err != nil {
+ return nil
+ }
} else {
- st = state.New(self.backend.ChainManager().GetBlockByNumber(0).Root(), self.backend.ChainDb())
+ st, err = state.New(self.backend.BlockChain().GetBlockByNumber(0).Root(), self.backend.ChainDb())
+ if err != nil {
+ return nil
+ }
}
}
@@ -244,30 +248,41 @@ func (self *XEth) State() *State { return self.state }
func (self *XEth) UpdateState() (wait chan *big.Int) {
wait = make(chan *big.Int)
go func() {
- sub := self.backend.EventMux().Subscribe(core.ChainHeadEvent{})
+ eventSub := self.backend.EventMux().Subscribe(core.ChainHeadEvent{})
+ defer eventSub.Unsubscribe()
+
var m, n *big.Int
var ok bool
- out:
+
+ eventCh := eventSub.Chan()
for {
select {
- case event := <-sub.Chan():
- ev, ok := event.(core.ChainHeadEvent)
- if ok {
- m = ev.Block.Number()
+ case event, ok := <-eventCh:
+ if !ok {
+ // Event subscription closed, set the channel to nil to stop spinning
+ eventCh = nil
+ continue
+ }
+ // A real event arrived, process if new head block assignment
+ if event, ok := event.Data.(core.ChainHeadEvent); ok {
+ m = event.Block.Number()
if n != nil && n.Cmp(m) < 0 {
wait <- n
n = nil
}
- statedb := state.New(ev.Block.Root(), self.backend.ChainDb())
+ statedb, err := state.New(event.Block.Root(), self.backend.ChainDb())
+ if err != nil {
+ glog.V(logger.Error).Infoln("Could not create new state: %v", err)
+ return
+ }
self.state = NewState(self, statedb)
}
case n, ok = <-wait:
if !ok {
- break out
+ return
}
}
}
- sub.Unsubscribe()
}()
return
}
@@ -290,19 +305,19 @@ func (self *XEth) getBlockByHeight(height int64) *types.Block {
num = uint64(height)
}
- return self.backend.ChainManager().GetBlockByNumber(num)
+ return self.backend.BlockChain().GetBlockByNumber(num)
}
func (self *XEth) BlockByHash(strHash string) *Block {
hash := common.HexToHash(strHash)
- block := self.backend.ChainManager().GetBlock(hash)
+ block := self.backend.BlockChain().GetBlock(hash)
return NewBlock(block)
}
func (self *XEth) EthBlockByHash(strHash string) *types.Block {
hash := common.HexToHash(strHash)
- block := self.backend.ChainManager().GetBlock(hash)
+ block := self.backend.BlockChain().GetBlock(hash)
return block
}
@@ -356,11 +371,11 @@ func (self *XEth) EthBlockByNumber(num int64) *types.Block {
}
func (self *XEth) Td(hash common.Hash) *big.Int {
- return self.backend.ChainManager().GetTd(hash)
+ return self.backend.BlockChain().GetTd(hash)
}
func (self *XEth) CurrentBlock() *types.Block {
- return self.backend.ChainManager().CurrentBlock()
+ return self.backend.BlockChain().CurrentBlock()
}
func (self *XEth) GetBlockReceipts(bhash common.Hash) types.Receipts {
@@ -372,7 +387,7 @@ func (self *XEth) GetTxReceipt(txhash common.Hash) *types.Receipt {
}
func (self *XEth) GasLimit() *big.Int {
- return self.backend.ChainManager().GasLimit()
+ return self.backend.BlockChain().GasLimit()
}
func (self *XEth) Block(v interface{}) *Block {
@@ -452,7 +467,7 @@ func (self *XEth) ClientVersion() string {
func (self *XEth) SetMining(shouldmine bool, threads int) bool {
ismining := self.backend.IsMining()
if shouldmine && !ismining {
- err := self.backend.StartMining(threads)
+ err := self.backend.StartMining(threads, "")
return err == nil
}
if ismining && !shouldmine {
@@ -504,7 +519,7 @@ func (self *XEth) IsContract(address string) bool {
}
func (self *XEth) UninstallFilter(id int) bool {
- defer self.filterManager.UninstallFilter(id)
+ defer self.filterManager.Remove(id)
if _, ok := self.logQueue[id]; ok {
self.logMu.Lock()
@@ -532,17 +547,15 @@ func (self *XEth) NewLogFilter(earliest, latest int64, skip, max int, address []
self.logMu.Lock()
defer self.logMu.Unlock()
- filter := core.NewFilter(self.backend)
- id := self.filterManager.InstallFilter(filter)
+ filter := filters.New(self.backend.ChainDb())
+ id := self.filterManager.Add(filter)
self.logQueue[id] = &logQueue{timeout: time.Now()}
- filter.SetEarliestBlock(earliest)
- filter.SetLatestBlock(latest)
- filter.SetSkip(skip)
- filter.SetMax(max)
- filter.SetAddress(cAddress(address))
+ filter.SetBeginBlock(earliest)
+ filter.SetEndBlock(latest)
+ filter.SetAddresses(cAddress(address))
filter.SetTopics(cTopics(topics))
- filter.LogsCallback = func(logs state.Logs) {
+ filter.LogsCallback = func(logs vm.Logs) {
self.logMu.Lock()
defer self.logMu.Unlock()
@@ -558,8 +571,8 @@ func (self *XEth) NewTransactionFilter() int {
self.transactionMu.Lock()
defer self.transactionMu.Unlock()
- filter := core.NewFilter(self.backend)
- id := self.filterManager.InstallFilter(filter)
+ filter := filters.New(self.backend.ChainDb())
+ id := self.filterManager.Add(filter)
self.transactionQueue[id] = &hashQueue{timeout: time.Now()}
filter.TransactionCallback = func(tx *types.Transaction) {
@@ -577,11 +590,11 @@ func (self *XEth) NewBlockFilter() int {
self.blockMu.Lock()
defer self.blockMu.Unlock()
- filter := core.NewFilter(self.backend)
- id := self.filterManager.InstallFilter(filter)
+ filter := filters.New(self.backend.ChainDb())
+ id := self.filterManager.Add(filter)
self.blockQueue[id] = &hashQueue{timeout: time.Now()}
- filter.BlockCallback = func(block *types.Block, logs state.Logs) {
+ filter.BlockCallback = func(block *types.Block, logs vm.Logs) {
self.blockMu.Lock()
defer self.blockMu.Unlock()
@@ -604,7 +617,7 @@ func (self *XEth) GetFilterType(id int) byte {
return UnknownFilterTy
}
-func (self *XEth) LogFilterChanged(id int) state.Logs {
+func (self *XEth) LogFilterChanged(id int) vm.Logs {
self.logMu.Lock()
defer self.logMu.Unlock()
@@ -634,8 +647,8 @@ func (self *XEth) TransactionFilterChanged(id int) []common.Hash {
return nil
}
-func (self *XEth) Logs(id int) state.Logs {
- filter := self.filterManager.GetFilter(id)
+func (self *XEth) Logs(id int) vm.Logs {
+ filter := self.filterManager.Get(id)
if filter != nil {
return filter.Find()
}
@@ -643,13 +656,11 @@ func (self *XEth) Logs(id int) state.Logs {
return nil
}
-func (self *XEth) AllLogs(earliest, latest int64, skip, max int, address []string, topics [][]string) state.Logs {
- filter := core.NewFilter(self.backend)
- filter.SetEarliestBlock(earliest)
- filter.SetLatestBlock(latest)
- filter.SetSkip(skip)
- filter.SetMax(max)
- filter.SetAddress(cAddress(address))
+func (self *XEth) AllLogs(earliest, latest int64, skip, max int, address []string, topics [][]string) vm.Logs {
+ filter := filters.New(self.backend.ChainDb())
+ filter.SetBeginBlock(earliest)
+ filter.SetEndBlock(latest)
+ filter.SetAddresses(cAddress(address))
filter.SetTopics(cTopics(topics))
return filter.Find()
@@ -832,7 +843,6 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
}
from.SetBalance(common.MaxBig)
- from.SetGasLimit(common.MaxBig)
msg := callmsg{
from: from,
@@ -855,9 +865,9 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
}
header := self.CurrentBlock().Header()
- vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header)
-
- res, gas, err := core.ApplyMessage(vmenv, msg, from)
+ vmenv := core.NewEnv(statedb, self.backend.BlockChain(), msg, header)
+ gp := new(core.GasPool).AddGas(common.MaxBig)
+ res, gas, err := core.ApplyMessage(vmenv, msg, gp)
return common.ToHex(res), gas.String(), err
}
@@ -1030,19 +1040,19 @@ func (m callmsg) Data() []byte { return m.data }
type logQueue struct {
mu sync.Mutex
- logs state.Logs
+ logs vm.Logs
timeout time.Time
id int
}
-func (l *logQueue) add(logs ...*state.Log) {
+func (l *logQueue) add(logs ...*vm.Log) {
l.mu.Lock()
defer l.mu.Unlock()
l.logs = append(l.logs, logs...)
}
-func (l *logQueue) get() state.Logs {
+func (l *logQueue) get() vm.Logs {
l.mu.Lock()
defer l.mu.Unlock()