Skip to content

Commit f52a1ae

Browse files
committed
core, core/vm, eth/filters: move Removed field into vm.Log
This field used to be assigned by the filter system and returned through the RPC API. Now that we have a Go client that uses the underlying type, the field needs to move. It is now assigned to true when the RemovedLogs event is generated so the filter system doesn't need to care about the field at all. While here, remove the log list from ChainSideEvent. There are no users of this field right now and any potential users could subscribe to RemovedLogsEvent instead.
1 parent 3bc0fe1 commit f52a1ae

File tree

8 files changed

+252
-165
lines changed

8 files changed

+252
-165
lines changed

core/blockchain.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
988988
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
989989
}
990990
blockInsertTimer.UpdateSince(bstart)
991-
events = append(events, ChainSideEvent{block, logs})
991+
events = append(events, ChainSideEvent{block})
992992

993993
case SplitStatTy:
994994
events = append(events, ChainSplitEvent{block, logs})
@@ -1062,24 +1062,25 @@ func countTransactions(chain []*types.Block) (c int) {
10621062
// event about them
10631063
func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
10641064
var (
1065-
newChain types.Blocks
1066-
oldChain types.Blocks
1067-
commonBlock *types.Block
1068-
oldStart = oldBlock
1069-
newStart = newBlock
1070-
deletedTxs types.Transactions
1071-
deletedLogs vm.Logs
1072-
deletedLogsByHash = make(map[common.Hash]vm.Logs)
1065+
newChain types.Blocks
1066+
oldChain types.Blocks
1067+
commonBlock *types.Block
1068+
oldStart = oldBlock
1069+
newStart = newBlock
1070+
deletedTxs types.Transactions
1071+
deletedLogs vm.Logs
10731072
// collectLogs collects the logs that were generated during the
10741073
// processing of the block that corresponds with the given hash.
10751074
// These logs are later announced as deleted.
10761075
collectLogs = func(h common.Hash) {
1077-
// Coalesce logs
1076+
// Coalesce logs and set 'Removed'.
10781077
receipts := GetBlockReceipts(self.chainDb, h, self.hc.GetBlockNumber(h))
10791078
for _, receipt := range receipts {
1080-
deletedLogs = append(deletedLogs, receipt.Logs...)
1081-
1082-
deletedLogsByHash[h] = receipt.Logs
1079+
for _, log := range receipt.Logs {
1080+
del := *log
1081+
del.Removed = true
1082+
deletedLogs = append(deletedLogs, &del)
1083+
}
10831084
}
10841085
}
10851086
)
@@ -1173,7 +1174,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
11731174
if len(oldChain) > 0 {
11741175
go func() {
11751176
for _, block := range oldChain {
1176-
self.eventMux.Post(ChainSideEvent{Block: block, Logs: deletedLogsByHash[block.Hash()]})
1177+
self.eventMux.Post(ChainSideEvent{Block: block})
11771178
}
11781179
}()
11791180
}

core/events.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ type ChainEvent struct {
6161

6262
type ChainSideEvent struct {
6363
Block *types.Block
64-
Logs vm.Logs
6564
}
6665

6766
type PendingBlockEvent struct {

core/vm/log.go

Lines changed: 103 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,42 @@ import (
2929

3030
var errMissingLogFields = errors.New("missing required JSON log fields")
3131

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.
3434
type Log struct {
3535
// Consensus fields.
3636
Address common.Address // address of the contract that generated the event
3737
Topics []common.Hash // list of topics provided by the contract.
3838
Data []byte // supplied by the contract, usually ABI-encoded
3939

40-
// Derived fields (don't reorder!).
40+
// Derived fields. These fields are filled in by the node
41+
// but not secured by consensus.
4142
BlockNumber uint64 // block in which the transaction was included
4243
TxHash common.Hash // hash of the transaction
4344
TxIndex uint // index of the transaction in the block
4445
BlockHash common.Hash // hash of the block in which the transaction was included
4546
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
4668
}
4769

4870
type jsonLog struct {
@@ -54,73 +76,115 @@ type jsonLog struct {
5476
TxHash *common.Hash `json:"transactionHash"`
5577
BlockHash *common.Hash `json:"blockHash"`
5678
Index *hexutil.Uint `json:"logIndex"`
79+
Removed bool `json:"removed"`
5780
}
5881

5982
func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *Log {
6083
return &Log{Address: address, Topics: topics, Data: data, BlockNumber: number}
6184
}
6285

86+
// EncodeRLP implements rlp.Encoder.
6387
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})
6589
}
6690

91+
// DecodeRLP implements rlp.Decoder.
6792
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
7297
}
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
7899
}
79100

80101
func (l *Log) String() string {
81102
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)
82103
}
83104

84105
// 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)
96122
}
97123

98124
// UnmarshalJSON implements json.Umarshaler.
99-
func (r *Log) UnmarshalJSON(input []byte) error {
125+
func (l *Log) UnmarshalJSON(input []byte) error {
100126
var dec jsonLog
101127
if err := json.Unmarshal(input, &dec); err != nil {
102128
return err
103129
}
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 {
106132
return errMissingLogFields
107133
}
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)
117148
}
149+
*l = declog
118150
return nil
119151
}
120152

121153
type Logs []*Log
122154

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.
126157
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+
}

core/vm/log_test.go

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,81 @@ package vm
1818

1919
import (
2020
"encoding/json"
21+
"reflect"
2122
"testing"
23+
24+
"github.com/davecgh/go-spew/spew"
25+
"github.com/ethereum/go-ethereum/common"
26+
"github.com/ethereum/go-ethereum/common/hexutil"
2227
)
2328

2429
var unmarshalLogTests = map[string]struct {
2530
input string
31+
want *Log
2632
wantError error
2733
}{
2834
"ok": {
29-
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x000000000000000000000000000000000000000000000001a055690d9db80000","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
35+
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x000000000000000000000000000000000000000000000001a055690d9db80000","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
36+
want: &Log{
37+
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
38+
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
39+
BlockNumber: 2019236,
40+
Data: hexutil.MustDecode("0x000000000000000000000000000000000000000000000001a055690d9db80000"),
41+
Index: 2,
42+
TxIndex: 3,
43+
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
44+
Topics: []common.Hash{
45+
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
46+
common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"),
47+
},
48+
},
3049
},
3150
"empty data": {
32-
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
51+
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
52+
want: &Log{
53+
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
54+
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
55+
BlockNumber: 2019236,
56+
Data: []byte{},
57+
Index: 2,
58+
TxIndex: 3,
59+
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
60+
Topics: []common.Hash{
61+
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
62+
common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"),
63+
},
64+
},
65+
},
66+
"missing block fields (pending logs)": {
67+
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","data":"0x","logIndex":"0x0","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
68+
want: &Log{
69+
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
70+
BlockHash: common.Hash{},
71+
BlockNumber: 0,
72+
Data: []byte{},
73+
Index: 0,
74+
TxIndex: 3,
75+
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
76+
Topics: []common.Hash{
77+
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
78+
},
79+
},
80+
},
81+
"Removed: true": {
82+
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3","removed":true}`,
83+
want: &Log{
84+
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
85+
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
86+
BlockNumber: 2019236,
87+
Data: []byte{},
88+
Index: 2,
89+
TxIndex: 3,
90+
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
91+
Topics: []common.Hash{
92+
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
93+
},
94+
Removed: true,
95+
},
3396
},
3497
"missing data": {
3598
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
@@ -38,10 +101,16 @@ var unmarshalLogTests = map[string]struct {
38101
}
39102

40103
func TestUnmarshalLog(t *testing.T) {
104+
dumper := spew.ConfigState{DisableMethods: true, Indent: " "}
41105
for name, test := range unmarshalLogTests {
42106
var log *Log
43107
err := json.Unmarshal([]byte(test.input), &log)
44108
checkError(t, name, err, test.wantError)
109+
if test.wantError == nil && err == nil {
110+
if !reflect.DeepEqual(log, test.want) {
111+
t.Errorf("test %q:\nGOT %sWANT %s", name, dumper.Sdump(log), dumper.Sdump(test.want))
112+
}
113+
}
45114
}
46115
}
47116

0 commit comments

Comments
 (0)