pull/138/head
kompotkot 2021-08-20 13:39:02 +00:00
rodzic 2c9bca0943
commit 0eed78ba16
1 zmienionych plików z 151 dodań i 28 usunięć

Wyświetl plik

@ -1,17 +1,22 @@
package main
import (
"encoding/json"
// "encoding/json"
// "encoding/hex"
"flag"
"fmt"
"os"
"time"
humbug "github.com/bugout-dev/humbug/go/pkg"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
// "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/google/uuid"
)
// Generate humbug client to be able write data in Bugout journal.
func humbugClientFromEnv() (*humbug.HumbugReporter, error) {
clientID := os.Getenv("ETHTXPOOL_HUMBUG_CLIENT_ID")
humbugToken := os.Getenv("ETHTXPOOL_HUMBUG_TOKEN")
@ -22,29 +27,124 @@ func humbugClientFromEnv() (*humbug.HumbugReporter, error) {
return reporter, err
}
type txJSON struct {
Type hexutil.Uint64 `json:"type"`
// Common transaction fields:
Nonce *hexutil.Uint64 `json:"nonce"`
GasPrice *hexutil.Big `json:"gasPrice"`
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
Gas *hexutil.Uint64 `json:"gas"`
Value *hexutil.Big `json:"value"`
Data *hexutil.Bytes `json:"input"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
To *common.Address `json:"to"`
// Access list transaction fields:
ChainID *hexutil.Big `json:"chainId,omitempty"`
// AccessList *AccessList `json:"accessList,omitempty"`
// Only used for encoding:
Hash common.Hash `json:"hash"`
}
type PendingTransaction struct {
From string `json:"from"`
Nonce uint64 `json:"nonce"`
Transaction interface{} `json:"transaction"`
From string `json:"from"`
Nonce uint64 `json:"nonce"`
Transaction *txJSON `json:"transaction"`
}
type PendingTransactions struct {
Transactions PendingTransaction `json:"transactions"`
}
var ReportTitle string = "Ethereum: Pending transaction"
// Fetch list of transactions form Ethereum TxPool
// func TxPoolCall(gethClient *rpc.Client) (pendingTxsNew []PendingTransaction) {
func TxPoolCall(gethClient *rpc.Client) {
pendingTxsOld := make([]PendingTransaction, 0, 6000) // List of transactions from previous iteration
pendingTxsNew := make([]PendingTransaction, 0, 6000) // Empty list for new incoming transactions
var result map[string]map[string]map[uint64]*txJSON
for {
gethClient.Call(&result, "txpool_content")
pendingTransactions := result["pending"]
// Iterate over fetched result
for fromAddress, transactionsByNonce := range pendingTransactions {
for nonce, transaction := range transactionsByNonce {
pendingTx := PendingTransaction{From: fromAddress, Nonce: nonce, Transaction: transaction}
pendingTxsNew = append(pendingTxsNew, pendingTx) // Add to list of new incoming transactions
// Check if transaction in old list of transactions,
// then remove from it
for oldTxInd, oldTx := range pendingTxsOld {
if pendingTx.Transaction.Hash == oldTx.Transaction.Hash {
pendingTxsOld[oldTxInd] = pendingTxsOld[len(pendingTxsOld)-1]
// pendingTxsOld[len(pendingTxsOld)-1] = "" // Erase last element (write zero value) TODO: not sure I should do it
pendingTxsOld = pendingTxsOld[:len(pendingTxsOld)-1]
} else {
// send to humbug
}
}
// _, jsonErr := json.Marshal(pendingTx)
// if jsonErr != nil {
// fmt.Fprintf(os.Stderr, "Error marshalling pending transaction to JSON:\n%v\n", pendingTx)
// continue
// }
// fmt.Println(transactionHash)
// // report := humbug.Report{
// // Title: ReportTitle,
// // Content: string(contents),
// // Tags: []string{"lol"},
// // }
// // reporter.Publish(report)
}
}
// - For loop through pendingTxsOld to mark in humbug as old
// - Clean old slice
pendingTxsOld = pendingTxsOld[:0]
fmt.Println("New:", len(pendingTxsNew))
// - Copy new slice to old
copy(pendingTxsOld, pendingTxsNew)
fmt.Println("New:", len(pendingTxsNew))
// - Clean new slice
pendingTxsNew = pendingTxsNew[:0]
fmt.Println("New:", len(pendingTxsNew))
fmt.Println("Old:", len(pendingTxsOld))
time.Sleep(3 * time.Second)
}
// return
}
func main() {
var gethConnectionString string
flag.StringVar(&gethConnectionString, "geth", "", "Geth IPC path/RPC url/Websockets URL")
flag.Parse()
// Set connection with Ethereum blockchain via geth
gethClient, err := rpc.Dial(gethConnectionString)
if err != nil {
panic(fmt.Sprintf("Could not connect to geth: %s", err.Error()))
}
defer gethClient.Close()
reporter, err := humbugClientFromEnv()
if err != nil {
panic(fmt.Sprintf("Invalid Humbug configuration: %s", err.Error()))
}
// reporter, err := humbugClientFromEnv()
// if err != nil {
// panic(fmt.Sprintf("Invalid Humbug configuration: %s", err.Error()))
// }
// TODO(kompotkot, zomglings): We should cache pending transactions in memory and only publish reports
// for new transactions. When this process starts up, it should pull the most recent (within last 5 minutes -- tunable)
@ -60,23 +160,46 @@ func main() {
// TODO(kompotkot, zomglings): Right now, we are only working with "pending" transactions. Ethereum
// TXPool data structure also has "queued" transactions. What is the difference between "pending" and
// "queued" and should we be reporting "queued" transaction as well?
var result map[string]map[string]map[uint64]*types.Transaction
gethClient.Call(&result, "txpool_content")
pendingTransactions := result["pending"]
for fromAddress, transactionsByNonce := range pendingTransactions {
for nonce, transaction := range transactionsByNonce {
pendingTx := PendingTransaction{From: fromAddress, Nonce: nonce, Transaction: transaction}
contents, jsonErr := json.Marshal(pendingTx)
if jsonErr != nil {
fmt.Fprintf(os.Stderr, "Error marshalling pending transaction to JSON:\n%v\n", pendingTx)
continue
}
report := humbug.Report{
Title: ReportTitle,
Content: string(contents),
Tags: []string{"lol"},
}
reporter.Publish(report)
}
}
// pendingHashList := []common.Hash
// updatedPendingHashList := []common.Hash
// var result map[string]map[string]map[uint64]*txJSON
// gethClient.Call(&result, "txpool_content")
// pendingTransactions := result["pending"]
// for fromAddress, transactionsByNonce := range pendingTransactions {
// for nonce, transaction := range transactionsByNonce {
// pendingTx := PendingTransaction{From: fromAddress, Nonce: nonce, Transaction: transaction}
// // pendingTransactionsRes := append(pendingTransactionsRes, pendingTx)
// fmt.Println(pendingTx.Transaction.GasPrice)
// contents, jsonErr := json.Marshal(pendingTx)
// if jsonErr != nil {
// fmt.Fprintf(os.Stderr, "Error marshalling pending transaction to JSON:\n%v\n", pendingTx)
// continue
// }
// fmt.Println(string(contents))
// // // report := humbug.Report{
// // // Title: ReportTitle,
// // // Content: string(contents),
// // // Tags: []string{"lol"},
// // // }
// // // reporter.Publish(report)
// }
// break
// }
TxPoolCall(gethClient)
// pendingTransactions := TxPoolCall(gethClient)
// fmt.Println(len(pendingTransactions))
// transactionHash := transaction.Hash
// for h := range pendingHashList{
// if h == transactionHash {
// updatedPendingHashList
// }
// }
}