aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Godeps/Godeps.json4
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/ethashc.go12
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.c2
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/internal.h6
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io.h7
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/io_win32.c2
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash/util.h8
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/ethash/test/c/test.cpp45
-rw-r--r--core/filter.go6
-rw-r--r--core/transaction_pool.go21
-rw-r--r--event/filter/eth_filter.go4
-rw-r--r--rpc/api.go23
-rw-r--r--rpc/responses.go11
-rw-r--r--xeth/xeth.go239
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
+}