@@ -29,20 +29,42 @@ import (
29
29
30
30
var errMissingLogFields = errors .New ("missing required JSON log fields" )
31
31
32
- // Log represents a contract log event. These events are generated by the LOG
33
- // opcode and stored/indexed by the node.
32
+ // Log represents a contract log event. These events are generated by the LOG opcode and
33
+ // stored/indexed by the node.
34
34
type Log struct {
35
35
// Consensus fields.
36
36
Address common.Address // address of the contract that generated the event
37
37
Topics []common.Hash // list of topics provided by the contract.
38
38
Data []byte // supplied by the contract, usually ABI-encoded
39
39
40
- // Derived fields (don't reorder!).
40
+ // Derived fields. These fields are filled in by the node
41
+ // but not secured by consensus.
41
42
BlockNumber uint64 // block in which the transaction was included
42
43
TxHash common.Hash // hash of the transaction
43
44
TxIndex uint // index of the transaction in the block
44
45
BlockHash common.Hash // hash of the block in which the transaction was included
45
46
Index uint // index of the log in the receipt
47
+
48
+ // The Removed field is true if this log was reverted due to a chain reorganisation.
49
+ // You must pay attention to this field if you receive logs through a filter query.
50
+ Removed bool
51
+ }
52
+
53
+ type rlpLog struct {
54
+ Address common.Address
55
+ Topics []common.Hash
56
+ Data []byte
57
+ }
58
+
59
+ type rlpStorageLog struct {
60
+ Address common.Address
61
+ Topics []common.Hash
62
+ Data []byte
63
+ BlockNumber uint64
64
+ TxHash common.Hash
65
+ TxIndex uint
66
+ BlockHash common.Hash
67
+ Index uint
46
68
}
47
69
48
70
type jsonLog struct {
@@ -54,73 +76,115 @@ type jsonLog struct {
54
76
TxHash * common.Hash `json:"transactionHash"`
55
77
BlockHash * common.Hash `json:"blockHash"`
56
78
Index * hexutil.Uint `json:"logIndex"`
79
+ Removed bool `json:"removed"`
57
80
}
58
81
59
82
func NewLog (address common.Address , topics []common.Hash , data []byte , number uint64 ) * Log {
60
83
return & Log {Address : address , Topics : topics , Data : data , BlockNumber : number }
61
84
}
62
85
86
+ // EncodeRLP implements rlp.Encoder.
63
87
func (l * Log ) EncodeRLP (w io.Writer ) error {
64
- return rlp .Encode (w , [] interface {}{ l .Address , l .Topics , l .Data })
88
+ return rlp .Encode (w , rlpLog { Address : l .Address , Topics : l .Topics , Data : l .Data })
65
89
}
66
90
91
+ // DecodeRLP implements rlp.Decoder.
67
92
func (l * Log ) DecodeRLP (s * rlp.Stream ) error {
68
- var log struct {
69
- Address common. Address
70
- Topics []common. Hash
71
- Data [] byte
93
+ var dec rlpLog
94
+ err := s . Decode ( & dec )
95
+ if err == nil {
96
+ l . Address , l . Topics , l . Data = dec . Address , dec . Topics , dec . Data
72
97
}
73
- if err := s .Decode (& log ); err != nil {
74
- return err
75
- }
76
- l .Address , l .Topics , l .Data = log .Address , log .Topics , log .Data
77
- return nil
98
+ return err
78
99
}
79
100
80
101
func (l * Log ) String () string {
81
102
return fmt .Sprintf (`log: %x %x %x %x %d %x %d` , l .Address , l .Topics , l .Data , l .TxHash , l .TxIndex , l .BlockHash , l .Index )
82
103
}
83
104
84
105
// MarshalJSON implements json.Marshaler.
85
- func (r * Log ) MarshalJSON () ([]byte , error ) {
86
- return json .Marshal (& jsonLog {
87
- Address : & r .Address ,
88
- Topics : & r .Topics ,
89
- Data : (* hexutil .Bytes )(& r .Data ),
90
- BlockNumber : (* hexutil .Uint64 )(& r .BlockNumber ),
91
- TxIndex : (* hexutil .Uint )(& r .TxIndex ),
92
- TxHash : & r .TxHash ,
93
- BlockHash : & r .BlockHash ,
94
- Index : (* hexutil .Uint )(& r .Index ),
95
- })
106
+ func (l * Log ) MarshalJSON () ([]byte , error ) {
107
+ jslog := & jsonLog {
108
+ Address : & l .Address ,
109
+ Topics : & l .Topics ,
110
+ Data : (* hexutil .Bytes )(& l .Data ),
111
+ TxIndex : (* hexutil .Uint )(& l .TxIndex ),
112
+ TxHash : & l .TxHash ,
113
+ Index : (* hexutil .Uint )(& l .Index ),
114
+ Removed : l .Removed ,
115
+ }
116
+ // Set block information for mined logs.
117
+ if (l .BlockHash != common.Hash {}) {
118
+ jslog .BlockHash = & l .BlockHash
119
+ jslog .BlockNumber = (* hexutil .Uint64 )(& l .BlockNumber )
120
+ }
121
+ return json .Marshal (jslog )
96
122
}
97
123
98
124
// UnmarshalJSON implements json.Umarshaler.
99
- func (r * Log ) UnmarshalJSON (input []byte ) error {
125
+ func (l * Log ) UnmarshalJSON (input []byte ) error {
100
126
var dec jsonLog
101
127
if err := json .Unmarshal (input , & dec ); err != nil {
102
128
return err
103
129
}
104
- if dec .Address == nil || dec .Topics == nil || dec .Data == nil || dec . BlockNumber == nil ||
105
- dec .TxIndex == nil || dec .TxHash == nil || dec .BlockHash == nil || dec . Index == nil {
130
+ if dec .Address == nil || dec .Topics == nil || dec .Data == nil ||
131
+ dec .TxIndex == nil || dec .TxHash == nil || dec .Index == nil {
106
132
return errMissingLogFields
107
133
}
108
- * r = Log {
109
- Address : * dec .Address ,
110
- Topics : * dec .Topics ,
111
- Data : * dec .Data ,
112
- BlockNumber : uint64 (* dec .BlockNumber ),
113
- TxHash : * dec .TxHash ,
114
- TxIndex : uint (* dec .TxIndex ),
115
- BlockHash : * dec .BlockHash ,
116
- Index : uint (* dec .Index ),
134
+ declog := Log {
135
+ Address : * dec .Address ,
136
+ Topics : * dec .Topics ,
137
+ Data : * dec .Data ,
138
+ TxHash : * dec .TxHash ,
139
+ TxIndex : uint (* dec .TxIndex ),
140
+ Index : uint (* dec .Index ),
141
+ Removed : dec .Removed ,
142
+ }
143
+ // Block information may be missing if the log is received through
144
+ // the pending log filter, so it's handled specially here.
145
+ if dec .BlockHash != nil && dec .BlockNumber != nil {
146
+ declog .BlockHash = * dec .BlockHash
147
+ declog .BlockNumber = uint64 (* dec .BlockNumber )
117
148
}
149
+ * l = declog
118
150
return nil
119
151
}
120
152
121
153
type Logs []* Log
122
154
123
- // LogForStorage is a wrapper around a Log that flattens and parses the entire
124
- // content of a log, as opposed to only the consensus fields originally (by hiding
125
- // the rlp interface methods).
155
+ // LogForStorage is a wrapper around a Log that flattens and parses the entire content of
156
+ // a log including non-consensus fields.
126
157
type LogForStorage Log
158
+
159
+ // EncodeRLP implements rlp.Encoder.
160
+ func (l * LogForStorage ) EncodeRLP (w io.Writer ) error {
161
+ return rlp .Encode (w , rlpStorageLog {
162
+ Address : l .Address ,
163
+ Topics : l .Topics ,
164
+ Data : l .Data ,
165
+ BlockNumber : l .BlockNumber ,
166
+ TxHash : l .TxHash ,
167
+ TxIndex : l .TxIndex ,
168
+ BlockHash : l .BlockHash ,
169
+ Index : l .Index ,
170
+ })
171
+ }
172
+
173
+ // DecodeRLP implements rlp.Decoder.
174
+ func (l * LogForStorage ) DecodeRLP (s * rlp.Stream ) error {
175
+ var dec rlpStorageLog
176
+ err := s .Decode (& dec )
177
+ if err == nil {
178
+ * l = LogForStorage {
179
+ Address : dec .Address ,
180
+ Topics : dec .Topics ,
181
+ Data : dec .Data ,
182
+ BlockNumber : dec .BlockNumber ,
183
+ TxHash : dec .TxHash ,
184
+ TxIndex : dec .TxIndex ,
185
+ BlockHash : dec .BlockHash ,
186
+ Index : dec .Index ,
187
+ }
188
+ }
189
+ return err
190
+ }
0 commit comments