Reduce Chaos in MemPool 😌

harmony

Reduce Chaos in MemPool 😌

banner

Table of Contents

Motivation

I discovered Ethereum's MemPool is one of the least explored domains, but not really least important.

Whenever a block is mined & some tx(s) are included in it, it's pretty much, value living at rest, whereas is case of mempool, value is in-flight. A lot of tx(s) are fighting for their space in next block to be mined, where only a few will get their place. But who will get, based or what criteria, it's not very much well defined.

We generally believe giving higher gas price compared to other tx(s) currently present in mempool, gives better chance that block miner will pick this tx during next block mining. But block miner always gets to override that, using custom logic. Also any one can write an automated program for monitoring mempool and replicate tx(s) of their interest with their own address, higher gas price - which may help them in cutting deal faster than original one or benefitting if target smart contract has some security loophole.

During my journey of exploring Ethereum MemPool, I found good initiative from BlockNative in demystifying MemPool. They've built some interesting products on top of mempool.

harmony - Reduce Chaos in MemPool 😌, aims to become a reliable mempool monitoring engine, while exposing useful functionalities for letting client applications write their monitoring logic seamlessly, with out worrying about underlying details too much 😎

  • You can subscribe to listen for tx(s) going to/ from address of interest
  • You can catch duplicate nonce tx(s), which of them gets accepted/ dropped
  • You can build notification service on top of it
  • It will help you in getting better gas price prediction
  • It can be used for building real-time charts showing current network traffic
  • Many more ...

Prerequisite

  • Make sure you've Go ( >= 1.16), make installed
  • You need to also have Redis ( >= 5.x )

Note : Consider setting up Redis instance with password protection

  • Get one Ethereum Node up & running, with txpool RPC API enabled. You can always use SaaS Ethereum node.

Installation

  • For using harmony, let's first clone this repo
git clone https://github.com/itzmeanjan/harmony.git
  • After getting inside harmony, create .env file with πŸ‘‡ content
cd harmony
touch .env
RPCUrl=https://<rpc-node>
MemPoolPollingPeriod=1000
PendingTxEntryTopic=pending_pool_entry
PendingTxExitTopic=pending_pool_exit
QueuedTxEntryTopic=queued_pool_entry
QueuedTxExitTopic=queued_pool_exit
RedisConnection=tcp
RedisAddress=127.0.0.1:6379
RedisPassword=password
RedisDB=1
ConcurrencyFactor=10
Port=7000
Environment Variable Interpretation
RPCUrl txpool RPC API enabled Ethereum Node's URI
MemPoolPollingPeriod RPC node's mempool to be checked every X milliseconds
PendingTxEntryTopic Whenever tx enters pending pool, it'll be published on Redis topic t
PendingTxExitTopic Whenever tx leaves pending pool, it'll be published on Redis topic t
QueuedTxEntryTopic Whenever tx enters queued pool, it'll be published on Redis topic t
QueuedTxExitTopic Whenever tx leaves queued pool, it'll be published on Redis topic t
RedisConnection Communicate with Redis over transport protocol
RedisAddress address:port combination of Redis
RedisPassword Authentication details for talking to Redis. [ Not mandatory ]
RedisDB Redis database to be used. [ By default there're 16 of them ]
ConcurrencyFactor Whenever concurrency can be leveraged, harmony will create worker pool with #-of logical CPUs x ConcurrencyFactor go routines. [ Can be float too ]
Port Starts HTTP server on this port ( > 1024 )
  • Let's build & run harmony
make run

Usage

Status of MemPool

For checking current state of mempool, you can issue one HTTP GET request

Method : GET

URL : /v1/stat

curl -s localhost:7000/v1/stat | jq

You'll receive response like πŸ‘‡

{
  "pendingPoolSize": 67,
  "queuedPoolSize": 0,
  "uptime": "29.214603s",
  "networkID": 137
}
Field Interpretation
pendingPoolSize Currently these many tx(s) are in pending state i.e. waiting to be picked up by some miner when next block gets mined
queuedPoolSize These tx(s) are stuck, will only be eligible for mining when lower nonce tx(s) of same wallet gets mined
uptime This mempool monitoring engine is alive for last t time unit
networkID The mempool monitoring engine keeps track of mempool of this network

Catching Any Mempool Changes

Whenever any change in mempool pool happens i.e. tx joins/ leaves pending/ queued pool, subscriber will be notified of those.

  • Tx joins queued pool, when it's stuck due to some nonce gap
  • It'll leave queued pool, when it's unstuck & lower nonce tx is processed
  • Tx joins pending pool, when it's ready to be included in next block [ though might not ]
  • Tx leaves pool, when tx it has been included in just mined block

Aforementioned changes generally happen in mempool & using following subscription API lets you capture all of those.

Transport : WebSocket

URL : /v1/graphql

subscription {
  memPool{
    from
    to
    gasPrice
	pool
	pendingFor
	queuedFor
  }
}

Catching Tx(s) From A in Mempool

When some new tx joins either of queued/ pending pool & that tx is sent from address A, subscriber to be notified of it.

When that tx will leave pool, client to be notified.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxFromAInMemPool{
    from
    to
    gasPrice
	pool
	pendingFor
	queuedFor
  }
}

Catching Tx(s) To A in Mempool

When some new tx joins either of queued/ pending pool & that tx is sent to address A, subscriber to be notified of it.

When that tx will leave pool, client to be notified.

Contract creation tx(s) will have empty to field

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxToAInMemPool{
    from
    to
    gasPrice
	pool
	pendingFor
	queuedFor
  }
}

Pending Pool

Pending pool inspection related APIs.

Pending for more than X

For listing all tx(s) pending for more than or equals to x time unit, send graphQL query

Method : POST

URL : /v1/graphql

query {
  pendingForMoreThan(x: "10s") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

You'll receive response of form

{
  "data": {
    "pendingForMoreThan": [
      {
        "from": "0xdF0692E287A763e5c011cc96Ee402994c6Dd246E",
        "gas": "35743",
        "gasPrice": "74 Gwei",
        "hash": "0x142f95b4615ad31d5435fb979a07405d50b70a2dab2707001cdb04853b75537e",
        "input": "0x22c67519000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001e35",
        "nonce": "108",
        "to": "0x86935F11C86623deC8a25696E1C19a8659CbF95d",
        "value": "0x0",
        "v": "0x136",
        "r": "0x4becd37941425526e5a1d361a44fd5f911affacaa5526e42e7a20c4a9fb04f90",
        "s": "0x3052c55bf6ac67326b4adb92c9ff3288ffe0f0be829b726c2a1cf5b9a58dca5c",
        "pendingFor": "10.677797s",
        "queuedFor": "0 s",
        "pool": "pending"
      }
    ]
  }
}

Pending for less than X

For listing all tx(s) pending for less than or equals to x time unit, send graphQL query

Method : POST

URL : /v1/graphql

query {
  pendingForLessThan(x: "1m10s") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Pending from A

For getting a list of all pending tx(s) from specific address, send a graphQL query like πŸ‘‡

Note : More than one pending tx from same address, denotes those are same nonce tx(s).

Method : POST

URL : /v1/graphql

query {
  pendingFrom(addr: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Pending to A

For getting a list of all pending tx(s) sent to specific address, you can send a graphQL query like πŸ‘‡

Method : POST

URL : /v1/graphql

query {
  pendingTo(addr: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Top X pending

Top X pending transaction(s), with high gas price

Method : POST

URL : /v1/graphql

query {
  topXPendingWithHighGasPrice(x: 10) {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Top X pending transaction(s), with low gas price

Method : POST

URL : /v1/graphql

query {
  topXPendingWithLowGasPrice(x: 10) {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Pending Duplicate Tx(s)

Given txHash, attempts to find out duplicate tx(s) present in pending pool.

Tx is considered to be duplicate, when it has, same sender address & nonce

Method : POST

URL : /v1/graphql

query {
  pendingDuplicates(hash: "0x2d17f2941e33afd3a648e3257857ed032191b7b93911364ba4906d640ca69b49") {
    from
	to
  	gas
  	gasPrice
  	hash
  	nonce
  	pendingFor
  	queuedFor
  	pool
  }
}

New pending tx(s)

Listening for any new tx, being added to pending pool, in real-time, over websocket transport

gql_subscription

Transport : WebSocket

URL : /v1/graphql

subscription {
  newPendingTx{
    from
    to
    gas
    gasPrice
    nonce
  }
}

New confirmed tx(s)

Listening for any new tx, leaving pending pool i.e. confirmed, in real-time, over websocket transport

Transport : WebSocket

URL : /v1/graphql

subscription {
  newConfirmedTx{
    from
    to
    gasPrice
  }
}

Pending Pool Changes

Whenever any change in pending tx pool happens i.e. tx joins/ leaves pool, subscriber will be notified of those

  • Tx joins pending pool, when it's ready to be included in next block [ though might not ]
  • Tx leaves pool, when tx it has been included in just mined block

Transport : WebSocket

URL : /v1/graphql

subscription {
  pendingPool{
    from
    to
    gasPrice
	pool
  }
}

New pending tx(s) from

When ever any tx is detected to be entering pending pool, where from address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newPendingTxFrom(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

New confirmed tx(s) from

When ever any tx is detected to be leaving pending pool i.e. got included in some block, where from address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newConfirmedTxFrom(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

Catching new pending tx from A

When new tx, sent from address A, is detected to be entering pending pool, client to be notified. Also when tx will be confirmed, they will be notified, that tx has left pending pool.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxFromAInPendingPool(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
	pendingFor
	queuedFor
  }
}

New pending tx(s) to

When ever any tx is detected to be entering pending pool, where to address is matching with specified one, subscriber will be notified of it.

Note: Tx(s) attempting to deploy contract, will have no to address

Transport : WebSocket

URL : /v1/graphql

subscription {
  newPendingTxTo(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

New confirmed tx(s) to

When ever any tx is detected to be leaving pending pool i.e. got included in some block, where to address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newConfirmedTxTo(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

Catching new pending tx to A

When new tx, where recipient address is A, is detected to be entering pending pool, client to be notified. Also when tx will be confirmed, they will be notified, that tx has left pending pool.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxToAInPendingPool(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
	pendingFor
	queuedFor
  }
}

Queued Pool

Queued tx pool inspection APIs.

Queued for more than X

For listing all tx(s) queued for more than or equals to x time unit, send graphQL query

Method : POST

URL : /v1/graphql

query {
  queuedForMoreThan(x: "1h10m39s") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Queued for less than X

For listing all tx(s) queued for less than or equals to x time unit, send graphQL query

Method : POST

URL : /v1/graphql

query {
  queuedForLessThan(x: "1m10s100ms") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Queued from A

For getting a list of all queued tx(s) from specific address, send a graphQL query like πŸ‘‡

Note : These are present in queued pool due to nonce gap in sender's address i.e. there must be some tx with lower nonce present in pending pool & until that one gets mined, these tx(s) in queued pool, will not move into pending pool.

Method : POST

URL : /v1/graphql

query {
  queuedFrom(addr: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Queued to A

For getting a list of all queued tx(s) sent to specific address, you can send a graphQL query like πŸ‘‡

Method : POST

URL : /v1/graphql

query {
  queuedTo(addr: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313") {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Top X pending

Top X queued transaction(s), with high gas price

Method : POST

URL : /v1/graphql

query {
  topXQueuedWithHighGasPrice(x: 10) {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Top X queued transaction(s), with low gas price

Method : POST

URL : /v1/graphql

query {
  topXQueuedWithLowGasPrice(x: 10) {
    from
  	gas
  	gasPrice
  	hash
  	input
  	nonce
  	to
  	value
  	v
  	r
  	s
  	pendingFor
  	queuedFor
  	pool
  }
}

Queued Duplicate Tx(s)

Given txHash, attempts to find out duplicate tx(s) present in queued pool.

Tx is considered to be duplicate, when it has, same sender address & nonce

Method : POST

URL : /v1/graphql

query {
  queuedDuplicates(hash: "0x2d17f2941e33afd3a648e3257857ed032191b7b93911364ba4906d640ca69b49") {
    from
	to
  	gas
  	gasPrice
  	hash
  	nonce
  	pendingFor
  	queuedFor
  	pool
  }
}

New queued tx(s)

Listening for any new tx, being added to queued pool, in real-time, over websocket transport

Transport : WebSocket

URL : /v1/graphql

subscription {
  newQueuedTx{
    from
    to
    gas
    gasPrice
    nonce
  }
}

New unstuck tx(s)

Listening for any new tx, leaving queued tx pool i.e. unstuck, in real-time, over websocket transport

Transport : WebSocket

URL : /v1/graphql

subscription {
  newUnstuckTx{
    from
    to
    gasPrice
  }
}

Queued Pool Changes

Whenever any change in queued tx pool happens i.e. tx joins/ leaves pool, subscriber will be notified of those

  • Tx joins queued pool, due to some issue in sender's account [ mostly nonce gap ], because it's not eligible for inclusion in next block to be mined
  • Tx leaves pool, when lower nonce has been filled up & this stuck tx is now ready to get included in block [ It's unstuck now ]

Transport : WebSocket

URL : /v1/graphql

subscription {
  queuedPool{
    from
    to
    gasPrice
	pool
  }
}

New queued tx(s) from

When ever any tx is detected to be entering queued pool ( because they're stuck due to nonce gap ), where from address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newQueuedTxFrom(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

New unstuck tx(s) from

When ever any tx is detected to be leaving queued pool ( because they were stuck due to nonce gap ), where from address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newUnstuckTxFrom(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

Catching new queued tx from A

When new tx, from address A, is detected to be entering queued pool, client to be notified. Also when that tx will be unstuck, client will be notified, that tx has left queued pool & it's now eligible to enter pending pool & become candidate tx for next block to be mined.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxFromAInQueuedPool(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
	pendingFor
	queuedFor
  }
}

New queued tx(s) to

When ever any tx is detected to be entering queued pool ( because they're stuck due to nonce gap ), where to address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newQueuedTxTo(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

New unstuck tx(s) to

When ever any tx is detected to be leaving queued pool ( because they were stuck due to nonce gap ), where to address is matching with specified one, subscriber will be notified of it.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newUnstuckTxTo(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
  }
}

Catching new queued tx to A

When new tx, targeted to address A, is detected to be entering queued pool, client to be notified. Also when tx will be unstuck, they will be notified, that tx has left queued pool & it's now eligible to enter pending pool & become candidate tx for next block to be mined.

Transport : WebSocket

URL : /v1/graphql

subscription {
  newTxToAInQueuedPool(address: "0x63ec5767F54F6943750A70eB6117EA2D9Ca77313"){
    from
    to
    gasPrice
	pendingFor
	queuedFor
  }
}

GraphQL Playground

harmony packs one graphQL playground for you, where you can play around with both query & subscription methods.

query works over HTTP transport, where as subscription works only over Websocket transport.

graphql_playground

URI : https://<base-url>/v1/graphql-playground

GraphQL Query/ Subscription Examples

I've written some examples for programmatically querying GraphQL API over HTTP & subscribing to topics for listening to MemPool state changes in real-time, over Websocket transport.

gql_subscription_example

You can find those here. Before you run those

  • Make sure you've Python3 installed. They're tested to be working on Python 3.9.2
  • Let's first enable virtual environment, by doing
cd examples
python3 -m venv venv
source venv/bin/activate
  • We can now fetch dependencies, by doing
pip install -r requirements.txt
  • You can now run any of examples, by doing
python3 query.py
python3 subscribe_1.py

Make sure, you've access to harmony node.

  • Finally when you're done, you can get out of virtual environment
deactivate

Note: harmony is not recommended for use in production environment at time of writing this. It's under active development.


Owner
Comments
  • Querying Mempool with GraphQL

    Querying Mempool with GraphQL

    Changes

    • Exposing graphql methods for querying latest state of mempool
    • Get tx(s) present in mempool i.e. {pending, queued} for >=, <= T, time unit
    • Also one graphql playground ✌️

    image

  • ❗ Failed to fetch block and Only transactions will be added, but completed transactions will not be removed;

    ❗ Failed to fetch block and Only transactions will be added, but completed transactions will not be removed;

    Hi, brother. During my testing, I found two problems:

    1. Only transactions will be added, but completed transactions will not be removed;
    2. Failed to fetch block:14294800 (error is: transaction type not supported)
    // ProcessBlock - Fetches all txs present in mined block & passes those to pending pool pruning worker
    func ProcessBlock(ctx context.Context, client *ethclient.Client, number *big.Int, commChan chan<- CaughtTxs, lastSeenBlockChan chan<- uint64) bool {
    	block, err := client.BlockByNumber(ctx, number)
    	if err != nil {
    		log.Printf("❗️ Failed to fetch block : %d\n %s \n", number, err) ---->(erris: transaction type not supported)
    		return false
    	}
    

    I need you help,thank you very much!


      / __/___/ /  ___
     / _// __/ _ \/ _ \
    /___/\__/_//_/\___/ v4.2.0
    High performance, minimalist Go web framework
    https://echo.labstack.com
    ____________________________________O/_______
                                        O\
    ⇨ http server started on [::]:7000
    2022/02/28 13:38:41 [βž•] Added 10119 tx(s) to queued tx pool, in 1.689134982s
    2022/02/28 13:38:41 [βž•] Added 457 tx(s) to pending tx pool, in 51.14923ms
    2022/02/28 13:38:41 ❇️ Pending Tx(s) : 457 | Queued Tx(s) : 10119, in 2.846309757s
    2022/02/28 13:38:42 [βž•] Added 7 tx(s) to queued tx pool, in 69.33677ms
    2022/02/28 13:38:42 [βž•] Added 34 tx(s) to pending tx pool, in 7.169083ms
    2022/02/28 13:38:42 ❇️ Pending Tx(s) : 491 | Queued Tx(s) : 10126, in 1.106247426s
    2022/02/28 13:38:43 [βž•] Added 10 tx(s) to pending tx pool, in 4.576167ms
    2022/02/28 13:38:43 ❇️ Pending Tx(s) : 501 | Queued Tx(s) : 10125, in 1.164577285s
    2022/02/28 13:38:44 [βž•] Added 18 tx(s) to pending tx pool, in 5.957062ms
    2022/02/28 13:38:44 ❇️ Pending Tx(s) : 519 | Queued Tx(s) : 10125, in 1.172117117s
    2022/02/28 13:38:45 [βž•] Added 11 tx(s) to pending tx pool, in 5.706903ms
    2022/02/28 13:38:45 ❇️ Pending Tx(s) : 530 | Queued Tx(s) : 10125, in 1.094710133s
    2022/02/28 13:38:46 [βž•] Added 3 tx(s) to queued tx pool, in 59.130545ms
    2022/02/28 13:38:46 [βž•] Added 18 tx(s) to pending tx pool, in 5.359677ms
    2022/02/28 13:38:46 ❇️ Pending Tx(s) : 548 | Queued Tx(s) : 10128, in 1.059802306s
    2022/02/28 13:38:49 [βž•] Added 16 tx(s) to pending tx pool, in 5.592977ms
    2022/02/28 13:38:49 ❇️ Pending Tx(s) : 564 | Queued Tx(s) : 10128, in 2.59863857s
    2022/02/28 13:38:51 [βž•] Added 1 tx(s) to queued tx pool, in 63.535859ms
    2022/02/28 13:38:51 [βž•] Added 36 tx(s) to pending tx pool, in 5.930608ms
    2022/02/28 13:38:51 ❇️ Pending Tx(s) : 600 | Queued Tx(s) : 10129, in 2.248649639s
    2022/02/28 13:38:53 [βž•] Added 2 tx(s) to queued tx pool, in 71.964043ms
    2022/02/28 13:38:53 [βž•] Added 118 tx(s) to pending tx pool, in 23.964072ms
    2022/02/28 13:38:53 ❇️ Pending Tx(s) : 718 | Queued Tx(s) : 10131, in 1.368934871s
    2022/02/28 13:38:54 [βž•] Added 20 tx(s) to pending tx pool, in 8.262592ms
    2022/02/28 13:38:54 ❇️ Pending Tx(s) : 738 | Queued Tx(s) : 10130, in 1.249005267s
    2022/02/28 13:38:55 [βž•] Added 1 tx(s) to queued tx pool, in 65.833426ms
    2022/02/28 13:38:55 [βž•] Added 12 tx(s) to pending tx pool, in 7.169755ms
    2022/02/28 13:38:55 ❇️ Pending Tx(s) : 750 | Queued Tx(s) : 10131, in 1.283568372s
    2022/02/28 13:38:56 [βž•] Added 10 tx(s) to pending tx pool, in 6.476501ms
    2022/02/28 13:38:56 ❇️ Pending Tx(s) : 760 | Queued Tx(s) : 10131, in 1.123001223s
    2022/02/28 13:38:58 [βž•] Added 1 tx(s) to queued tx pool, in 64.265631ms
    2022/02/28 13:38:58 [βž•] Added 23 tx(s) to pending tx pool, in 9.541043ms
    2022/02/28 13:38:58 ❇️ Pending Tx(s) : 783 | Queued Tx(s) : 10132, in 1.300504424s
    2022/02/28 13:38:59 [βž•] Added 4 tx(s) to queued tx pool, in 57.305082ms
    2022/02/28 13:38:59 [βž•] Added 35 tx(s) to pending tx pool, in 7.423574ms
    2022/02/28 13:38:59 ❇️ Pending Tx(s) : 818 | Queued Tx(s) : 10135, in 1.211386451s
    2022/02/28 13:39:00 [βž•] Added 13 tx(s) to pending tx pool, in 5.248855ms
    2022/02/28 13:39:00 ❇️ Pending Tx(s) : 831 | Queued Tx(s) : 10134, in 1.078215911s
    2022/02/28 13:39:05 [βž•] Added 5 tx(s) to queued tx pool, in 102.491104ms
    2022/02/28 13:39:05 [βž•] Added 12 tx(s) to pending tx pool, in 5.874882ms
    2022/02/28 13:39:05 ❇️ Pending Tx(s) : 843 | Queued Tx(s) : 10139, in 5.221286546s
    2022/02/28 13:39:06 [βž•] Added 10 tx(s) to queued tx pool, in 72.461747ms
    2022/02/28 13:39:07 [βž•] Added 44 tx(s) to pending tx pool, in 8.327105ms
    2022/02/28 13:39:07 ❇️ Pending Tx(s) : 887 | Queued Tx(s) : 10148, in 1.33273809s
    2022/02/28 13:39:08 [βž•] Added 1 tx(s) to queued tx pool, in 67.475553ms
    2022/02/28 13:39:08 [βž•] Added 44 tx(s) to pending tx pool, in 9.34013ms
    2022/02/28 13:39:08 ❇️ Pending Tx(s) : 932 | Queued Tx(s) : 10147, in 1.097033077s
    2022/02/28 13:39:09 [βž•] Added 13 tx(s) to pending tx pool, in 3.924495ms
    2022/02/28 13:39:09 ❇️ Pending Tx(s) : 945 | Queued Tx(s) : 10145, in 1.223074494s
    2022/02/28 13:39:10 [βž•] Added 2 tx(s) to queued tx pool, in 63.137728ms
    2022/02/28 13:39:10 [βž•] Added 8 tx(s) to pending tx pool, in 4.184372ms
    2022/02/28 13:39:10 ❇️ Pending Tx(s) : 953 | Queued Tx(s) : 10147, in 1.4534464s
    2022/02/28 13:39:12 [βž–] Removed 10 tx(s) from queued tx pool
    2022/02/28 13:39:12 [βž•] Added 28 tx(s) to pending tx pool, in 8.849301ms
    2022/02/28 13:39:12 ❇️ Pending Tx(s) : 981 | Queued Tx(s) : 10146, in 1.227720543s
    2022/02/28 13:39:13 [βž•] Added 2 tx(s) to queued tx pool, in 68.985141ms
    2022/02/28 13:39:13 [βž•] Added 18 tx(s) to pending tx pool, in 5.884856ms
    2022/02/28 13:39:13 ❇️ Pending Tx(s) : 999 | Queued Tx(s) : 10146, in 1.111469165s
    2022/02/28 13:39:14 [βž•] Added 15 tx(s) to pending tx pool, in 5.15586ms
    2022/02/28 13:39:14 ❇️ Pending Tx(s) : 1014 | Queued Tx(s) : 10146, in 1.520474802s
    2022/02/28 13:39:16 [βž•] Added 21 tx(s) to pending tx pool, in 5.802966ms
    2022/02/28 13:39:16 ❇️ Pending Tx(s) : 1035 | Queued Tx(s) : 10146, in 1.932619267s
    2022/02/28 13:39:17 [βž•] Added 17 tx(s) to pending tx pool, in 5.911145ms
    
    --------------------------Out Log---------------------------------------------
    2022/02/28 13:02:10 ❇️ Pending Tx(s) : 1016 | Queued Tx(s) : 11854, in 1.395611208s
    2022/02/28 13:02:12 [βž•] Added 2 tx(s) to queued tx pool, in 69.049747ms
    2022/02/28 13:02:12 [βž•] Added 13 tx(s) to pending tx pool, in 8.059417ms
    2022/02/28 13:02:12 ❇️ Pending Tx(s) : 1029 | Queued Tx(s) : 11856, in 1.55538375s
    2022/02/28 13:02:13 πŸ” header.Number 14294800 block(s)
    2022/02/28 13:02:13 ❗ Failed to fetch block : 14294800
    ------------------------------Code-------------------------------------------
          log.Printf("πŸ” header.Number %d block(s)\n", header.Number)
          if !ProcessBlock(ctx, client, header.Number, commChan, lastSeenBlockChan) {
            // Put entry in table that we failed to fetch this block, to be
            // attempted in some time future
            retryTable[header.Number] = struct{}{}
          }
    -----------------------------Code---------------------------------------------
    // ProcessBlock - Fetches all txs present in mined block & passes those to pending pool pruning worker
    func ProcessBlock(ctx context.Context, client *ethclient.Client, number *big.Int, commChan chan<- CaughtTxs, lastSeenBlockChan chan<- uint64) bool {
    	block, err := client.BlockByNumber(ctx, number)
    	if err != nil {
    		log.Printf("❗ Failed to fetch block : %d\n", number)
    		return false
    	}
    -------------------------------------------------------------------------
    
  • Failed to fetch mempool content : the method txpool_content does not exist/is not available

    Failed to fetch mempool content : the method txpool_content does not exist/is not available

    2022/02/13 07:27:21 [😌] Harmony - Reducing Chaos in MemPool 2022/02/13 07:27:21 [❃] Running in solo mode


    / // / ___ / // / _ / _
    /
    /_
    ////___/ v4.2.0 High performance, minimalist Go web framework https://echo.labstack.com _____________________________O/ O
    ⇨ http server started on [::]:7000 2022/02/13 07:27:21 [❗️] Failed to fetch mempool content : the method txpool_content does not exist/is not available 2022/02/13 07:27:21 ❗️ Block header subscription failed 2022/02/13 07:27:21 [βœ…] Gracefully shut down harmony after 8.188836ms

    can u help me?

  • Integrated `pub0sub`

    Integrated `pub0sub`

    What's new ?

    After experimenting with pub0sub - Fast, Lightweight Pub/Sub over TCP, QUIC - powered by Async I/O; for some time I've decided to use it with harmony for Pub/Sub.

    As pub0sub's Pub/Sub server 0hub is built using async I/O, it'll hopefully perform well.

    Under testing !!!

  • Update {Pending, Queued}MemPool with latest `txpool_content`

    Update {Pending, Queued}MemPool with latest `txpool_content`

    Changes

    • Periodically keep polling txpool_content for latest state of mempool
    • Attempt to update internal data structures with latest data
    • Keep track of discovery_time for each tx(s) found in either queued/ pending pool
    • After each iteration of fetching latest mempool state, publish changes ( only changes ) to pubsub topic [ WIP ]

    image

  • GraphQL New Queries

    GraphQL New Queries

    What's new ?

    As I wanted to query mempool for existence of transactions with gas price >= or <= specified gas price, I've added respective GraphQL queries for both pending & queued pool.

    Now one can get list of all pending txs with gas price >= 20.1 ( Gwei ).

    query {
      pendingWithMoreThan(x: 20.1) {
    	from
    	hash
    	gasPriceGwei
      }
    }
    

    For <= 10 Gwei, make use of query pendingWithLessThan(x: 10) { ... }.

    README.md has documentation around it.

    Note: Gas price provided/ represented in Gwei

  • GraphQL New Field Addition

    GraphQL New Field Addition

    Why ?

    I'm interested in obtaining gasPrice GraphQL field as float, which is why I add gasPriceGwei field which returns gas price in Gwei unit as floating point number ( double precision ).

    Now GraphQL queries can also be written as

    query {
      pendingForMoreThan(x: "10s") {
        gasPriceGwei
        nonce
      }
    }
    
  • Replace Redis with `pubsub`

    Replace Redis with `pubsub`

    What's new ?

    Redis was used for in-app messaging leveraging Single Producer Multiple Consumers/ Multiple Producers Multiple Consumers patterns, built around topics. But I recently wrote one embeddable, light-weight pub/sub system pubsub & Redis Pub/Sub being replaced with pubsub which is sleek, lean & doesn't make network calls πŸ”₯

    This is being tested now.

  • Reduce overtime memory usage

    Reduce overtime memory usage

    Why ?

    Both pending & queued pool keeps track of which tx(s) were removed because they were dropped/ confirmed/ unstuck & this memory usage overtime becomes a problem.

    If we keep removing those entries from tracker table which were seen long time back ( > 1 hour ), we can free some memory. 1 hour is just a random number being used, in hope, after 1 hour of last time it was attempted to be added into pool it is probably not there for again added into pool. This may not be true, if RPC node being relied on, doesn't feed us with fresh data.

  • Supervising Block Header Listener Worker

    Supervising Block Header Listener Worker

    Why ?

    Block header listen go routine can crash due to several reasons, so it's better to handle that by catching when it crashes & spawning new worker which can continue where its previous worker left off.

  • Track slowly propagated tx(s)

    Track slowly propagated tx(s)

    Why ?

    Some times mempool tx propagation takes more time than usual & mempool tx is received when it's actually mined. I'm going to keep track of which mined txs I couldn't find in pending pool & later time when same tx joins mempool as pending one, I'll let pending pool pruning worker know, this tx is actually mined.

    Hopefully solving our problem.

    Being tested on mainnet now

  •  Failed to publish tx ... pool : connection already teared down

    Failed to publish tx ... pool : connection already teared down

    Got this error in the console while running the program. The subscription feature also does not work, it just endlessly loads. I assume these issues are connected. The pub0 has been configured with default settings and is running in the background. The log starts by saying listening on xyz. Then it constantly switches from connected to disconnected

    harmony console

    pub0 logs .

  • Failed to acquire resource(s) : tls: first record does not look like a TLS handshake

    Failed to acquire resource(s) : tls: first record does not look like a TLS handshake

    ------------------------- RUN ------------------------------ user@fly9:~/Source/harmony$ ./harmony 2021/08/22 17:54:57 [😌] Harmony - Reducing Chaos in MemPool 2021/08/22 17:54:57 [❗️] Failed to acquire resource(s) : tls: first record does not look like a TLS handshake

    ------------------------- ENV FILE ------------------------- user@fly9:~/Source/harmony$ cat .env RPCUrl=https://localhost:8545 WSUrl=wss://localhost:8546 MemPoolPollingPeriod=1000 PendingPoolSize=4096 QueuedPoolSize=4096 PendingTxEntryTopic=pending_pool_entry PendingTxExitTopic=pending_pool_exit QueuedTxEntryTopic=queued_pool_entry QueuedTxExitTopic=queued_pool_exit ConcurrencyFactor=10 Port=7000 Pub0SubHost=127.0.0.1 Pub0SubPort=13000

    --------------------------------- NETSTAT PORT CHECK OF GETH ------------------------- user@fly9:~/Source/harmony$ netstat -nalptl | grep geth | grep 85 | grep -v EST tcp 0 0 127.0.0.1:8545 0.0.0.0:* LISTEN 2264523/geth
    tcp 0 0 127.0.0.1:8546 0.0.0.0:* LISTEN 2264523/geth

    --------------------------------- GETH VERSION ------------------------------------------- user@fly9:~$ geth version Geth Version: 1.10.6-stable Git Commit: 576681f29b895dd39e559b7ba17fcd89b42e4833 Architecture: amd64 Go Version: go1.16.4 Operating System: linux

    --------------------------------- HARMONY VERSION ------------------------------------- commit 4572d3712321cdaeb20e3313067f71ad3b3268dd (HEAD -> main, tag: v0.9.5, origin/main, origin/HEAD)

    --------------------------------- WIRESHARK SCEENSHOT if it helps ---------------------- image

EVM Liquidity Sniper Bot consuming GETH txs through the mempool

AX-50 Liquidity Sniper This bot requires you to run the GETH client + use ethers framework. Supports any EVM environment and UniSwapV2 forked AMM seem

Jan 6, 2023
A simple program able to listen to the pending transactions of the Ethereum mempool. Written in Go.

eth-mempool-listener-go A simple program able to listen to the pending transactions of the Ethereum mempool. How does it work ? It creates a set of cl

Dec 26, 2022
:alarm_clock: :fire: A TCP proxy to simulate network and system conditions for chaos and resiliency testing
:alarm_clock: :fire: A TCP proxy to simulate network and system conditions for chaos and resiliency testing

Toxiproxy Toxiproxy is a framework for simulating network conditions. It's made specifically to work in testing, CI and development environments, supp

Jan 7, 2023
HTTP mocking to test API services for chaos scenarios
HTTP mocking to test API services for chaos scenarios

GAOS HTTP mocking to test API services for chaos scenarios Gaos, can create and provide custom mock restful services via using your fully-customizable

Nov 5, 2022
Litmus helps Kubernetes SREs and developers practice chaos engineering in a Kubernetes native way.
Litmus helps Kubernetes SREs and developers practice chaos engineering in a Kubernetes native way.

Litmus Cloud-Native Chaos Engineering Read this in other languages. ???? ???? ???? ???? Overview Litmus is a toolset to do cloud-native chaos engineer

Jan 1, 2023
A function for chaos testing with OpenFaaS

chaos-fn A function for chaos testing with OpenFaaS Use-cases Test retries on certain HTTP codes Test timeouts Test certain lengths of HTTP request bo

May 26, 2022
Chaos Engineering tool for introducing failure into syscalls

Syscall monkey Chaos Engineering tool for tampering with syscalls.

Jun 11, 2022
Toxiproxy - A TCP proxy to simulate network and system conditions for chaos and resiliency testing
Toxiproxy - A TCP proxy to simulate network and system conditions for chaos and resiliency testing

Toxiproxy is a framework for simulating network conditions. It's made specifically to work in testing, CI and development environments, supp

Nov 3, 2021
The test suite to demonstrate the chaos experiment behavior in different scenarios

Litmus-E2E The goal of litmus e2e is to provide the test suite to demonstrate the chaos experiment behavior in different scenarios. As the name sugges

Jul 7, 2022
Chaosblade executor for chaos experiments on Java applications
Chaosblade executor for chaos experiments on Java applications

Chaosblade-exec-jvm: Chaosblade executor for chaos experiments on Java applications Introduction The project is a chaosblade executor based on jvm-san

Dec 16, 2022
Chaostheory task1 - This is repository for Chaos Theory Internship Program

Chaos Theory Internship - Take Home Task. Hyeonwoo KIM(clo3olb) City Universiry

Feb 11, 2022
Fast, efficient, and scalable distributed map/reduce system, DAG execution, in memory or on disk, written in pure Go, runs standalone or distributedly.

Gleam Gleam is a high performance and efficient distributed execution system, and also simple, generic, flexible and easy to customize. Gleam is built

Jan 1, 2023
Reduce debugging time while programming Go. Use static and stack-trace analysis to determine which func call causes the error.
Reduce debugging time while programming Go. Use static and stack-trace analysis to determine which func call causes the error.

Errlog: reduce debugging time while programming Introduction Use errlog to improve error logging and speed up debugging while you create amazing code

Nov 18, 2022
Fast, efficient, and scalable distributed map/reduce system, DAG execution, in memory or on disk, written in pure Go, runs standalone or distributedly.

Gleam Gleam is a high performance and efficient distributed execution system, and also simple, generic, flexible and easy to customize. Gleam is built

Jan 5, 2023
Map, Reduce, Filter, De/Multiplex, etc. for the Go language.

proto proto gives Go operations like Map, Reduce, Filter, De/Multiplex, etc. without sacrificing idiomatic harmony or speed. It also introduces a conv

Nov 17, 2022
Go library for writing standalone Map/Reduce jobs or for use with Hadoop's streaming protocol

dmrgo is a Go library for writing map/reduce jobs. It can be used with Hadoop's streaming protocol, but also includes a standalone map/reduce impleme

Nov 27, 2022
Reduce maintainer fatigue by automating GitHub
Reduce maintainer fatigue by automating GitHub

derek Derek reduces fatigue for maintainers by automating governance and delegating permissions to your team and community. Follow @derekapp on Twitte

Dec 23, 2022
"there" also called "GoThere" aims to be a simple Go Library to reduce redundant code for REST APIs.

there "there" also called "GoThere" aims to be a simple Go Library to reduce redundant code for REST APIs. Despite the existence of the other librarie

Dec 25, 2022