diff options
-rw-r--r-- | Godeps/Godeps.json | 4 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go | 12 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c | 2 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h | 6 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h | 7 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c | 2 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h | 8 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp | 45 | ||||
-rw-r--r-- | core/filter.go | 6 | ||||
-rw-r--r-- | core/transaction_pool.go | 21 | ||||
-rw-r--r-- | event/filter/eth_filter.go | 4 | ||||
-rw-r--r-- | rpc/api.go | 23 | ||||
-rw-r--r-- | rpc/responses.go | 11 | ||||
-rw-r--r-- | xeth/xeth.go | 239 |
14 files changed, 286 insertions, 104 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 2480ff9a2..8b4b299f8 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -17,8 +17,8 @@ }, { "ImportPath": "github.com/ethereum/ethash", - "Comment": "v23.1-195-g4d50db9", - "Rev": "4d50db90d8bb5f2fae357570366cb8c657a4ddfc" + "Comment": "v23.1-204-g0401fdf", + "Rev": "0401fdf56a3bc8679f9560e542c3d1cf83020efe" }, { "ImportPath": "github.com/howeyc/fsnotify", diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go b/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go index 25863828f..8a441525d 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go @@ -1,6 +1,17 @@ package ethash /* + -mno-stack-arg-probe disables stack probing which avoids the function + __chkstk_ms being linked. this avoids a clash of this symbol as we also + separately link the secp256k1 lib which ends up defining this symbol + + 1. https://gcc.gnu.org/onlinedocs/gccint/Stack-Checking.html + 2. https://groups.google.com/forum/#!msg/golang-dev/v1bziURSQ4k/88fXuJ24e-gJ + 3. https://groups.google.com/forum/#!topic/golang-nuts/VNP6Mwz_B6o + +*/ + +/* #cgo CFLAGS: -std=gnu99 -Wall #cgo windows CFLAGS: -mno-stack-arg-probe #cgo LDFLAGS: -lm @@ -10,7 +21,6 @@ package ethash #include "src/libethash/io.c" #ifdef _WIN32 -# include "src/libethash/util_win32.c" # include "src/libethash/io_win32.c" # include "src/libethash/mmap_win32.c" #else diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c index 607e44138..e881e0c7b 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c @@ -280,7 +280,7 @@ ethash_h256_t ethash_get_seedhash(uint64_t block_number) return ret; } -int ethash_quick_check_difficulty( +bool ethash_quick_check_difficulty( ethash_h256_t const* header_hash, uint64_t const nonce, ethash_h256_t const* mix_hash, diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h index 221ff290a..4e2b695ac 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h @@ -47,7 +47,7 @@ static inline void ethash_h256_reset(ethash_h256_t* hash) } // Returns if hash is less than or equal to difficulty -static inline int ethash_check_difficulty( +static inline bool ethash_check_difficulty( ethash_h256_t const* hash, ethash_h256_t const* difficulty ) @@ -59,10 +59,10 @@ static inline int ethash_check_difficulty( } return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i); } - return 1; + return true; } -int ethash_quick_check_difficulty( +bool ethash_quick_check_difficulty( ethash_h256_t const* header_hash, uint64_t const nonce, ethash_h256_t const* mix_hash, diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h index 4fe46d756..05aa5ed37 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h @@ -34,11 +34,12 @@ extern "C" { #endif // Maximum size for mutable part of DAG file name +// 6 is for "full-R", the suffix of the filename // 10 is for maximum number of digits of a uint32_t (for REVISION) -// 1 is for _ and 16 is for the first 16 hex digits for first 8 bytes of +// 1 is for - and 16 is for the first 16 hex digits for first 8 bytes of // the seedhash and last 1 is for the null terminating character // Reference: https://github.com/ethereum/wiki/wiki/Ethash-DAG -#define DAG_MUTABLE_NAME_MAX_SIZE (10 + 1 + 16 + 1) +#define DAG_MUTABLE_NAME_MAX_SIZE (6 + 10 + 1 + 16 + 1) /// Possible return values of @see ethash_io_prepare enum ethash_io_rc { ETHASH_IO_FAIL = 0, ///< There has been an IO failure @@ -176,7 +177,7 @@ static inline bool ethash_io_mutable_name( #if LITTLE_ENDIAN == BYTE_ORDER hash = ethash_swap_u64(hash); #endif - return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "%u_%016" PRIx64, revision, hash) >= 0; + return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "full-R%u-%016" PRIx64, revision, hash) >= 0; } #ifdef __cplusplus diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c index d9c54d141..2e6c8deb8 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c @@ -25,7 +25,7 @@ #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> -#include <Shlobj.h> +#include <shlobj.h> FILE* ethash_fopen(char const* file_name, char const* mode) { diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h index 0d2307f3d..c5fc6e55b 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h @@ -26,11 +26,11 @@ extern "C" { #endif -//#ifdef _MSC_VER +#ifdef _MSC_VER void debugf(char const* str, ...); -//#else -//#define debugf printf -//#endif +#else +#define debugf printf +#endif static inline uint32_t min_u32(uint32_t a, uint32_t b) { diff --git a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp index 55fe02316..1933e03e3 100644 --- a/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp +++ b/Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp @@ -205,10 +205,10 @@ BOOST_AUTO_TEST_CASE(test_ethash_io_mutable_name) { // should have at least 8 bytes provided since this is what we test :) ethash_h256_t seed1 = ethash_h256_static_init(0, 10, 65, 255, 34, 55, 22, 8); ethash_io_mutable_name(1, &seed1, mutable_name); - BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "1_000a41ff22371608")); + BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "full-R1-000a41ff22371608")); ethash_h256_t seed2 = ethash_h256_static_init(0, 0, 0, 0, 0, 0, 0, 0); ethash_io_mutable_name(44, &seed2, mutable_name); - BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "44_0000000000000000")); + BOOST_REQUIRE_EQUAL(0, strcmp(mutable_name, "full-R44-0000000000000000")); } BOOST_AUTO_TEST_CASE(test_ethash_dir_creation) { @@ -599,16 +599,49 @@ BOOST_AUTO_TEST_CASE(test_incomplete_dag_file) { fs::remove_all("./test_ethash_directory/"); } -BOOST_AUTO_TEST_CASE(test_block_verification) { +BOOST_AUTO_TEST_CASE(test_block22_verification) { + // from POC-9 testnet, epoch 0 ethash_light_t light = ethash_light_new(22); ethash_h256_t seedhash = stringToBlockhash("372eca2454ead349c3df0ab5d00b0b706b23e49d469387db91811cee0358fc6d"); BOOST_ASSERT(light); ethash_return_value_t ret = ethash_light_compute( light, seedhash, - 0x495732e0ed7a801c + 0x495732e0ed7a801cU ); BOOST_REQUIRE_EQUAL(blockhashToHexString(&ret.result), "00000b184f1fdd88bfd94c86c39e65db0c36144d5e43f745f722196e730cb614"); + ethash_h256_t difficulty = ethash_h256_static_init(0x2, 0x5, 0x40); + BOOST_REQUIRE(ethash_check_difficulty(&ret.result, &difficulty)); + ethash_light_delete(light); +} + +BOOST_AUTO_TEST_CASE(test_block30001_verification) { + // from POC-9 testnet, epoch 1 + ethash_light_t light = ethash_light_new(30001); + ethash_h256_t seedhash = stringToBlockhash("7e44356ee3441623bc72a683fd3708fdf75e971bbe294f33e539eedad4b92b34"); + BOOST_ASSERT(light); + ethash_return_value_t ret = ethash_light_compute( + light, + seedhash, + 0x318df1c8adef7e5eU + ); + ethash_h256_t difficulty = ethash_h256_static_init(0x17, 0x62, 0xff); + BOOST_REQUIRE(ethash_check_difficulty(&ret.result, &difficulty)); + ethash_light_delete(light); +} + +BOOST_AUTO_TEST_CASE(test_block60000_verification) { + // from POC-9 testnet, epoch 2 + ethash_light_t light = ethash_light_new(60000); + ethash_h256_t seedhash = stringToBlockhash("5fc898f16035bf5ac9c6d9077ae1e3d5fc1ecc3c9fd5bee8bb00e810fdacbaa0"); + BOOST_ASSERT(light); + ethash_return_value_t ret = ethash_light_compute( + light, + seedhash, + 0x50377003e5d830caU + ); + ethash_h256_t difficulty = ethash_h256_static_init(0x25, 0xa6, 0x1e); + BOOST_REQUIRE(ethash_check_difficulty(&ret.result, &difficulty)); ethash_light_delete(light); } @@ -617,7 +650,7 @@ BOOST_AUTO_TEST_CASE(test_block_verification) { // Uncomment and run on your own machine if you want to confirm // it works fine. #if 0 -static int lef_cb(unsigned _progress) +static int progress_cb(unsigned _progress) { printf("CREATING DAG. PROGRESS: %u\n", _progress); fflush(stdout); @@ -627,7 +660,7 @@ static int lef_cb(unsigned _progress) BOOST_AUTO_TEST_CASE(full_dag_test) { ethash_light_t light = ethash_light_new(55); BOOST_ASSERT(light); - ethash_full_t full = ethash_full_new(light, lef_cb); + ethash_full_t full = ethash_full_new(light, progress_cb); BOOST_ASSERT(full); ethash_light_delete(light); ethash_full_delete(full); diff --git a/core/filter.go b/core/filter.go index c10fb7eeb..2ca57da65 100644 --- a/core/filter.go +++ b/core/filter.go @@ -22,9 +22,9 @@ type Filter struct { max int topics [][]common.Hash - BlockCallback func(*types.Block, state.Logs) - PendingCallback func(*types.Transaction) - LogsCallback func(state.Logs) + BlockCallback func(*types.Block, state.Logs) + TransactionCallback func(*types.Transaction) + LogsCallback func(state.Logs) } // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block diff --git a/core/transaction_pool.go b/core/transaction_pool.go index bac6b7f0b..6898a4bda 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -204,6 +204,27 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) { } } +// GetTransaction allows you to check the pending and queued transaction in the +// transaction pool. +// It has two stategies, first check the pool (map) then check the queue +func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { + // check the txs first + if tx, ok := tp.txs[hash]; ok { + return tx + } + + // check queue + for _, txs := range tp.queue { + for _, tx := range txs { + if tx.Hash() == hash { + return tx + } + } + } + + return nil +} + func (self *TxPool) GetTransactions() (txs types.Transactions) { self.mu.RLock() defer self.mu.RUnlock() diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go index a1abe3418..b0d5078a2 100644 --- a/event/filter/eth_filter.go +++ b/event/filter/eth_filter.go @@ -88,8 +88,8 @@ out: case core.TxPreEvent: self.filterMu.RLock() for _, filter := range self.filters { - if filter.PendingCallback != nil { - filter.PendingCallback(event.Tx) + if filter.TransactionCallback != nil { + filter.TransactionCallback(event.Tx) } } self.filterMu.RUnlock() diff --git a/rpc/api.go b/rpc/api.go index 452116fb4..6ba0d93e2 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -338,14 +338,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - id := api.xeth().RegisterFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics) + id := api.xeth().NewLogFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics) *reply = newHexNum(big.NewInt(int64(id)).Bytes()) + case "eth_newBlockFilter": - args := new(FilterStringArgs) - if err := json.Unmarshal(req.Params, &args); err != nil { - return err - } - *reply = newHexNum(api.xeth().NewFilterString(args.Word)) + *reply = newHexNum(api.xeth().NewBlockFilter()) + case "eth_newPendingTransactionFilter": + *reply = newHexNum(api.xeth().NewTransactionFilter()) case "eth_uninstallFilter": args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { @@ -357,7 +356,17 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err if err := json.Unmarshal(req.Params, &args); err != nil { return err } - *reply = NewLogsRes(api.xeth().FilterChanged(args.Id)) + + switch api.xeth().GetFilterType(args.Id) { + case xeth.BlockFilterTy: + *reply = NewHashesRes(api.xeth().BlockFilterChanged(args.Id)) + case xeth.TransactionFilterTy: + *reply = NewHashesRes(api.xeth().TransactionFilterChanged(args.Id)) + case xeth.LogFilterTy: + *reply = NewLogsRes(api.xeth().LogFilterChanged(args.Id)) + default: + *reply = []string{} // reply empty string slice + } case "eth_getFilterLogs": args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { diff --git a/rpc/responses.go b/rpc/responses.go index 884b7e69b..9fdf60c02 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -3,6 +3,7 @@ package rpc import ( "encoding/json" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" ) @@ -303,3 +304,13 @@ func NewLogsRes(logs state.Logs) (ls []LogRes) { return } + +func NewHashesRes(hs []common.Hash) []string { + hashes := make([]string, len(hs)) + + for i, hash := range hs { + hashes[i] = hash.Hex() + } + + return hashes +} diff --git a/xeth/xeth.go b/xeth/xeth.go index beda8871c..ad8596803 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -30,6 +30,14 @@ var ( defaultGas = big.NewInt(90000) //500000 ) +// byte will be inferred +const ( + UnknownFilterTy = iota + BlockFilterTy + TransactionFilterTy + LogFilterTy +) + func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) } func DefaultGasPrice() *big.Int { return new(big.Int).Set(defaultGasPrice) } @@ -43,11 +51,17 @@ type XEth struct { quit chan struct{} filterManager *filter.FilterManager - logMut sync.RWMutex - logs map[int]*logFilter + logMu sync.RWMutex + logQueue map[int]*logQueue + + blockMu sync.RWMutex + blockQueue map[int]*hashQueue + + transactionMu sync.RWMutex + transactionQueue map[int]*hashQueue - messagesMut sync.RWMutex - messages map[int]*whisperFilter + messagesMu sync.RWMutex + messages map[int]*whisperFilter // regmut sync.Mutex // register map[string][]*interface{} // TODO improve return type @@ -63,14 +77,16 @@ type XEth struct { // confirms all transactions will be used. func New(eth *eth.Ethereum, frontend Frontend) *XEth { xeth := &XEth{ - backend: eth, - frontend: frontend, - whisper: NewWhisper(eth.Whisper()), - quit: make(chan struct{}), - filterManager: filter.NewFilterManager(eth.EventMux()), - logs: make(map[int]*logFilter), - messages: make(map[int]*whisperFilter), - agent: miner.NewRemoteAgent(), + backend: eth, + frontend: frontend, + whisper: NewWhisper(eth.Whisper()), + quit: make(chan struct{}), + filterManager: filter.NewFilterManager(eth.EventMux()), + logQueue: make(map[int]*logQueue), + blockQueue: make(map[int]*hashQueue), + transactionQueue: make(map[int]*hashQueue), + messages: make(map[int]*whisperFilter), + agent: miner.NewRemoteAgent(), } eth.Miner().Register(xeth.agent) if frontend == nil { @@ -90,23 +106,41 @@ done: for { select { case <-timer.C: - self.logMut.Lock() - self.messagesMut.Lock() - for id, filter := range self.logs { + self.logMu.Lock() + for id, filter := range self.logQueue { + if time.Since(filter.timeout) > filterTickerTime { + self.filterManager.UninstallFilter(id) + delete(self.logQueue, id) + } + } + self.logMu.Unlock() + + self.blockMu.Lock() + for id, filter := range self.blockQueue { + if time.Since(filter.timeout) > filterTickerTime { + self.filterManager.UninstallFilter(id) + delete(self.blockQueue, id) + } + } + self.blockMu.Unlock() + + self.transactionMu.Lock() + for id, filter := range self.transactionQueue { if time.Since(filter.timeout) > filterTickerTime { self.filterManager.UninstallFilter(id) - delete(self.logs, id) + delete(self.transactionQueue, id) } } + self.transactionMu.Unlock() + self.messagesMu.Lock() for id, filter := range self.messages { if time.Since(filter.activity()) > filterTickerTime { self.Whisper().Unwatch(id) delete(self.messages, id) } } - self.messagesMut.Unlock() - self.logMut.Unlock() + self.messagesMu.Unlock() case <-self.quit: break done } @@ -271,6 +305,8 @@ func (self *XEth) EthTransactionByHash(hash string) (tx *types.Transaction, blha data, _ := self.backend.ExtraDb().Get(common.FromHex(hash)) if len(data) != 0 { tx = types.NewTransactionFromBytes(data) + } else { // check pending transactions + tx = self.backend.TxPool().GetTransaction(common.HexToHash(hash)) } // meta @@ -447,7 +483,32 @@ func (self *XEth) SecretToAddress(key string) string { return common.ToHex(pair.Address()) } -func (self *XEth) RegisterFilter(earliest, latest int64, skip, max int, address []string, topics [][]string) int { +func (self *XEth) UninstallFilter(id int) bool { + defer self.filterManager.UninstallFilter(id) + + if _, ok := self.logQueue[id]; ok { + self.logMu.Lock() + defer self.logMu.Unlock() + delete(self.logQueue, id) + return true + } + if _, ok := self.blockQueue[id]; ok { + self.blockMu.Lock() + defer self.blockMu.Unlock() + delete(self.blockQueue, id) + return true + } + if _, ok := self.transactionQueue[id]; ok { + self.transactionMu.Lock() + defer self.transactionMu.Unlock() + delete(self.transactionQueue, id) + return true + } + + return false +} + +func (self *XEth) NewLogFilter(earliest, latest int64, skip, max int, address []string, topics [][]string) int { var id int filter := core.NewFilter(self.backend) filter.SetEarliestBlock(earliest) @@ -457,71 +518,90 @@ func (self *XEth) RegisterFilter(earliest, latest int64, skip, max int, address filter.SetAddress(cAddress(address)) filter.SetTopics(cTopics(topics)) filter.LogsCallback = func(logs state.Logs) { - self.logMut.Lock() - defer self.logMut.Unlock() + self.logMu.Lock() + defer self.logMu.Unlock() - self.logs[id].add(logs...) + self.logQueue[id].add(logs...) } id = self.filterManager.InstallFilter(filter) - self.logs[id] = &logFilter{timeout: time.Now()} + self.logQueue[id] = &logQueue{timeout: time.Now()} return id } -func (self *XEth) UninstallFilter(id int) bool { - if _, ok := self.logs[id]; ok { - delete(self.logs, id) - self.filterManager.UninstallFilter(id) - return true - } +func (self *XEth) NewTransactionFilter() int { + var id int + filter := core.NewFilter(self.backend) + filter.TransactionCallback = func(tx *types.Transaction) { + self.transactionMu.Lock() + defer self.transactionMu.Unlock() - return false + self.transactionQueue[id].add(tx.Hash()) + } + id = self.filterManager.InstallFilter(filter) + self.transactionQueue[id] = &hashQueue{timeout: time.Now()} + return id } -func (self *XEth) NewFilterString(word string) int { +func (self *XEth) NewBlockFilter() int { var id int filter := core.NewFilter(self.backend) + filter.BlockCallback = func(block *types.Block, logs state.Logs) { + self.blockMu.Lock() + defer self.blockMu.Unlock() - switch word { - case "pending": - filter.PendingCallback = func(tx *types.Transaction) { - self.logMut.Lock() - defer self.logMut.Unlock() - - self.logs[id].add(&state.Log{}) - } - case "latest": - filter.BlockCallback = func(block *types.Block, logs state.Logs) { - self.logMut.Lock() - defer self.logMut.Unlock() + self.blockQueue[id].add(block.Hash()) + } + id = self.filterManager.InstallFilter(filter) + self.blockQueue[id] = &hashQueue{timeout: time.Now()} + return id +} - for _, log := range logs { - self.logs[id].add(log) - } - self.logs[id].add(&state.Log{}) - } +func (self *XEth) GetFilterType(id int) byte { + if _, ok := self.blockQueue[id]; ok { + return BlockFilterTy + } else if _, ok := self.transactionQueue[id]; ok { + return TransactionFilterTy + } else if _, ok := self.logQueue[id]; ok { + return LogFilterTy } - id = self.filterManager.InstallFilter(filter) - self.logs[id] = &logFilter{timeout: time.Now()} + return UnknownFilterTy +} - return id +func (self *XEth) LogFilterChanged(id int) state.Logs { + self.logMu.Lock() + defer self.logMu.Unlock() + + if self.logQueue[id] != nil { + return self.logQueue[id].get() + } + return nil } -func (self *XEth) FilterChanged(id int) state.Logs { - self.logMut.Lock() - defer self.logMut.Unlock() +func (self *XEth) BlockFilterChanged(id int) []common.Hash { + self.blockMu.Lock() + defer self.blockMu.Unlock() - if self.logs[id] != nil { - return self.logs[id].get() + if self.blockQueue[id] != nil { + return self.blockQueue[id].get() } + return nil +} + +func (self *XEth) TransactionFilterChanged(id int) []common.Hash { + self.blockMu.Lock() + defer self.blockMu.Unlock() + if self.transactionQueue[id] != nil { + return self.transactionQueue[id].get() + } return nil } func (self *XEth) Logs(id int) state.Logs { - self.logMut.Lock() - defer self.logMut.Unlock() + self.logMu.Lock() + defer self.logMu.Unlock() filter := self.filterManager.GetFilter(id) if filter != nil { @@ -552,24 +632,24 @@ func (p *XEth) NewWhisperFilter(to, from string, topics [][]string) int { // Callback to delegate core whisper messages to this xeth filter callback := func(msg WhisperMessage) { - p.messagesMut.RLock() // Only read lock to the filter pool - defer p.messagesMut.RUnlock() + p.messagesMu.RLock() // Only read lock to the filter pool + defer p.messagesMu.RUnlock() p.messages[id].insert(msg) } // Initialize the core whisper filter and wrap into xeth id = p.Whisper().Watch(to, from, topics, callback) - p.messagesMut.Lock() + p.messagesMu.Lock() p.messages[id] = newWhisperFilter(id, p.Whisper()) - p.messagesMut.Unlock() + p.messagesMu.Unlock() return id } // UninstallWhisperFilter disables and removes an existing filter. func (p *XEth) UninstallWhisperFilter(id int) bool { - p.messagesMut.Lock() - defer p.messagesMut.Unlock() + p.messagesMu.Lock() + defer p.messagesMu.Unlock() if _, ok := p.messages[id]; ok { delete(p.messages, id) @@ -580,8 +660,8 @@ func (p *XEth) UninstallWhisperFilter(id int) bool { // WhisperMessages retrieves all the known messages that match a specific filter. func (self *XEth) WhisperMessages(id int) []WhisperMessage { - self.messagesMut.RLock() - defer self.messagesMut.RUnlock() + self.messagesMu.RLock() + defer self.messagesMu.RUnlock() if self.messages[id] != nil { return self.messages[id].messages() @@ -592,8 +672,8 @@ func (self *XEth) WhisperMessages(id int) []WhisperMessage { // WhisperMessagesChanged retrieves all the new messages matched by a filter // since the last retrieval func (self *XEth) WhisperMessagesChanged(id int) []WhisperMessage { - self.messagesMut.RLock() - defer self.messagesMut.RUnlock() + self.messagesMu.RLock() + defer self.messagesMu.RUnlock() if self.messages[id] != nil { return self.messages[id].retrieve() @@ -860,19 +940,36 @@ func (m callmsg) Gas() *big.Int { return m.gas } func (m callmsg) Value() *big.Int { return m.value } func (m callmsg) Data() []byte { return m.data } -type logFilter struct { +type logQueue struct { logs state.Logs timeout time.Time id int } -func (l *logFilter) add(logs ...*state.Log) { +func (l *logQueue) add(logs ...*state.Log) { l.logs = append(l.logs, logs...) } -func (l *logFilter) get() state.Logs { +func (l *logQueue) get() state.Logs { l.timeout = time.Now() tmp := l.logs l.logs = nil return tmp } + +type hashQueue struct { + hashes []common.Hash + timeout time.Time + id int +} + +func (l *hashQueue) add(hashes ...common.Hash) { + l.hashes = append(l.hashes, hashes...) +} + +func (l *hashQueue) get() []common.Hash { + l.timeout = time.Now() + tmp := l.hashes + l.hashes = nil + return tmp +} |