aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-02-23 22:43:41 +0800
committerobscuren <geffobscura@gmail.com>2015-02-23 22:43:41 +0800
commitb2a225a52e45315f3ec90e11707fefa6059d13f5 (patch)
tree7019227fc4af5e39f88bcc58ddc455826df8d569
parent20aa6dde067a0c8d28fdafd43e41f996f014e8b0 (diff)
downloaddexon-b2a225a52e45315f3ec90e11707fefa6059d13f5.tar.gz
dexon-b2a225a52e45315f3ec90e11707fefa6059d13f5.tar.zst
dexon-b2a225a52e45315f3ec90e11707fefa6059d13f5.zip
Properly uninstall filters. Mining issue fixed #closes #365
* Added an additional tx state which is used to get the current nonce * Refresh transient state each time a new canonical block is found * Properly uninstall filters. Fixes a possible crash in RPC
-rw-r--r--cmd/mist/assets/examples/coin.html24
-rw-r--r--core/chain_manager.go30
-rw-r--r--rpc/packages.go11
-rw-r--r--rpc/util.go2
-rw-r--r--whisper/whisper.go4
-rw-r--r--xeth/xeth.go10
6 files changed, 59 insertions, 22 deletions
diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html
index 18a6811d7..509a9aeeb 100644
--- a/cmd/mist/assets/examples/coin.html
+++ b/cmd/mist/assets/examples/coin.html
@@ -19,6 +19,7 @@
<span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
+ <span id="message"></span>
</div>
<hr>
@@ -95,17 +96,28 @@
}
function transact() {
- var to = document.querySelector("#address").value;
- if( to.length == 0 ) {
+ var to = document.querySelector("#address");
+ if( to.value.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else {
- to = "0x"+to;
+ if (to.value.substr(0,2) != "0x")
+ to.value = "0x"+to.value;
}
- var value = parseInt( document.querySelector("#amount").value );
- console.log("transact: ", to, " => ", value)
+ var value = document.querySelector("#amount");
+ var amount = parseInt( value.value );
+ console.log("transact: ", to.value, " => ", amount)
- contract.send( to, value );
+ contract.send( to.value, amount );
+
+ to.value = "";
+ value.value = "";
+
+ var message = document.querySelector("#message")
+ message.innerHTML = "Submitted";
+ setTimeout(function() {
+ message.innerHTML = "";
+ }, 1000);
}
refresh();
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 9ef091c3c..4c7db6e2e 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -85,12 +85,14 @@ type ChainManager struct {
lastBlockHash []byte
transState *state.StateDB
+ txState *state.StateDB
}
func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager {
bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux}
bc.setLastBlock()
bc.transState = bc.State().Copy()
+ bc.txState = bc.State().Copy()
return bc
}
@@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB {
return self.transState
}
+func (self *ChainManager) TxState() *state.StateDB {
+ self.tsmu.RLock()
+ defer self.tsmu.RUnlock()
+
+ return self.txState
+}
+
+func (self *ChainManager) setTxState(state *state.StateDB) {
+ self.tsmu.Lock()
+ defer self.tsmu.Unlock()
+ self.txState = state
+}
+
func (self *ChainManager) setTransState(statedb *state.StateDB) {
self.transState = statedb
}
@@ -363,6 +378,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
defer self.tsmu.Unlock()
for _, block := range chain {
+ // Call in to the block processor and check for errors. It's likely that if one block fails
+ // all others will fail too (unless a known block is returned).
td, err := self.processor.Process(block)
if err != nil {
if IsKnownBlockErr(err) {
@@ -377,11 +394,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
block.Td = td
- var chain, split bool
+ var canonical, split bool
self.mu.Lock()
{
+ // Write block to database. Eventually we'll have to improve on this and throw away blocks that are
+ // not in the canonical chain.
self.write(block)
cblock := self.currentBlock
+ // Compare the TD of the last known block in the canonical chain to make sure it's greater.
+ // At this point it's possible that a different chain (fork) becomes the new canonical chain.
if td.Cmp(self.td) > 0 {
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
@@ -391,17 +412,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self.setTotalDifficulty(td)
self.insert(block)
- chain = true
+ canonical = true
}
}
self.mu.Unlock()
- if chain {
+ if canonical {
+ self.setTransState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainEvent{block, td})
}
if split {
- self.setTransState(state.New(block.Root(), self.db))
+ self.setTxState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainSplitEvent{block})
}
}
diff --git a/rpc/packages.go b/rpc/packages.go
index b51bde7ce..571f3a300 100644
--- a/rpc/packages.go
+++ b/rpc/packages.go
@@ -126,10 +126,6 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error
self.logMut.Lock()
defer self.logMut.Unlock()
- if self.logs[id] == nil {
- self.logs[id] = &logFilter{timeout: time.Now()}
- }
-
self.logs[id].add(&state.StateLog{})
}
if args == "pending" {
@@ -139,6 +135,7 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error
}
id = self.filterManager.InstallFilter(filter)
+ self.logs[id] = &logFilter{timeout: time.Now()}
*reply = id
return nil
@@ -377,12 +374,10 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
args.Fn = func(msg xeth.WhisperMessage) {
p.messagesMut.Lock()
defer p.messagesMut.Unlock()
- if p.messages[id] == nil {
- p.messages[id] = &whisperFilter{timeout: time.Now()}
- }
p.messages[id].add(msg) // = append(p.messages[id], msg)
}
id = p.xeth.Whisper().Watch(args)
+ p.messages[id] = &whisperFilter{timeout: time.Now()}
*reply = id
return nil
}
@@ -623,12 +618,14 @@ done:
self.messagesMut.Lock()
for id, filter := range self.logs {
if time.Since(filter.timeout) > 20*time.Second {
+ self.filterManager.UninstallFilter(id)
delete(self.logs, id)
}
}
for id, filter := range self.messages {
if time.Since(filter.timeout) > 20*time.Second {
+ self.xeth.Whisper().Unwatch(id)
delete(self.messages, id)
}
}
diff --git a/rpc/util.go b/rpc/util.go
index 1939b3474..00a418783 100644
--- a/rpc/util.go
+++ b/rpc/util.go
@@ -108,6 +108,7 @@ func toLogs(logs state.Logs) (ls []Log) {
type whisperFilter struct {
messages []xeth.WhisperMessage
timeout time.Time
+ id int
}
func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) {
@@ -123,6 +124,7 @@ func (w *whisperFilter) get() []xeth.WhisperMessage {
type logFilter struct {
logs state.Logs
timeout time.Time
+ id int
}
func (l *logFilter) add(logs ...state.Log) {
diff --git a/whisper/whisper.go b/whisper/whisper.go
index 50c2f98fd..13209f9a6 100644
--- a/whisper/whisper.go
+++ b/whisper/whisper.go
@@ -127,6 +127,10 @@ func (self *Whisper) Watch(opts Filter) int {
})
}
+func (self *Whisper) Unwatch(id int) {
+ self.filters.Uninstall(id)
+}
+
func (self *Whisper) Messages(id int) (messages []*Message) {
filter := self.filters.Get(id)
if filter != nil {
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 5907a8329..2985ce982 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -277,7 +277,7 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
}
var err error
- state := self.eth.ChainManager().TransState()
+ state := self.eth.ChainManager().TxState()
if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
}
@@ -289,10 +289,10 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
//fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce())
// Do some pre processing for our "pre" events and hooks
- block := self.chainManager.NewBlock(key.Address())
- coinbase := state.GetOrNewStateObject(key.Address())
- coinbase.SetGasPool(block.GasLimit())
- self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
+ //block := self.chainManager.NewBlock(key.Address())
+ //coinbase := state.GetOrNewStateObject(key.Address())
+ //coinbase.SetGasPool(block.GasLimit())
+ //self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
err = self.eth.TxPool().Add(tx)
if err != nil {