Use txids returned from pendingTransactions subscriptionfor mempool
This commit is contained in:
parent
9288a12f1d
commit
e12641ae7d
@ -41,20 +41,22 @@ type Configuration struct {
|
|||||||
// EthereumRPC is an interface to JSON-RPC eth service.
|
// EthereumRPC is an interface to JSON-RPC eth service.
|
||||||
type EthereumRPC struct {
|
type EthereumRPC struct {
|
||||||
*bchain.BaseChain
|
*bchain.BaseChain
|
||||||
client *ethclient.Client
|
client *ethclient.Client
|
||||||
rpc *rpc.Client
|
rpc *rpc.Client
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
Parser *EthereumParser
|
Parser *EthereumParser
|
||||||
Mempool *bchain.MempoolEthereumType
|
Mempool *bchain.MempoolEthereumType
|
||||||
bestHeaderMu sync.Mutex
|
bestHeaderLock sync.Mutex
|
||||||
bestHeader *ethtypes.Header
|
bestHeader *ethtypes.Header
|
||||||
bestHeaderTime time.Time
|
bestHeaderTime time.Time
|
||||||
chanNewBlock chan *ethtypes.Header
|
chanNewBlock chan *ethtypes.Header
|
||||||
newBlockSubscription *rpc.ClientSubscription
|
newBlockSubscription *rpc.ClientSubscription
|
||||||
chanNewTx chan ethcommon.Hash
|
chanNewTx chan ethcommon.Hash
|
||||||
newTxSubscription *rpc.ClientSubscription
|
newTxSubscription *rpc.ClientSubscription
|
||||||
ChainConfig *Configuration
|
pendingTransactions map[string]struct{}
|
||||||
isETC bool
|
pendingTransactionsLock sync.Mutex
|
||||||
|
ChainConfig *Configuration
|
||||||
|
isETC bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEthereumRPC returns new EthRPC instance.
|
// NewEthereumRPC returns new EthRPC instance.
|
||||||
@ -76,10 +78,11 @@ func NewEthereumRPC(config json.RawMessage, pushHandler func(bchain.Notification
|
|||||||
ec := ethclient.NewClient(rc)
|
ec := ethclient.NewClient(rc)
|
||||||
|
|
||||||
s := &EthereumRPC{
|
s := &EthereumRPC{
|
||||||
BaseChain: &bchain.BaseChain{},
|
BaseChain: &bchain.BaseChain{},
|
||||||
client: ec,
|
client: ec,
|
||||||
rpc: rc,
|
rpc: rc,
|
||||||
ChainConfig: &c,
|
ChainConfig: &c,
|
||||||
|
pendingTransactions: make(map[string]struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// always create parser
|
// always create parser
|
||||||
@ -100,10 +103,10 @@ func NewEthereumRPC(config json.RawMessage, pushHandler func(bchain.Notification
|
|||||||
}
|
}
|
||||||
glog.V(2).Info("rpc: new block header ", h.Number)
|
glog.V(2).Info("rpc: new block header ", h.Number)
|
||||||
// update best header to the new header
|
// update best header to the new header
|
||||||
s.bestHeaderMu.Lock()
|
s.bestHeaderLock.Lock()
|
||||||
s.bestHeader = h
|
s.bestHeader = h
|
||||||
s.bestHeaderTime = time.Now()
|
s.bestHeaderTime = time.Now()
|
||||||
s.bestHeaderMu.Unlock()
|
s.bestHeaderLock.Unlock()
|
||||||
// notify blockbook
|
// notify blockbook
|
||||||
pushHandler(bchain.NotificationNewBlock)
|
pushHandler(bchain.NotificationNewBlock)
|
||||||
}
|
}
|
||||||
@ -118,9 +121,13 @@ func NewEthereumRPC(config json.RawMessage, pushHandler func(bchain.Notification
|
|||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
hex := t.Hex()
|
||||||
if glog.V(2) {
|
if glog.V(2) {
|
||||||
glog.Info("rpc: new tx ", t.Hex())
|
glog.Info("rpc: new tx ", hex)
|
||||||
}
|
}
|
||||||
|
s.pendingTransactionsLock.Lock()
|
||||||
|
s.pendingTransactions[hex] = struct{}{}
|
||||||
|
s.pendingTransactionsLock.Unlock()
|
||||||
pushHandler(bchain.NotificationNewTx)
|
pushHandler(bchain.NotificationNewTx)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -296,8 +303,8 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthereumRPC) getBestHeader() (*ethtypes.Header, error) {
|
func (b *EthereumRPC) getBestHeader() (*ethtypes.Header, error) {
|
||||||
b.bestHeaderMu.Lock()
|
b.bestHeaderLock.Lock()
|
||||||
defer b.bestHeaderMu.Unlock()
|
defer b.bestHeaderLock.Unlock()
|
||||||
// ETC does not have newBlocks subscription, bestHeader must be updated very often (each 1 second)
|
// ETC does not have newBlocks subscription, bestHeader must be updated very often (each 1 second)
|
||||||
if b.isETC {
|
if b.isETC {
|
||||||
if b.bestHeaderTime.Add(1 * time.Second).Before(time.Now()) {
|
if b.bestHeaderTime.Add(1 * time.Second).Before(time.Now()) {
|
||||||
@ -467,12 +474,16 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
btxs := make([]bchain.Tx, len(body.Transactions))
|
btxs := make([]bchain.Tx, len(body.Transactions))
|
||||||
for i, tx := range body.Transactions {
|
for i := range body.Transactions {
|
||||||
btx, err := b.Parser.ethTxToTx(&tx, &rpcReceipt{Logs: logs[tx.Hash]}, bbh.Time, uint32(bbh.Confirmations))
|
tx := &body.Transactions[i]
|
||||||
|
btx, err := b.Parser.ethTxToTx(tx, &rpcReceipt{Logs: logs[tx.Hash]}, bbh.Time, uint32(bbh.Confirmations))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash)
|
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash)
|
||||||
}
|
}
|
||||||
btxs[i] = *btx
|
btxs[i] = *btx
|
||||||
|
b.pendingTransactionsLock.Lock()
|
||||||
|
delete(b.pendingTransactions, tx.Hash)
|
||||||
|
b.pendingTransactionsLock.Unlock()
|
||||||
}
|
}
|
||||||
bbk := bchain.Block{
|
bbk := bchain.Block{
|
||||||
BlockHeader: *bbh,
|
BlockHeader: *bbh,
|
||||||
@ -507,7 +518,14 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
|||||||
// GetTransactionForMempool returns a transaction by the transaction ID.
|
// GetTransactionForMempool returns a transaction by the transaction ID.
|
||||||
// It could be optimized for mempool, i.e. without block time and confirmations
|
// It could be optimized for mempool, i.e. without block time and confirmations
|
||||||
func (b *EthereumRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
func (b *EthereumRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||||
return b.GetTransaction(txid)
|
tx, err := b.GetTransaction(txid)
|
||||||
|
// it there is an error getting the tx or the tx is confirmed, remove it from pending transactions
|
||||||
|
if err != nil || (tx != nil && tx.Confirmations > 0) {
|
||||||
|
b.pendingTransactionsLock.Lock()
|
||||||
|
delete(b.pendingTransactions, txid)
|
||||||
|
b.pendingTransactionsLock.Unlock()
|
||||||
|
}
|
||||||
|
return tx, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransaction returns a transaction by the transaction ID.
|
// GetTransaction returns a transaction by the transaction ID.
|
||||||
@ -613,14 +631,25 @@ func (b *EthereumRPC) GetMempool() ([]string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(raw) == 0 {
|
|
||||||
return nil, bchain.ErrBlockNotFound
|
|
||||||
}
|
|
||||||
var body rpcBlockTxids
|
var body rpcBlockTxids
|
||||||
if err := json.Unmarshal(raw, &body); err != nil {
|
if len(raw) > 0 {
|
||||||
return nil, err
|
if err := json.Unmarshal(raw, &body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return body.Transactions, nil
|
b.pendingTransactionsLock.Lock()
|
||||||
|
// join transactions returned by getBlockRaw with pendingTransactions from subscription
|
||||||
|
for _, txid := range body.Transactions {
|
||||||
|
b.pendingTransactions[txid] = struct{}{}
|
||||||
|
}
|
||||||
|
txids := make([]string, len(b.pendingTransactions))
|
||||||
|
i := 0
|
||||||
|
for txid := range b.pendingTransactions {
|
||||||
|
txids[i] = txid
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
b.pendingTransactionsLock.Unlock()
|
||||||
|
return txids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EstimateFee returns fee estimation
|
// EstimateFee returns fee estimation
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user