Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
6b0ddd14
Unverified
Commit
6b0ddd14
authored
Mar 27, 2019
by
Matthew Halpern
Committed by
Péter Szilágyi
Apr 15, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, eth, les, light: store transaction receipts without txHash and gasCost
parent
1528b791
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
552 additions
and
123 deletions
+552
-123
blockchain.go
core/blockchain.go
+15
-52
chain_makers.go
core/chain_makers.go
+9
-0
accessors_chain.go
core/rawdb/accessors_chain.go
+94
-18
accessors_chain_test.go
core/rawdb/accessors_chain_test.go
+201
-9
log.go
core/types/log.go
+3
-3
receipt.go
core/types/receipt.go
+81
-28
receipt_test.go
core/types/receipt_test.go
+133
-0
filter_test.go
eth/filters/filter_test.go
+5
-0
handler_test.go
les/handler_test.go
+1
-1
odr_test.go
light/odr_test.go
+1
-1
odr_util.go
light/odr_util.go
+9
-11
No files found.
core/blockchain.go
View file @
6b0ddd14
...
...
@@ -35,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -43,7 +42,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
lru
"github.com/hashicorp/golang-lru"
"github.com/hashicorp/golang-lru"
)
var
(
...
...
@@ -79,12 +78,19 @@ const (
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
//
// During the process of upgrading the database version from 3 to 4,
// the following incompatible database changes were added.
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
// * the `Bloom` field of receipt is deleted
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
BlockChainVersion
uint64
=
4
// Changelog:
//
// - Version 4
// The following incompatible database changes were added:
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
// * the `Bloom` field of receipt is deleted
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
// - Version 5
// The following incompatible database changes were added:
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are no longer stored for a receipt
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are computed by looking up the
// receipts' corresponding block
BlockChainVersion
uint64
=
5
)
// CacheConfig contains the configuration values for the trie caching/pruning
...
...
@@ -784,49 +790,6 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
}
}
// SetReceiptsData computes all the non-consensus fields of the receipts
func
SetReceiptsData
(
config
*
params
.
ChainConfig
,
block
*
types
.
Block
,
receipts
types
.
Receipts
)
error
{
signer
:=
types
.
MakeSigner
(
config
,
block
.
Number
())
transactions
,
logIndex
:=
block
.
Transactions
(),
uint
(
0
)
if
len
(
transactions
)
!=
len
(
receipts
)
{
return
errors
.
New
(
"transaction and receipt count mismatch"
)
}
for
j
:=
0
;
j
<
len
(
receipts
);
j
++
{
// The transaction hash can be retrieved from the transaction itself
receipts
[
j
]
.
TxHash
=
transactions
[
j
]
.
Hash
()
// block location fields
receipts
[
j
]
.
BlockHash
=
block
.
Hash
()
receipts
[
j
]
.
BlockNumber
=
block
.
Number
()
receipts
[
j
]
.
TransactionIndex
=
uint
(
j
)
// The contract address can be derived from the transaction itself
if
transactions
[
j
]
.
To
()
==
nil
{
// Deriving the signer is expensive, only do if it's actually needed
from
,
_
:=
types
.
Sender
(
signer
,
transactions
[
j
])
receipts
[
j
]
.
ContractAddress
=
crypto
.
CreateAddress
(
from
,
transactions
[
j
]
.
Nonce
())
}
// The used gas can be calculated based on previous receipts
if
j
==
0
{
receipts
[
j
]
.
GasUsed
=
receipts
[
j
]
.
CumulativeGasUsed
}
else
{
receipts
[
j
]
.
GasUsed
=
receipts
[
j
]
.
CumulativeGasUsed
-
receipts
[
j
-
1
]
.
CumulativeGasUsed
}
// The derived log fields can simply be set from the block and transaction
for
k
:=
0
;
k
<
len
(
receipts
[
j
]
.
Logs
);
k
++
{
receipts
[
j
]
.
Logs
[
k
]
.
BlockNumber
=
block
.
NumberU64
()
receipts
[
j
]
.
Logs
[
k
]
.
BlockHash
=
block
.
Hash
()
receipts
[
j
]
.
Logs
[
k
]
.
TxHash
=
receipts
[
j
]
.
TxHash
receipts
[
j
]
.
Logs
[
k
]
.
TxIndex
=
uint
(
j
)
receipts
[
j
]
.
Logs
[
k
]
.
Index
=
logIndex
logIndex
++
}
}
return
nil
}
// InsertReceiptChain attempts to complete an already existing header chain with
// transaction and receipt data.
func
(
bc
*
BlockChain
)
InsertReceiptChain
(
blockChain
types
.
Blocks
,
receiptChain
[]
types
.
Receipts
)
(
int
,
error
)
{
...
...
@@ -865,7 +828,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
continue
}
// Compute all the non-consensus fields of the receipts
if
err
:=
SetReceiptsData
(
bc
.
chainConfig
,
block
,
receipts
);
err
!=
nil
{
if
err
:=
rawdb
.
SetReceiptsData
(
bc
.
chainConfig
,
block
.
Hash
(),
block
.
Number
(),
block
.
Body
()
,
receipts
);
err
!=
nil
{
return
i
,
fmt
.
Errorf
(
"failed to set receipts data: %v"
,
err
)
}
// Write all the data out into the database
...
...
core/chain_makers.go
View file @
6b0ddd14
...
...
@@ -104,6 +104,15 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b
.
receipts
=
append
(
b
.
receipts
,
receipt
)
}
// AddUncheckedTx forcefully adds a transaction to the block without any
// validation.
//
// AddUncheckedTx will cause consensus failures when used during real
// chain processing. This is best used in conjunction with raw block insertion.
func
(
b
*
BlockGen
)
AddUncheckedTx
(
tx
*
types
.
Transaction
)
{
b
.
txs
=
append
(
b
.
txs
,
tx
)
}
// Number returns the block number of the block being generated.
func
(
b
*
BlockGen
)
Number
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
b
.
header
.
Number
)
...
...
core/rawdb/accessors_chain.go
View file @
6b0ddd14
...
...
@@ -19,12 +19,15 @@ package rawdb
import
(
"bytes"
"encoding/binary"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
...
...
@@ -299,39 +302,112 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
return
data
}
// ReadReceipts retrieves all the transaction receipts belonging to a block.
func
ReadReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
// ReadRawReceipts retrieves all the transaction receipts belonging to a block.
// The receipt metadata fields are not guaranteed to be populated, so they
// should not be used. Use ReadReceipts instead if the metadata is needed.
func
ReadRawReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
// Retrieve the flattened receipt slice
data
:=
ReadReceiptsRLP
(
db
,
hash
,
number
)
if
len
(
data
)
==
0
{
return
nil
}
// Convert the receipts from their storage form to their internal representation
storageReceipts
:=
[]
*
types
.
ReceiptForStorage
{}
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
storageReceipts
);
err
!=
nil
{
log
.
Error
(
"Invalid receipt array RLP"
,
"hash"
,
hash
,
"err"
,
err
)
return
nil
}
receipts
:=
make
(
types
.
Receipts
,
len
(
storageReceipts
))
logIndex
:=
uint
(
0
)
for
i
,
receipt
:=
range
storageReceipts
{
// Assemble deriving fields for log.
for
_
,
log
:=
range
receipt
.
Logs
{
log
.
TxHash
=
receipt
.
TxHash
log
.
BlockHash
=
hash
log
.
BlockNumber
=
number
log
.
TxIndex
=
uint
(
i
)
log
.
Index
=
logIndex
logIndex
+=
1
}
receipts
[
i
]
=
(
*
types
.
Receipt
)(
receipt
)
receipts
[
i
]
.
BlockHash
=
hash
receipts
[
i
]
.
BlockNumber
=
big
.
NewInt
(
0
)
.
SetUint64
(
number
)
receipts
[
i
]
.
TransactionIndex
=
uint
(
i
)
var
receipts
types
.
Receipts
for
_
,
storageReceipt
:=
range
storageReceipts
{
receipt
:=
(
*
types
.
Receipt
)(
storageReceipt
)
receipts
=
append
(
receipts
,
receipt
)
}
return
receipts
}
// ReadReceipts retrieves all the transaction receipts belonging to a block, including
// its correspoinding metadata fields. If it is unable to populate these metadata
// fields then nil is returned.
//
// The current implementation populates these metadata fields by reading the receipts'
// corresponding block body, so if the block body is not found it will return nil even
// if the receipt itself is stored.
func
ReadReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
receipts
:=
ReadRawReceipts
(
db
,
hash
,
number
)
if
receipts
==
nil
{
return
receipts
}
// Retrieve the block body to populate missing fields for receipts and logs
body
:=
ReadBody
(
db
,
hash
,
number
)
if
body
==
nil
{
log
.
Error
(
"Missing body but have receipt"
,
"hash"
,
hash
,
"number"
,
number
)
return
nil
}
genesisHash
:=
ReadCanonicalHash
(
db
,
0
)
if
genesisHash
==
(
common
.
Hash
{})
{
log
.
Error
(
"Missing genesis hash"
)
return
nil
}
config
:=
ReadChainConfig
(
db
,
genesisHash
)
if
config
==
nil
{
log
.
Error
(
"Missing chain config "
,
"hash"
,
hash
)
return
nil
}
SetReceiptsData
(
config
,
hash
,
big
.
NewInt
(
int64
(
number
)),
body
,
receipts
)
return
receipts
}
// SetReceiptsData computes all the non-consensus fields of the receipts
func
SetReceiptsData
(
config
*
params
.
ChainConfig
,
blockHash
common
.
Hash
,
blockNumber
*
big
.
Int
,
body
*
types
.
Body
,
receipts
types
.
Receipts
)
error
{
signer
:=
types
.
MakeSigner
(
config
,
blockNumber
)
transactions
,
logIndex
:=
body
.
Transactions
,
uint
(
0
)
if
len
(
transactions
)
!=
len
(
receipts
)
{
return
errors
.
New
(
"transaction and receipt count mismatch"
)
}
for
j
:=
0
;
j
<
len
(
receipts
);
j
++
{
// The transaction hash can be retrieved from the transaction itself
receipts
[
j
]
.
TxHash
=
transactions
[
j
]
.
Hash
()
// block location fields
receipts
[
j
]
.
BlockHash
=
blockHash
receipts
[
j
]
.
BlockNumber
=
blockNumber
receipts
[
j
]
.
TransactionIndex
=
uint
(
j
)
// The contract address can be derived from the transaction itself
if
transactions
[
j
]
.
To
()
==
nil
{
// Deriving the signer is expensive, only do if it's actually needed
from
,
_
:=
types
.
Sender
(
signer
,
transactions
[
j
])
receipts
[
j
]
.
ContractAddress
=
crypto
.
CreateAddress
(
from
,
transactions
[
j
]
.
Nonce
())
}
// The used gas can be calculated based on previous receipts
if
j
==
0
{
receipts
[
j
]
.
GasUsed
=
receipts
[
j
]
.
CumulativeGasUsed
}
else
{
receipts
[
j
]
.
GasUsed
=
receipts
[
j
]
.
CumulativeGasUsed
-
receipts
[
j
-
1
]
.
CumulativeGasUsed
}
// The derived log fields can simply be set from the block and transaction
for
k
:=
0
;
k
<
len
(
receipts
[
j
]
.
Logs
);
k
++
{
receipts
[
j
]
.
Logs
[
k
]
.
BlockNumber
=
blockNumber
.
Uint64
()
receipts
[
j
]
.
Logs
[
k
]
.
BlockHash
=
blockHash
receipts
[
j
]
.
Logs
[
k
]
.
TxHash
=
receipts
[
j
]
.
TxHash
receipts
[
j
]
.
Logs
[
k
]
.
TxIndex
=
uint
(
j
)
receipts
[
j
]
.
Logs
[
k
]
.
Index
=
logIndex
logIndex
++
}
}
return
nil
}
// WriteReceipts stores all the transaction receipts belonging to a block.
func
WriteReceipts
(
db
ethdb
.
Writer
,
hash
common
.
Hash
,
number
uint64
,
receipts
types
.
Receipts
)
{
// Convert the receipts into their storage form and serialize them
...
...
core/rawdb/accessors_chain_test.go
View file @
6b0ddd14
...
...
@@ -18,6 +18,11 @@ package rawdb
import
(
"bytes"
"encoding/hex"
"fmt"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"math/big"
"testing"
...
...
@@ -267,6 +272,11 @@ func TestHeadStorage(t *testing.T) {
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
db
:=
NewMemoryDatabase
()
tx1
:=
types
.
NewTransaction
(
1
,
common
.
HexToAddress
(
"0x1"
),
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
)
tx2
:=
types
.
NewTransaction
(
2
,
common
.
HexToAddress
(
"0x2"
),
big
.
NewInt
(
2
),
2
,
big
.
NewInt
(
2
),
nil
)
// Include block needed to read metadata.
body
:=
&
types
.
Body
{
Transactions
:
types
.
Transactions
{
tx1
,
tx2
}}
receipt1
:=
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
...
...
@@ -274,7 +284,7 @@ func TestBlockReceiptStorage(t *testing.T) {
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x11
,
0x11
}
),
TxHash
:
tx1
.
Hash
(
),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
111111
,
}
...
...
@@ -286,7 +296,7 @@ func TestBlockReceiptStorage(t *testing.T) {
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x22
,
0x22
}
),
TxHash
:
tx2
.
Hash
(
),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
222222
,
}
...
...
@@ -298,23 +308,205 @@ func TestBlockReceiptStorage(t *testing.T) {
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"non existent receipts returned: %v"
,
rs
)
}
// Insert the body that corresponds to the receipts.
WriteBody
(
db
,
hash
,
0
,
body
)
// Insert the receipt slice into the database and check presence
WriteReceipts
(
db
,
hash
,
0
,
receipts
)
// Insert canonical hash that the chain configuration will be mapped to.
WriteCanonicalHash
(
db
,
hash
,
0
)
// Insert the chain configuration.
WriteChainConfig
(
db
,
hash
,
params
.
MainnetChainConfig
)
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
==
0
{
t
.
Fatalf
(
"no receipts returned"
)
}
else
{
for
i
:=
0
;
i
<
len
(
receipts
);
i
++
{
rlpHave
,
_
:=
rlp
.
EncodeToBytes
(
rs
[
i
])
rlpWant
,
_
:=
rlp
.
EncodeToBytes
(
receipts
[
i
])
if
!
bytes
.
Equal
(
rlpHave
,
rlpWant
)
{
t
.
Fatalf
(
"receipt #%d: receipt mismatch: have %v, want %v"
,
i
,
rs
[
i
],
receipts
[
i
])
}
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
err
.
Error
())
}
}
DeleteBody
(
db
,
hash
,
0
)
// Check that receipts are no longer returned when metadata cannot be recomputed.
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
rs
!=
nil
{
t
.
Fatalf
(
"receipts returned when body was deleted: %v"
,
rs
)
}
// Check that receipts without metadata can be returned when specifically
rs
:=
ReadRawReceipts
(
db
,
hash
,
0
)
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
err
.
Error
())
}
// Re-insert the body that corresponds to the receipts.
WriteBody
(
db
,
hash
,
0
,
body
)
// Delete the receipt slice and check purge
DeleteReceipts
(
db
,
hash
,
0
)
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"deleted receipts returned: %v"
,
rs
)
}
}
func
checkReceiptsRLP
(
have
,
want
types
.
Receipts
)
error
{
if
len
(
have
)
!=
len
(
want
)
{
return
fmt
.
Errorf
(
"receipts sizes mismatch: have %d, want %d"
,
len
(
have
),
len
(
want
))
}
for
i
:=
0
;
i
<
len
(
want
);
i
++
{
rlpHave
,
err
:=
rlp
.
EncodeToBytes
(
have
[
i
])
if
err
!=
nil
{
return
err
}
rlpWant
,
err
:=
rlp
.
EncodeToBytes
(
want
[
i
])
if
err
!=
nil
{
return
err
}
if
!
bytes
.
Equal
(
rlpHave
,
rlpWant
)
{
return
fmt
.
Errorf
(
"receipt #%d: receipt mismatch: have %s, want %s"
,
i
,
hex
.
EncodeToString
(
rlpHave
),
hex
.
EncodeToString
(
rlpWant
))
}
}
return
nil
}
// Tests that receipts associated with a single block can be stored and retrieved.
func
TestSetReceiptsData
(
t
*
testing
.
T
)
{
tx0
:=
types
.
NewContractCreation
(
1
,
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
)
tx1
:=
types
.
NewTransaction
(
2
,
common
.
HexToAddress
(
"0x2"
),
big
.
NewInt
(
2
),
2
,
big
.
NewInt
(
2
),
nil
)
txs
:=
types
.
Transactions
{
tx0
,
tx1
}
// Include block needed to read metadata.
body
:=
&
types
.
Body
{
Transactions
:
txs
}
receipt1
:=
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
Logs
:
[]
*
types
.
Log
{
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
tx0
.
Hash
(),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
1
,
}
receipt2
:=
&
types
.
Receipt
{
PostState
:
common
.
Hash
{
2
}
.
Bytes
(),
CumulativeGasUsed
:
3
,
Logs
:
[]
*
types
.
Log
{
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
TxHash
:
tx1
.
Hash
(),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
2
,
}
receipt2
.
Bloom
=
types
.
CreateBloom
(
types
.
Receipts
{
receipt2
})
receipts
:=
[]
*
types
.
Receipt
{
receipt1
,
receipt2
}
blockNumber
:=
big
.
NewInt
(
1
)
blockHash
:=
common
.
BytesToHash
([]
byte
{
0x03
,
0x14
})
clearComputedFieldsOnReceipts
(
t
,
receipts
)
if
err
:=
SetReceiptsData
(
params
.
MainnetChainConfig
,
blockHash
,
blockNumber
,
body
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
"SetReceiptsData(...) = %v, want <nil>"
,
err
)
}
signer
:=
types
.
MakeSigner
(
params
.
MainnetChainConfig
,
blockNumber
)
logIndex
:=
uint
(
0
)
for
i
:=
range
receipts
{
if
receipts
[
i
]
.
TxHash
!=
txs
[
i
]
.
Hash
()
{
t
.
Errorf
(
"receipts[%d].TxHash = %s, want %s"
,
i
,
receipts
[
i
]
.
TxHash
.
String
(),
txs
[
i
]
.
Hash
()
.
String
())
}
if
receipts
[
i
]
.
BlockHash
!=
blockHash
{
t
.
Errorf
(
"receipts[%d].BlockHash = %s, want %s"
,
i
,
receipts
[
i
]
.
BlockHash
.
String
(),
blockHash
.
String
())
}
if
receipts
[
i
]
.
BlockNumber
.
Cmp
(
blockNumber
)
!=
0
{
t
.
Errorf
(
"receipts[%c].BlockNumber = %s, want %s"
,
i
,
receipts
[
i
]
.
BlockNumber
.
String
(),
blockNumber
.
String
())
}
if
receipts
[
i
]
.
TransactionIndex
!=
uint
(
i
)
{
t
.
Errorf
(
"receipts[%d].TransactionIndex = %d, want %d"
,
i
,
receipts
[
i
]
.
TransactionIndex
,
i
)
}
if
receipts
[
i
]
.
GasUsed
!=
txs
[
i
]
.
Gas
()
{
t
.
Errorf
(
"receipts[%d].GasUsed = %d, want %d"
,
i
,
receipts
[
i
]
.
GasUsed
,
txs
[
i
]
.
Gas
())
}
if
txs
[
i
]
.
To
()
!=
nil
&&
receipts
[
i
]
.
ContractAddress
!=
(
common
.
Address
{})
{
t
.
Errorf
(
"receipts[%d].ContractAddress = %s, want %s"
,
i
,
receipts
[
i
]
.
ContractAddress
,
(
common
.
Address
{})
.
String
())
}
from
,
_
:=
types
.
Sender
(
signer
,
txs
[
i
])
contractAddress
:=
crypto
.
CreateAddress
(
from
,
txs
[
i
]
.
Nonce
())
if
txs
[
i
]
.
To
()
==
nil
&&
receipts
[
i
]
.
ContractAddress
!=
contractAddress
{
t
.
Errorf
(
"receipts[%d].ContractAddress = %s, want %s"
,
i
,
receipts
[
i
]
.
ContractAddress
.
String
(),
contractAddress
.
String
())
}
for
j
:=
range
receipts
[
i
]
.
Logs
{
if
receipts
[
i
]
.
Logs
[
j
]
.
BlockNumber
!=
blockNumber
.
Uint64
()
{
t
.
Errorf
(
"receipts[%d].Logs[%d].BlockNumber = %d, want %d"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
BlockNumber
,
blockNumber
.
Uint64
())
}
if
receipts
[
i
]
.
Logs
[
j
]
.
BlockHash
!=
blockHash
{
t
.
Errorf
(
"receipts[%d].Logs[%d].BlockHash = %s, want %s"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
BlockHash
.
String
(),
blockHash
.
String
())
}
if
receipts
[
i
]
.
Logs
[
j
]
.
TxHash
!=
txs
[
i
]
.
Hash
()
{
t
.
Errorf
(
"receipts[%d].Logs[%d].TxHash = %s, want %s"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
TxHash
.
String
(),
txs
[
i
]
.
Hash
()
.
String
())
}
if
receipts
[
i
]
.
Logs
[
j
]
.
TxHash
!=
txs
[
i
]
.
Hash
()
{
t
.
Errorf
(
"receipts[%d].Logs[%d].TxHash = %s, want %s"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
TxHash
.
String
(),
txs
[
i
]
.
Hash
()
.
String
())
}
if
receipts
[
i
]
.
Logs
[
j
]
.
TxIndex
!=
uint
(
i
)
{
t
.
Errorf
(
"receipts[%d].Logs[%d].TransactionIndex = %d, want %d"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
TxIndex
,
i
)
}
if
receipts
[
i
]
.
Logs
[
j
]
.
Index
!=
logIndex
{
t
.
Errorf
(
"receipts[%d].Logs[%d].Index = %d, want %d"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
Index
,
logIndex
)
}
logIndex
++
}
}
}
func
clearComputedFieldsOnReceipts
(
t
*
testing
.
T
,
receipts
types
.
Receipts
)
{
t
.
Helper
()
for
_
,
receipt
:=
range
receipts
{
clearComputedFieldsOnReceipt
(
t
,
receipt
)
}
}
func
clearComputedFieldsOnReceipt
(
t
*
testing
.
T
,
receipt
*
types
.
Receipt
)
{
t
.
Helper
()
receipt
.
TxHash
=
common
.
Hash
{}
receipt
.
BlockHash
=
common
.
Hash
{}
receipt
.
BlockNumber
=
big
.
NewInt
(
math
.
MaxUint32
)
receipt
.
TransactionIndex
=
math
.
MaxUint32
receipt
.
ContractAddress
=
common
.
Address
{}
receipt
.
GasUsed
=
0
clearComputedFieldsOnLogs
(
t
,
receipt
.
Logs
)
}
func
clearComputedFieldsOnLogs
(
t
*
testing
.
T
,
logs
[]
*
types
.
Log
)
{
t
.
Helper
()
for
_
,
log
:=
range
logs
{
clearComputedFieldsOnLog
(
t
,
log
)
}
}
func
clearComputedFieldsOnLog
(
t
*
testing
.
T
,
log
*
types
.
Log
)
{
t
.
Helper
()
log
.
BlockNumber
=
math
.
MaxUint32
log
.
BlockHash
=
common
.
Hash
{}
log
.
TxHash
=
common
.
Hash
{}
log
.
TxIndex
=
math
.
MaxUint32
log
.
Index
=
math
.
MaxUint32
}
core/types/log.go
View file @
6b0ddd14
...
...
@@ -71,8 +71,8 @@ type rlpLog struct {
// rlpStorageLog is the storage encoding of a log.
type
rlpStorageLog
rlpLog
//
L
egacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
type
L
egacyRlpStorageLog
struct
{
//
l
egacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
type
l
egacyRlpStorageLog
struct
{
Address
common
.
Address
Topics
[]
common
.
Hash
Data
[]
byte
...
...
@@ -129,7 +129,7 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
}
}
else
{
// Try to decode log with previous definition.
var
dec
L
egacyRlpStorageLog
var
dec
l
egacyRlpStorageLog
err
=
rlp
.
DecodeBytes
(
blob
,
&
dec
)
if
err
==
nil
{
*
l
=
LogForStorage
{
...
...
core/types/receipt.go
View file @
6b0ddd14
...
...
@@ -82,8 +82,15 @@ type receiptRLP struct {
Logs
[]
*
Log
}
// receiptStorageRLP is the storage encoding of a receipt.
type
receiptStorageRLP
struct
{
// storedReceiptRLP is the storage encoding of a receipt.
type
storedReceiptRLP
struct
{
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
Logs
[]
*
LogForStorage
}
// v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4.
type
v4StoredReceiptRLP
struct
{
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
TxHash
common
.
Hash
...
...
@@ -92,8 +99,8 @@ type receiptStorageRLP struct {
GasUsed
uint64
}
//
LegacyReceiptStorageRLP is the previous
storage encoding of a receipt including some unnecessary fields.
type
LegacyReceiptStorage
RLP
struct
{
//
legacyStoredReceiptRLP is the original
storage encoding of a receipt including some unnecessary fields.
type
legacyStoredReceipt
RLP
struct
{
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
Bloom
Bloom
...
...
@@ -177,13 +184,10 @@ type ReceiptForStorage Receipt
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
// into an RLP stream.
func
(
r
*
ReceiptForStorage
)
EncodeRLP
(
w
io
.
Writer
)
error
{
enc
:=
&
receiptStorage
RLP
{
enc
:=
&
storedReceipt
RLP
{
PostStateOrStatus
:
(
*
Receipt
)(
r
)
.
statusEncoding
(),
CumulativeGasUsed
:
r
.
CumulativeGasUsed
,
TxHash
:
r
.
TxHash
,
ContractAddress
:
r
.
ContractAddress
,
Logs
:
make
([]
*
LogForStorage
,
len
(
r
.
Logs
)),
GasUsed
:
r
.
GasUsed
,
}
for
i
,
log
:=
range
r
.
Logs
{
enc
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
...
...
@@ -198,32 +202,81 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
if
err
!=
nil
{
return
err
}
var
dec
receiptStorageRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
dec
);
err
!=
nil
{
var
sdec
LegacyReceiptStorageRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
sdec
);
err
!=
nil
{
return
err
}
dec
.
PostStateOrStatus
=
common
.
CopyBytes
(
sdec
.
PostStateOrStatus
)
dec
.
CumulativeGasUsed
=
sdec
.
CumulativeGasUsed
dec
.
TxHash
=
sdec
.
TxHash
dec
.
ContractAddress
=
sdec
.
ContractAddress
dec
.
Logs
=
sdec
.
Logs
dec
.
GasUsed
=
sdec
.
GasUsed
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
dec
.
PostStateOrStatus
);
err
!=
nil
{
if
err
:=
decodeStoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
return
nil
}
if
err
:=
decodeV4StoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
return
nil
}
return
decodeLegacyStoredReceiptRLP
(
r
,
blob
)
}
func
decodeStoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
var
stored
storedReceiptRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
}
// Assign the consensus fields
r
.
CumulativeGasUsed
=
dec
.
CumulativeGasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
dec
.
Logs
))
for
i
,
log
:=
range
dec
.
Logs
{
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
for
i
,
log
:=
range
stored
.
Logs
{
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
}
r
.
Bloom
=
CreateBloom
(
Receipts
{(
*
Receipt
)(
r
)})
return
nil
}
func
decodeV4StoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
var
stored
v4StoredReceiptRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
}
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
TxHash
=
stored
.
TxHash
r
.
ContractAddress
=
stored
.
ContractAddress
r
.
GasUsed
=
stored
.
GasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
for
i
,
log
:=
range
stored
.
Logs
{
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
}
r
.
Bloom
=
CreateBloom
(
Receipts
{(
*
Receipt
)(
r
)})
// Assign the implementation fields
r
.
TxHash
,
r
.
ContractAddress
,
r
.
GasUsed
=
dec
.
TxHash
,
dec
.
ContractAddress
,
dec
.
GasUsed
return
nil
}
func
decodeLegacyStoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
var
stored
legacyStoredReceiptRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
}
r
.
CumulativeGasUsed
=
stored
.
GasUsed
r
.
Bloom
=
stored
.
Bloom
r
.
TxHash
=
stored
.
TxHash
r
.
ContractAddress
=
stored
.
ContractAddress
r
.
GasUsed
=
stored
.
GasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
for
i
,
log
:=
range
stored
.
Logs
{
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
}
return
nil
}
...
...
core/types/receipt_test.go
0 → 100644
View file @
6b0ddd14
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
types
import
(
"bytes"
"encoding/hex"
"encoding/json"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)
func
TestLegacyReceiptDecoding
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
encode
func
(
*
Receipt
)
([]
byte
,
error
)
}{
{
"StoredReceiptRLP"
,
encodeAsStoredReceiptRLP
,
},
{
"V4StoredReceiptRLP"
,
encodeAsV4StoredReceiptRLP
,
},
{
"LegacyStoredReceiptRLP"
,
encodeAsLegacyStoredReceiptRLP
,
},
}
tx
:=
NewTransaction
(
1
,
common
.
HexToAddress
(
"0x1"
),
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
)
receipt
:=
&
Receipt
{
Status
:
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
Logs
:
[]
*
Log
{
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
tx
.
Hash
(),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
111111
,
}
receipt
.
Bloom
=
CreateBloom
(
Receipts
{
receipt
})
want
,
err
:=
json
.
Marshal
(
receipt
)
if
err
!=
nil
{
t
.
Fatalf
(
"Error encoding reference receipt to JSON: %v"
,
err
)
}
for
_
,
tc
:=
range
tests
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
enc
,
err
:=
tc
.
encode
(
receipt
)
if
err
!=
nil
{
t
.
Fatalf
(
"Error encoding receipt: %v"
,
err
)
}
var
dec
ReceiptForStorage
if
err
:=
rlp
.
DecodeBytes
(
enc
,
&
dec
);
err
!=
nil
{
t
.
Fatalf
(
"Error decoding RLP receipt: %v"
,
err
)
}
have
,
err
:=
rlp
.
EncodeToBytes
((
*
Receipt
)(
receipt
))
if
err
!=
nil
{
t
.
Fatalf
(
"Error encoding receipt: %v"
,
err
)
}
if
!
bytes
.
Equal
(
have
,
want
)
{
t
.
Fatalf
(
"receipt mismatch: have %s, want %s"
,
hex
.
EncodeToString
(
have
),
hex
.
EncodeToString
(
want
))
}
})
}
}
func
encodeAsStoredReceiptRLP
(
want
*
Receipt
)
([]
byte
,
error
)
{
stored
:=
&
storedReceiptRLP
{
PostStateOrStatus
:
want
.
statusEncoding
(),
CumulativeGasUsed
:
want
.
CumulativeGasUsed
,
Logs
:
make
([]
*
LogForStorage
,
len
(
want
.
Logs
)),
}
for
i
,
log
:=
range
want
.
Logs
{
stored
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
}
return
rlp
.
EncodeToBytes
(
stored
)
}
func
encodeAsV4StoredReceiptRLP
(
want
*
Receipt
)
([]
byte
,
error
)
{
stored
:=
&
v4StoredReceiptRLP
{
PostStateOrStatus
:
want
.
statusEncoding
(),
CumulativeGasUsed
:
want
.
CumulativeGasUsed
,
TxHash
:
want
.
TxHash
,
ContractAddress
:
want
.
ContractAddress
,
Logs
:
make
([]
*
LogForStorage
,
len
(
want
.
Logs
)),
GasUsed
:
want
.
GasUsed
,
}
for
i
,
log
:=
range
want
.
Logs
{
stored
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
}
return
rlp
.
EncodeToBytes
(
stored
)
}
func
encodeAsLegacyStoredReceiptRLP
(
want
*
Receipt
)
([]
byte
,
error
)
{
stored
:=
&
legacyStoredReceiptRLP
{
PostStateOrStatus
:
want
.
statusEncoding
(),
CumulativeGasUsed
:
want
.
CumulativeGasUsed
,
Bloom
:
want
.
Bloom
,
TxHash
:
want
.
TxHash
,
ContractAddress
:
want
.
ContractAddress
,
Logs
:
make
([]
*
LogForStorage
,
len
(
want
.
Logs
)),
GasUsed
:
want
.
GasUsed
,
}
for
i
,
log
:=
range
want
.
Logs
{
stored
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
}
return
rlp
.
EncodeToBytes
(
stored
)
}
eth/filters/filter_test.go
View file @
6b0ddd14
...
...
@@ -138,6 +138,7 @@ func TestFilters(t *testing.T) {
},
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
1
,
common
.
HexToAddress
(
"0x1"
),
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
))
case
2
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
...
...
@@ -147,6 +148,8 @@ func TestFilters(t *testing.T) {
},
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
2
,
common
.
HexToAddress
(
"0x2"
),
big
.
NewInt
(
2
),
2
,
big
.
NewInt
(
2
),
nil
))
case
998
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
...
...
@@ -156,6 +159,7 @@ func TestFilters(t *testing.T) {
},
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
998
,
common
.
HexToAddress
(
"0x998"
),
big
.
NewInt
(
998
),
998
,
big
.
NewInt
(
998
),
nil
))
case
999
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
...
...
@@ -165,6 +169,7 @@ func TestFilters(t *testing.T) {
},
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
999
,
common
.
HexToAddress
(
"0x999"
),
big
.
NewInt
(
999
),
999
,
big
.
NewInt
(
999
),
nil
))
}
})
for
i
,
block
:=
range
chain
{
...
...
les/handler_test.go
View file @
6b0ddd14
...
...
@@ -292,7 +292,7 @@ func testGetReceipt(t *testing.T, protocol int) {
block
:=
bc
.
GetBlockByNumber
(
i
)
hashes
=
append
(
hashes
,
block
.
Hash
())
receipts
=
append
(
receipts
,
rawdb
.
ReadReceipts
(
server
.
db
,
block
.
Hash
(),
block
.
NumberU64
()))
receipts
=
append
(
receipts
,
rawdb
.
ReadR
awR
eceipts
(
server
.
db
,
block
.
Hash
(),
block
.
NumberU64
()))
}
// Send the hash request and verify the response
cost
:=
server
.
tPeer
.
GetRequestCost
(
GetReceiptsMsg
,
len
(
hashes
))
...
...
light/odr_test.go
View file @
6b0ddd14
...
...
@@ -79,7 +79,7 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
case
*
ReceiptsRequest
:
number
:=
rawdb
.
ReadHeaderNumber
(
odr
.
sdb
,
req
.
Hash
)
if
number
!=
nil
{
req
.
Receipts
=
rawdb
.
ReadReceipts
(
odr
.
sdb
,
req
.
Hash
,
*
number
)
req
.
Receipts
=
rawdb
.
ReadR
awR
eceipts
(
odr
.
sdb
,
req
.
Hash
,
*
number
)
}
case
*
TrieRequest
:
t
,
_
:=
trie
.
New
(
req
.
Id
.
Root
,
trie
.
NewDatabase
(
odr
.
sdb
))
...
...
light/odr_util.go
View file @
6b0ddd14
...
...
@@ -21,7 +21,6 @@ import (
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -127,8 +126,8 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint
// GetBlockReceipts retrieves the receipts generated by the transactions included
// in a block given by its hash.
func
GetBlockReceipts
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
(
types
.
Receipts
,
error
)
{
//
Retrieve the potentially incomplete receipts from disk or network
receipts
:=
rawdb
.
ReadReceipts
(
odr
.
Database
(),
hash
,
number
)
//
Assume receipts are already stored locally and attempt to retrieve.
receipts
:=
rawdb
.
ReadR
awR
eceipts
(
odr
.
Database
(),
hash
,
number
)
if
receipts
==
nil
{
r
:=
&
ReceiptsRequest
{
Hash
:
hash
,
Number
:
number
}
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
...
...
@@ -136,6 +135,7 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
}
receipts
=
r
.
Receipts
}
// If the receipts are incomplete, fill the derived fields
if
len
(
receipts
)
>
0
&&
receipts
[
0
]
.
TxHash
==
(
common
.
Hash
{})
{
block
,
err
:=
GetBlock
(
ctx
,
odr
,
hash
,
number
)
...
...
@@ -145,11 +145,12 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
genesis
:=
rawdb
.
ReadCanonicalHash
(
odr
.
Database
(),
0
)
config
:=
rawdb
.
ReadChainConfig
(
odr
.
Database
(),
genesis
)
if
err
:=
core
.
SetReceiptsData
(
config
,
block
,
receipts
);
err
!=
nil
{
if
err
:=
rawdb
.
SetReceiptsData
(
config
,
block
.
Hash
(),
block
.
Number
(),
block
.
Body
()
,
receipts
);
err
!=
nil
{
return
nil
,
err
}
rawdb
.
WriteReceipts
(
odr
.
Database
(),
hash
,
number
,
receipts
)
}
return
receipts
,
nil
}
...
...
@@ -157,14 +158,11 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
// block given by its hash.
func
GetBlockLogs
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
([][]
*
types
.
Log
,
error
)
{
// Retrieve the potentially incomplete receipts from disk or network
receipts
:=
rawdb
.
ReadReceipts
(
odr
.
Database
(),
hash
,
number
)
if
receipts
==
nil
{
r
:=
&
ReceiptsRequest
{
Hash
:
hash
,
Number
:
number
}
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
return
nil
,
err
}
receipts
=
r
.
Receipts
receipts
,
err
:=
GetBlockReceipts
(
ctx
,
odr
,
hash
,
number
)
if
err
!=
nil
{
return
nil
,
err
}
// Return the logs without deriving any computed fields on the receipts
logs
:=
make
([][]
*
types
.
Log
,
len
(
receipts
))
for
i
,
receipt
:=
range
receipts
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment