/
processor.go
133 lines (121 loc) · 3.52 KB
/
processor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package eth
import (
"context"
poller "github.com/IRT-SystemX/bcm-poller/poller"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"log"
"math"
"math/big"
)
type BlockCacheEvent struct {
number *big.Int
parentHash string
hash string
Fork bool
Size float64 `json:"block_size"`
Gas float64 `json:"block_gas"`
GasLimit float64 `json:"block_gas_limit"`
Usage float64 `json:"block_usage"`
Interval uint64
timestamp uint64
difficulty string
uncles uint64
Miner string
Transactions []*TxEvent
poller.BlockEvent
}
func (blockEvent *BlockCacheEvent) Number() *big.Int {
return blockEvent.number
}
func (blockEvent *BlockCacheEvent) Timestamp() uint64 {
return blockEvent.timestamp
}
func (blockEvent *BlockCacheEvent) ParentHash() string {
return blockEvent.parentHash
}
func (blockEvent *BlockCacheEvent) Hash() string {
return blockEvent.hash
}
func (blockEvent *BlockCacheEvent) SetFork(fork bool) {
blockEvent.Fork = fork
}
type TxEvent struct {
Sender string
Receiver string
Value *big.Int
FunctionId string
Events []string
Deploy string
}
type Processor struct {
client *ethclient.Client
signer types.EIP155Signer
fork *ForkWatcher
}
func NewProcessor(client *ethclient.Client, fork *ForkWatcher) *Processor {
processor := &Processor{client: client, fork: fork}
chainID, err := processor.client.NetworkID(context.Background())
if err != nil {
log.Fatal(err)
}
processor.signer = types.NewEIP155Signer(chainID)
return processor
}
func (processor *Processor) NewBlockEvent(number *big.Int, parentHash string, hash string) poller.BlockEvent {
blockEvent := &BlockCacheEvent{
number: number,
parentHash: parentHash,
hash: hash,
}
return interface{}(blockEvent).(poller.BlockEvent)
}
func (processor *Processor) Process(obj interface{}, event poller.BlockEvent, listening bool) {
block := obj.(*types.Block)
blockEvent := interface{}(event).(*BlockCacheEvent)
blockEvent.timestamp = block.Time()
blockEvent.difficulty = block.Difficulty().String()
blockEvent.uncles = uint64(len(block.Uncles()))
blockEvent.Size = float64(block.Size())
blockEvent.Gas = float64(block.GasUsed())
blockEvent.GasLimit = float64(block.GasLimit())
blockEvent.Usage = math.Abs(float64(block.GasUsed()) * 100 / float64(block.GasLimit()))
blockEvent.Miner = block.Coinbase().Hex()
blockEvent.Transactions = make([]*TxEvent, len(block.Transactions()))
for i, tx := range block.Transactions() {
//log.Printf("Process tx %s", tx.Hash().Hex())
txEvent := &TxEvent{Events: make([]string, 0)}
blockEvent.Transactions[i] = txEvent
txEvent.Value = tx.Value()
if tx.To() != nil {
txEvent.Receiver = tx.To().Hex()
}
msg, err := tx.AsMessage(processor.signer)
if err != nil {
log.Println("Error msg: ", err)
} else {
txEvent.Sender = msg.From().Hex()
data := msg.Data()
if len(data) > 4 {
txEvent.FunctionId = string(hexutil.Encode(data[:4]))
}
}
receipt, err := processor.client.TransactionReceipt(context.Background(), tx.Hash())
if err != nil {
log.Println("Error receipt: ", err)
} else {
txEvent.Deploy = receipt.ContractAddress.Hex()
for _, vLog := range receipt.Logs {
for i := range vLog.Topics {
txEvent.Events = append(txEvent.Events, vLog.Topics[i].Hex())
}
}
}
}
blockEvent.SetFork(false)
if listening {
processor.fork.checkFork(blockEvent)
processor.fork.apply(blockEvent)
}
}