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
7221cb14
Unverified
Commit
7221cb14
authored
Apr 15, 2019
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, eth, les, light: scope receipt functionality a bit cleaner
parent
6b0ddd14
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
250 additions
and
287 deletions
+250
-287
simulated.go
accounts/abi/bind/backends/simulated.go
+3
-3
bench_test.go
core/bench_test.go
+1
-1
blockchain.go
core/blockchain.go
+4
-4
blockchain_test.go
core/blockchain_test.go
+4
-4
accessors_chain.go
core/rawdb/accessors_chain.go
+8
-69
accessors_chain_test.go
core/rawdb/accessors_chain_test.go
+15
-167
accessors_indexes.go
core/rawdb/accessors_indexes.go
+5
-2
block_test.go
core/types/block_test.go
+0
-5
receipt.go
core/types/receipt.go
+56
-16
receipt_test.go
core/types/receipt_test.go
+140
-4
fakepeer.go
eth/downloader/fakepeer.go
+1
-1
filter_system_test.go
eth/filters/filter_system_test.go
+2
-2
handler.go
les/handler.go
+1
-1
odr_test.go
les/odr_test.go
+8
-3
odr_test.go
light/odr_test.go
+1
-1
odr_util.go
light/odr_util.go
+1
-4
No files found.
accounts/abi/bind/backends/simulated.go
View file @
7221cb14
...
@@ -160,7 +160,7 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
...
@@ -160,7 +160,7 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
// TransactionReceipt returns the receipt of a transaction.
// TransactionReceipt returns the receipt of a transaction.
func
(
b
*
SimulatedBackend
)
TransactionReceipt
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Receipt
,
error
)
{
func
(
b
*
SimulatedBackend
)
TransactionReceipt
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Receipt
,
error
)
{
receipt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
b
.
database
,
txHash
)
receipt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
b
.
database
,
txHash
,
b
.
config
)
return
receipt
,
nil
return
receipt
,
nil
}
}
...
@@ -464,7 +464,7 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
...
@@ -464,7 +464,7 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
if
number
==
nil
{
if
number
==
nil
{
return
nil
,
nil
return
nil
,
nil
}
}
return
rawdb
.
ReadReceipts
(
fb
.
db
,
hash
,
*
number
),
nil
return
rawdb
.
ReadReceipts
(
fb
.
db
,
hash
,
*
number
,
fb
.
bc
.
Config
()
),
nil
}
}
func
(
fb
*
filterBackend
)
GetLogs
(
ctx
context
.
Context
,
hash
common
.
Hash
)
([][]
*
types
.
Log
,
error
)
{
func
(
fb
*
filterBackend
)
GetLogs
(
ctx
context
.
Context
,
hash
common
.
Hash
)
([][]
*
types
.
Log
,
error
)
{
...
@@ -472,7 +472,7 @@ func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*ty
...
@@ -472,7 +472,7 @@ func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*ty
if
number
==
nil
{
if
number
==
nil
{
return
nil
,
nil
return
nil
,
nil
}
}
receipts
:=
rawdb
.
ReadReceipts
(
fb
.
db
,
hash
,
*
number
)
receipts
:=
rawdb
.
ReadReceipts
(
fb
.
db
,
hash
,
*
number
,
fb
.
bc
.
Config
()
)
if
receipts
==
nil
{
if
receipts
==
nil
{
return
nil
,
nil
return
nil
,
nil
}
}
...
...
core/bench_test.go
View file @
7221cb14
...
@@ -297,7 +297,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
...
@@ -297,7 +297,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if
full
{
if
full
{
hash
:=
header
.
Hash
()
hash
:=
header
.
Hash
()
rawdb
.
ReadBody
(
db
,
hash
,
n
)
rawdb
.
ReadBody
(
db
,
hash
,
n
)
rawdb
.
ReadReceipts
(
db
,
hash
,
n
)
rawdb
.
ReadReceipts
(
db
,
hash
,
n
,
chain
.
Config
()
)
}
}
}
}
chain
.
Stop
()
chain
.
Stop
()
...
...
core/blockchain.go
View file @
7221cb14
...
@@ -653,7 +653,7 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
...
@@ -653,7 +653,7 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
if
number
==
nil
{
if
number
==
nil
{
return
nil
return
nil
}
}
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
)
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
,
bc
.
chainConfig
)
if
receipts
==
nil
{
if
receipts
==
nil
{
return
nil
return
nil
}
}
...
@@ -828,8 +828,8 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
...
@@ -828,8 +828,8 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
continue
continue
}
}
// Compute all the non-consensus fields of the receipts
// Compute all the non-consensus fields of the receipts
if
err
:=
r
awdb
.
SetReceiptsData
(
bc
.
chainConfig
,
block
.
Hash
(),
block
.
Number
(),
block
.
Body
(),
receipts
);
err
!=
nil
{
if
err
:=
r
eceipts
.
DeriveFields
(
bc
.
chainConfig
,
block
.
Hash
(),
block
.
NumberU64
(),
block
.
Transactions
()
);
err
!=
nil
{
return
i
,
fmt
.
Errorf
(
"failed to
set
receipts data: %v"
,
err
)
return
i
,
fmt
.
Errorf
(
"failed to
derive
receipts data: %v"
,
err
)
}
}
// Write all the data out into the database
// Write all the data out into the database
rawdb
.
WriteBody
(
batch
,
block
.
Hash
(),
block
.
NumberU64
(),
block
.
Body
())
rawdb
.
WriteBody
(
batch
,
block
.
Hash
(),
block
.
NumberU64
(),
block
.
Body
())
...
@@ -1451,7 +1451,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
...
@@ -1451,7 +1451,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
if
number
==
nil
{
if
number
==
nil
{
return
return
}
}
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
)
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
,
bc
.
chainConfig
)
for
_
,
receipt
:=
range
receipts
{
for
_
,
receipt
:=
range
receipts
{
for
_
,
log
:=
range
receipt
.
Logs
{
for
_
,
log
:=
range
receipt
.
Logs
{
l
:=
*
log
l
:=
*
log
...
...
core/blockchain_test.go
View file @
7221cb14
...
@@ -658,7 +658,7 @@ func TestFastVsFullChains(t *testing.T) {
...
@@ -658,7 +658,7 @@ func TestFastVsFullChains(t *testing.T) {
}
else
if
types
.
CalcUncleHash
(
fblock
.
Uncles
())
!=
types
.
CalcUncleHash
(
ablock
.
Uncles
())
{
}
else
if
types
.
CalcUncleHash
(
fblock
.
Uncles
())
!=
types
.
CalcUncleHash
(
ablock
.
Uncles
())
{
t
.
Errorf
(
"block #%d [%x]: uncles mismatch: have %v, want %v"
,
num
,
hash
,
fblock
.
Uncles
(),
ablock
.
Uncles
())
t
.
Errorf
(
"block #%d [%x]: uncles mismatch: have %v, want %v"
,
num
,
hash
,
fblock
.
Uncles
(),
ablock
.
Uncles
())
}
}
if
freceipts
,
areceipts
:=
rawdb
.
ReadReceipts
(
fastDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
fastDb
,
hash
)
),
rawdb
.
ReadReceipts
(
archiveDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
archiveDb
,
hash
));
types
.
DeriveSha
(
freceipts
)
!=
types
.
DeriveSha
(
areceipts
)
{
if
freceipts
,
areceipts
:=
rawdb
.
ReadReceipts
(
fastDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
fastDb
,
hash
)
,
fast
.
Config
()),
rawdb
.
ReadReceipts
(
archiveDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
archiveDb
,
hash
),
archive
.
Config
(
));
types
.
DeriveSha
(
freceipts
)
!=
types
.
DeriveSha
(
areceipts
)
{
t
.
Errorf
(
"block #%d [%x]: receipts mismatch: have %v, want %v"
,
num
,
hash
,
freceipts
,
areceipts
)
t
.
Errorf
(
"block #%d [%x]: receipts mismatch: have %v, want %v"
,
num
,
hash
,
freceipts
,
areceipts
)
}
}
}
}
...
@@ -843,7 +843,7 @@ func TestChainTxReorgs(t *testing.T) {
...
@@ -843,7 +843,7 @@ func TestChainTxReorgs(t *testing.T) {
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
!=
nil
{
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
!=
nil
{
t
.
Errorf
(
"drop %d: tx %v found while shouldn't have been"
,
i
,
txn
)
t
.
Errorf
(
"drop %d: tx %v found while shouldn't have been"
,
i
,
txn
)
}
}
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
());
rcpt
!=
nil
{
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
()
,
blockchain
.
Config
()
);
rcpt
!=
nil
{
t
.
Errorf
(
"drop %d: receipt %v found while shouldn't have been"
,
i
,
rcpt
)
t
.
Errorf
(
"drop %d: receipt %v found while shouldn't have been"
,
i
,
rcpt
)
}
}
}
}
...
@@ -852,7 +852,7 @@ func TestChainTxReorgs(t *testing.T) {
...
@@ -852,7 +852,7 @@ func TestChainTxReorgs(t *testing.T) {
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
t
.
Errorf
(
"add %d: expected tx to be found"
,
i
)
t
.
Errorf
(
"add %d: expected tx to be found"
,
i
)
}
}
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
());
rcpt
==
nil
{
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
()
,
blockchain
.
Config
()
);
rcpt
==
nil
{
t
.
Errorf
(
"add %d: expected receipt to be found"
,
i
)
t
.
Errorf
(
"add %d: expected receipt to be found"
,
i
)
}
}
}
}
...
@@ -861,7 +861,7 @@ func TestChainTxReorgs(t *testing.T) {
...
@@ -861,7 +861,7 @@ func TestChainTxReorgs(t *testing.T) {
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
if
txn
,
_
,
_
,
_
:=
rawdb
.
ReadTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
t
.
Errorf
(
"share %d: expected tx to be found"
,
i
)
t
.
Errorf
(
"share %d: expected tx to be found"
,
i
)
}
}
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
());
rcpt
==
nil
{
if
rcpt
,
_
,
_
,
_
:=
rawdb
.
ReadReceipt
(
db
,
tx
.
Hash
()
,
blockchain
.
Config
()
);
rcpt
==
nil
{
t
.
Errorf
(
"share %d: expected receipt to be found"
,
i
)
t
.
Errorf
(
"share %d: expected receipt to be found"
,
i
)
}
}
}
}
...
...
core/rawdb/accessors_chain.go
View file @
7221cb14
...
@@ -19,12 +19,10 @@ package rawdb
...
@@ -19,12 +19,10 @@ package rawdb
import
(
import
(
"bytes"
"bytes"
"encoding/binary"
"encoding/binary"
"errors"
"math/big"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
...
@@ -311,20 +309,16 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
...
@@ -311,20 +309,16 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
if
len
(
data
)
==
0
{
if
len
(
data
)
==
0
{
return
nil
return
nil
}
}
// Convert the receipts from their storage form to their internal representation
// Convert the receipts from their storage form to their internal representation
storageReceipts
:=
[]
*
types
.
ReceiptForStorage
{}
storageReceipts
:=
[]
*
types
.
ReceiptForStorage
{}
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
storageReceipts
);
err
!=
nil
{
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
storageReceipts
);
err
!=
nil
{
log
.
Error
(
"Invalid receipt array RLP"
,
"hash"
,
hash
,
"err"
,
err
)
log
.
Error
(
"Invalid receipt array RLP"
,
"hash"
,
hash
,
"err"
,
err
)
return
nil
return
nil
}
}
receipts
:=
make
(
types
.
Receipts
,
len
(
storageReceipts
))
var
receipts
types
.
Receipts
for
i
,
storageReceipt
:=
range
storageReceipts
{
for
_
,
storageReceipt
:=
range
storageReceipts
{
receipts
[
i
]
=
(
*
types
.
Receipt
)(
storageReceipt
)
receipt
:=
(
*
types
.
Receipt
)(
storageReceipt
)
receipts
=
append
(
receipts
,
receipt
)
}
}
return
receipts
return
receipts
}
}
...
@@ -335,79 +329,24 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
...
@@ -335,79 +329,24 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
// The current implementation populates these metadata fields by reading the receipts'
// 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
// corresponding block body, so if the block body is not found it will return nil even
// if the receipt itself is stored.
// if the receipt itself is stored.
func
ReadReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
func
ReadReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
,
config
*
params
.
ChainConfig
)
types
.
Receipts
{
// We're deriving many fields from the block body, retrieve beside the receipt
receipts
:=
ReadRawReceipts
(
db
,
hash
,
number
)
receipts
:=
ReadRawReceipts
(
db
,
hash
,
number
)
if
receipts
==
nil
{
if
receipts
==
nil
{
return
receipts
return
nil
}
}
// Retrieve the block body to populate missing fields for receipts and logs
body
:=
ReadBody
(
db
,
hash
,
number
)
body
:=
ReadBody
(
db
,
hash
,
number
)
if
body
==
nil
{
if
body
==
nil
{
log
.
Error
(
"Missing body but have receipt"
,
"hash"
,
hash
,
"number"
,
number
)
log
.
Error
(
"Missing body but have receipt"
,
"hash"
,
hash
,
"number"
,
number
)
return
nil
return
nil
}
}
if
err
:=
receipts
.
DeriveFields
(
config
,
hash
,
number
,
body
.
Transactions
);
err
!=
nil
{
genesisHash
:=
ReadCanonicalHash
(
db
,
0
)
log
.
Error
(
"Failed to derive block receipts fields"
,
"hash"
,
hash
,
"number"
,
number
,
"err"
,
err
)
if
genesisHash
==
(
common
.
Hash
{})
{
log
.
Error
(
"Missing genesis hash"
)
return
nil
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
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.
// WriteReceipts stores all the transaction receipts belonging to a block.
func
WriteReceipts
(
db
ethdb
.
Writer
,
hash
common
.
Hash
,
number
uint64
,
receipts
types
.
Receipts
)
{
func
WriteReceipts
(
db
ethdb
.
Writer
,
hash
common
.
Hash
,
number
uint64
,
receipts
types
.
Receipts
)
{
// Convert the receipts into their storage form and serialize them
// Convert the receipts into their storage form and serialize them
...
...
core/rawdb/accessors_chain_test.go
View file @
7221cb14
...
@@ -20,14 +20,12 @@ import (
...
@@ -20,14 +20,12 @@ import (
"bytes"
"bytes"
"encoding/hex"
"encoding/hex"
"fmt"
"fmt"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"math/big"
"math/big"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
"golang.org/x/crypto/sha3"
)
)
...
@@ -272,11 +270,13 @@ func TestHeadStorage(t *testing.T) {
...
@@ -272,11 +270,13 @@ func TestHeadStorage(t *testing.T) {
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
db
:=
NewMemoryDatabase
()
db
:=
NewMemoryDatabase
()
// Create a live block since we need metadata to reconstruct the receipt
tx1
:=
types
.
NewTransaction
(
1
,
common
.
HexToAddress
(
"0x1"
),
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
)
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
)
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
}}
body
:=
&
types
.
Body
{
Transactions
:
types
.
Transactions
{
tx1
,
tx2
}}
// Create the two receipts to manage afterwards
receipt1
:=
&
types
.
Receipt
{
receipt1
:=
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusFailed
,
Status
:
types
.
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
CumulativeGasUsed
:
1
,
...
@@ -289,6 +289,7 @@ func TestBlockReceiptStorage(t *testing.T) {
...
@@ -289,6 +289,7 @@ func TestBlockReceiptStorage(t *testing.T) {
GasUsed
:
111111
,
GasUsed
:
111111
,
}
}
receipt1
.
Bloom
=
types
.
CreateBloom
(
types
.
Receipts
{
receipt1
})
receipt1
.
Bloom
=
types
.
CreateBloom
(
types
.
Receipts
{
receipt1
})
receipt2
:=
&
types
.
Receipt
{
receipt2
:=
&
types
.
Receipt
{
PostState
:
common
.
Hash
{
2
}
.
Bytes
(),
PostState
:
common
.
Hash
{
2
}
.
Bytes
(),
CumulativeGasUsed
:
2
,
CumulativeGasUsed
:
2
,
...
@@ -305,41 +306,35 @@ func TestBlockReceiptStorage(t *testing.T) {
...
@@ -305,41 +306,35 @@ func TestBlockReceiptStorage(t *testing.T) {
// Check that no receipt entries are in a pristine database
// Check that no receipt entries are in a pristine database
hash
:=
common
.
BytesToHash
([]
byte
{
0x03
,
0x14
})
hash
:=
common
.
BytesToHash
([]
byte
{
0x03
,
0x14
})
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
!=
0
{
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
,
params
.
TestChainConfig
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"non existent receipts returned: %v"
,
rs
)
t
.
Fatalf
(
"non existent receipts returned: %v"
,
rs
)
}
}
// Insert the body that corresponds to the receipts
.
// Insert the body that corresponds to the receipts
WriteBody
(
db
,
hash
,
0
,
body
)
WriteBody
(
db
,
hash
,
0
,
body
)
// Insert the receipt slice into the database and check presence
// Insert the receipt slice into the database and check presence
WriteReceipts
(
db
,
hash
,
0
,
receipts
)
WriteReceipts
(
db
,
hash
,
0
,
receipts
)
// Insert canonical hash that the chain configuration will be mapped to.
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
,
params
.
TestChainConfig
);
len
(
rs
)
==
0
{
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"
)
t
.
Fatalf
(
"no receipts returned"
)
}
else
{
}
else
{
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
err
.
Error
())
t
.
Fatalf
(
err
.
Error
())
}
}
}
}
// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
DeleteBody
(
db
,
hash
,
0
)
DeleteBody
(
db
,
hash
,
0
)
// Check that receipts are no longer returned when metadata cannot be recomputed.
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
,
params
.
TestChainConfig
);
rs
!=
nil
{
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
rs
!=
nil
{
t
.
Fatalf
(
"receipts returned when body was deleted: %v"
,
rs
)
t
.
Fatalf
(
"receipts returned when body was deleted: %v"
,
rs
)
}
}
// Check that receipts without metadata can be returned when specifically
// Ensure that receipts without metadata can be returned without the block body too
rs
:=
ReadRawReceipts
(
db
,
hash
,
0
)
if
err
:=
checkReceiptsRLP
(
ReadRawReceipts
(
db
,
hash
,
0
),
receipts
);
err
!=
nil
{
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
err
.
Error
())
t
.
Fatalf
(
err
.
Error
())
}
}
//
Re-insert the body that corresponds to the receipts.
//
Sanity check that body alone without the receipt is a full purge
WriteBody
(
db
,
hash
,
0
,
body
)
WriteBody
(
db
,
hash
,
0
,
body
)
// Delete the receipt slice and check purge
DeleteReceipts
(
db
,
hash
,
0
)
DeleteReceipts
(
db
,
hash
,
0
)
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
!=
0
{
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
,
params
.
TestChainConfig
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"deleted receipts returned: %v"
,
rs
)
t
.
Fatalf
(
"deleted receipts returned: %v"
,
rs
)
}
}
}
}
...
@@ -348,7 +343,6 @@ func checkReceiptsRLP(have, want types.Receipts) error {
...
@@ -348,7 +343,6 @@ func checkReceiptsRLP(have, want types.Receipts) error {
if
len
(
have
)
!=
len
(
want
)
{
if
len
(
have
)
!=
len
(
want
)
{
return
fmt
.
Errorf
(
"receipts sizes mismatch: have %d, want %d"
,
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
++
{
for
i
:=
0
;
i
<
len
(
want
);
i
++
{
rlpHave
,
err
:=
rlp
.
EncodeToBytes
(
have
[
i
])
rlpHave
,
err
:=
rlp
.
EncodeToBytes
(
have
[
i
])
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -358,155 +352,9 @@ func checkReceiptsRLP(have, want types.Receipts) error {
...
@@ -358,155 +352,9 @@ func checkReceiptsRLP(have, want types.Receipts) error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
!
bytes
.
Equal
(
rlpHave
,
rlpWant
)
{
if
!
bytes
.
Equal
(
rlpHave
,
rlpWant
)
{
return
fmt
.
Errorf
(
"receipt #%d: receipt mismatch: have %s, want %s"
,
i
,
hex
.
EncodeToString
(
rlpHave
),
hex
.
EncodeToString
(
rlpWant
))
return
fmt
.
Errorf
(
"receipt #%d: receipt mismatch: have %s, want %s"
,
i
,
hex
.
EncodeToString
(
rlpHave
),
hex
.
EncodeToString
(
rlpWant
))
}
}
}
}
return
nil
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/rawdb/accessors_indexes.go
View file @
7221cb14
...
@@ -21,6 +21,7 @@ import (
...
@@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -85,7 +86,8 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
...
@@ -85,7 +86,8 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
// ReadReceipt retrieves a specific transaction receipt from the database, along with
// ReadReceipt retrieves a specific transaction receipt from the database, along with
// its added positional metadata.
// its added positional metadata.
func
ReadReceipt
(
db
ethdb
.
Reader
,
hash
common
.
Hash
)
(
*
types
.
Receipt
,
common
.
Hash
,
uint64
,
uint64
)
{
func
ReadReceipt
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
config
*
params
.
ChainConfig
)
(
*
types
.
Receipt
,
common
.
Hash
,
uint64
,
uint64
)
{
// Retrieve the context of the receipt based on the transaction hash
blockHash
:=
ReadTxLookupEntry
(
db
,
hash
)
blockHash
:=
ReadTxLookupEntry
(
db
,
hash
)
if
blockHash
==
(
common
.
Hash
{})
{
if
blockHash
==
(
common
.
Hash
{})
{
return
nil
,
common
.
Hash
{},
0
,
0
return
nil
,
common
.
Hash
{},
0
,
0
...
@@ -94,7 +96,8 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash) (*types.Receipt, common.Hash
...
@@ -94,7 +96,8 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash) (*types.Receipt, common.Hash
if
blockNumber
==
nil
{
if
blockNumber
==
nil
{
return
nil
,
common
.
Hash
{},
0
,
0
return
nil
,
common
.
Hash
{},
0
,
0
}
}
receipts
:=
ReadReceipts
(
db
,
blockHash
,
*
blockNumber
)
// Read all the receipts from the block and return the one with the matching hash
receipts
:=
ReadReceipts
(
db
,
blockHash
,
*
blockNumber
,
config
)
for
receiptIndex
,
receipt
:=
range
receipts
{
for
receiptIndex
,
receipt
:=
range
receipts
{
if
receipt
.
TxHash
==
hash
{
if
receipt
.
TxHash
==
hash
{
return
receipt
,
blockHash
,
*
blockNumber
,
uint64
(
receiptIndex
)
return
receipt
,
blockHash
,
*
blockNumber
,
uint64
(
receiptIndex
)
...
...
core/types/block_test.go
View file @
7221cb14
...
@@ -18,7 +18,6 @@ package types
...
@@ -18,7 +18,6 @@ package types
import
(
import
(
"bytes"
"bytes"
"fmt"
"math/big"
"math/big"
"reflect"
"reflect"
"testing"
"testing"
...
@@ -52,11 +51,7 @@ func TestBlockEncoding(t *testing.T) {
...
@@ -52,11 +51,7 @@ func TestBlockEncoding(t *testing.T) {
check
(
"Size"
,
block
.
Size
(),
common
.
StorageSize
(
len
(
blockEnc
)))
check
(
"Size"
,
block
.
Size
(),
common
.
StorageSize
(
len
(
blockEnc
)))
tx1
:=
NewTransaction
(
0
,
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
big
.
NewInt
(
10
),
50000
,
big
.
NewInt
(
10
),
nil
)
tx1
:=
NewTransaction
(
0
,
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
big
.
NewInt
(
10
),
50000
,
big
.
NewInt
(
10
),
nil
)
tx1
,
_
=
tx1
.
WithSignature
(
HomesteadSigner
{},
common
.
Hex2Bytes
(
"9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"
))
tx1
,
_
=
tx1
.
WithSignature
(
HomesteadSigner
{},
common
.
Hex2Bytes
(
"9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"
))
fmt
.
Println
(
block
.
Transactions
()[
0
]
.
Hash
())
fmt
.
Println
(
tx1
.
data
)
fmt
.
Println
(
tx1
.
Hash
())
check
(
"len(Transactions)"
,
len
(
block
.
Transactions
()),
1
)
check
(
"len(Transactions)"
,
len
(
block
.
Transactions
()),
1
)
check
(
"Transactions[0].Hash"
,
block
.
Transactions
()[
0
]
.
Hash
(),
tx1
.
Hash
())
check
(
"Transactions[0].Hash"
,
block
.
Transactions
()[
0
]
.
Hash
(),
tx1
.
Hash
())
...
...
core/types/receipt.go
View file @
7221cb14
...
@@ -18,6 +18,7 @@ package types
...
@@ -18,6 +18,7 @@ package types
import
(
import
(
"bytes"
"bytes"
"errors"
"fmt"
"fmt"
"io"
"io"
"math/big"
"math/big"
...
@@ -25,6 +26,8 @@ import (
...
@@ -25,6 +26,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -99,8 +102,8 @@ type v4StoredReceiptRLP struct {
...
@@ -99,8 +102,8 @@ type v4StoredReceiptRLP struct {
GasUsed
uint64
GasUsed
uint64
}
}
//
legacy
StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
//
v3
StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
type
legacy
StoredReceiptRLP
struct
{
type
v3
StoredReceiptRLP
struct
{
PostStateOrStatus
[]
byte
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
CumulativeGasUsed
uint64
Bloom
Bloom
Bloom
Bloom
...
@@ -198,20 +201,21 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
...
@@ -198,20 +201,21 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
// fields of a receipt from an RLP stream.
// fields of a receipt from an RLP stream.
func
(
r
*
ReceiptForStorage
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
func
(
r
*
ReceiptForStorage
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
// Retrieve the entire receipt blob as we need to try multiple decoders
blob
,
err
:=
s
.
Raw
()
blob
,
err
:=
s
.
Raw
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
// Try decoding from the newest format for future proofness, then the older one
// for old nodes that just upgraded. V4 was an intermediate unreleased format so
// we do need to decode it, but it's not common (try last).
if
err
:=
decodeStoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
if
err
:=
decodeStoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
return
nil
return
nil
}
}
if
err
:=
decodeV3StoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
if
err
:=
decodeV4StoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
return
nil
return
nil
}
}
return
decodeV4StoredReceiptRLP
(
r
,
blob
)
return
decodeLegacyStoredReceiptRLP
(
r
,
blob
)
}
}
func
decodeStoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
func
decodeStoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
...
@@ -219,11 +223,9 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
...
@@ -219,11 +223,9 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
return
err
}
}
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
for
i
,
log
:=
range
stored
.
Logs
{
for
i
,
log
:=
range
stored
.
Logs
{
...
@@ -239,11 +241,9 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
...
@@ -239,11 +241,9 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
return
err
}
}
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
TxHash
=
stored
.
TxHash
r
.
TxHash
=
stored
.
TxHash
r
.
ContractAddress
=
stored
.
ContractAddress
r
.
ContractAddress
=
stored
.
ContractAddress
...
@@ -257,16 +257,14 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
...
@@ -257,16 +257,14 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
return
nil
return
nil
}
}
func
decode
Legacy
StoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
func
decode
V3
StoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
var
stored
legacy
StoredReceiptRLP
var
stored
v3
StoredReceiptRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
return
err
}
}
r
.
CumulativeGasUsed
=
stored
.
GasUsed
r
.
CumulativeGasUsed
=
stored
.
GasUsed
r
.
Bloom
=
stored
.
Bloom
r
.
Bloom
=
stored
.
Bloom
r
.
TxHash
=
stored
.
TxHash
r
.
TxHash
=
stored
.
TxHash
...
@@ -276,7 +274,6 @@ func decodeLegacyStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
...
@@ -276,7 +274,6 @@ func decodeLegacyStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
for
i
,
log
:=
range
stored
.
Logs
{
for
i
,
log
:=
range
stored
.
Logs
{
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
}
}
return
nil
return
nil
}
}
...
@@ -294,3 +291,46 @@ func (r Receipts) GetRlp(i int) []byte {
...
@@ -294,3 +291,46 @@ func (r Receipts) GetRlp(i int) []byte {
}
}
return
bytes
return
bytes
}
}
// DeriveFields fills the receipts with their computed fields based on consensus
// data and contextual infos like containing block and transactions.
func
(
r
Receipts
)
DeriveFields
(
config
*
params
.
ChainConfig
,
hash
common
.
Hash
,
number
uint64
,
txs
Transactions
)
error
{
signer
:=
MakeSigner
(
config
,
new
(
big
.
Int
)
.
SetUint64
(
number
))
logIndex
:=
uint
(
0
)
if
len
(
txs
)
!=
len
(
r
)
{
return
errors
.
New
(
"transaction and receipt count mismatch"
)
}
for
i
:=
0
;
i
<
len
(
r
);
i
++
{
// The transaction hash can be retrieved from the transaction itself
r
[
i
]
.
TxHash
=
txs
[
i
]
.
Hash
()
// block location fields
r
[
i
]
.
BlockHash
=
hash
r
[
i
]
.
BlockNumber
=
new
(
big
.
Int
)
.
SetUint64
(
number
)
r
[
i
]
.
TransactionIndex
=
uint
(
i
)
// The contract address can be derived from the transaction itself
if
txs
[
i
]
.
To
()
==
nil
{
// Deriving the signer is expensive, only do if it's actually needed
from
,
_
:=
Sender
(
signer
,
txs
[
i
])
r
[
i
]
.
ContractAddress
=
crypto
.
CreateAddress
(
from
,
txs
[
i
]
.
Nonce
())
}
// The used gas can be calculated based on previous r
if
i
==
0
{
r
[
i
]
.
GasUsed
=
r
[
i
]
.
CumulativeGasUsed
}
else
{
r
[
i
]
.
GasUsed
=
r
[
i
]
.
CumulativeGasUsed
-
r
[
i
-
1
]
.
CumulativeGasUsed
}
// The derived log fields can simply be set from the block and transaction
for
j
:=
0
;
j
<
len
(
r
[
i
]
.
Logs
);
j
++
{
r
[
i
]
.
Logs
[
j
]
.
BlockNumber
=
number
r
[
i
]
.
Logs
[
j
]
.
BlockHash
=
hash
r
[
i
]
.
Logs
[
j
]
.
TxHash
=
r
[
i
]
.
TxHash
r
[
i
]
.
Logs
[
j
]
.
TxIndex
=
uint
(
i
)
r
[
i
]
.
Logs
[
j
]
.
Index
=
logIndex
logIndex
++
}
}
return
nil
}
core/types/receipt_test.go
View file @
7221cb14
...
@@ -20,10 +20,13 @@ import (
...
@@ -20,10 +20,13 @@ import (
"bytes"
"bytes"
"encoding/hex"
"encoding/hex"
"encoding/json"
"encoding/json"
"math"
"math/big"
"math/big"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -41,8 +44,8 @@ func TestLegacyReceiptDecoding(t *testing.T) {
...
@@ -41,8 +44,8 @@ func TestLegacyReceiptDecoding(t *testing.T) {
encodeAsV4StoredReceiptRLP
,
encodeAsV4StoredReceiptRLP
,
},
},
{
{
"
Legacy
StoredReceiptRLP"
,
"
V3
StoredReceiptRLP"
,
encodeAs
Legacy
StoredReceiptRLP
,
encodeAs
V3
StoredReceiptRLP
,
},
},
}
}
...
@@ -116,8 +119,8 @@ func encodeAsV4StoredReceiptRLP(want *Receipt) ([]byte, error) {
...
@@ -116,8 +119,8 @@ func encodeAsV4StoredReceiptRLP(want *Receipt) ([]byte, error) {
return
rlp
.
EncodeToBytes
(
stored
)
return
rlp
.
EncodeToBytes
(
stored
)
}
}
func
encodeAs
Legacy
StoredReceiptRLP
(
want
*
Receipt
)
([]
byte
,
error
)
{
func
encodeAs
V3
StoredReceiptRLP
(
want
*
Receipt
)
([]
byte
,
error
)
{
stored
:=
&
legacy
StoredReceiptRLP
{
stored
:=
&
v3
StoredReceiptRLP
{
PostStateOrStatus
:
want
.
statusEncoding
(),
PostStateOrStatus
:
want
.
statusEncoding
(),
CumulativeGasUsed
:
want
.
CumulativeGasUsed
,
CumulativeGasUsed
:
want
.
CumulativeGasUsed
,
Bloom
:
want
.
Bloom
,
Bloom
:
want
.
Bloom
,
...
@@ -131,3 +134,136 @@ func encodeAsLegacyStoredReceiptRLP(want *Receipt) ([]byte, error) {
...
@@ -131,3 +134,136 @@ func encodeAsLegacyStoredReceiptRLP(want *Receipt) ([]byte, error) {
}
}
return
rlp
.
EncodeToBytes
(
stored
)
return
rlp
.
EncodeToBytes
(
stored
)
}
}
// Tests that receipt data can be correctly derived from the contextual infos
func
TestSetReceiptsData
(
t
*
testing
.
T
)
{
// Create a few transactions to have receipts for
txs
:=
Transactions
{
NewContractCreation
(
1
,
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
),
NewTransaction
(
2
,
common
.
HexToAddress
(
"0x2"
),
big
.
NewInt
(
2
),
2
,
big
.
NewInt
(
2
),
nil
),
}
// Create the corresponding receipts
receipts
:=
Receipts
{
&
Receipt
{
Status
:
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
Logs
:
[]
*
Log
{
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
txs
[
0
]
.
Hash
(),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
1
,
},
&
Receipt
{
PostState
:
common
.
Hash
{
2
}
.
Bytes
(),
CumulativeGasUsed
:
3
,
Logs
:
[]
*
Log
{
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
TxHash
:
txs
[
1
]
.
Hash
(),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
2
,
},
}
receipts
[
1
]
.
Bloom
=
CreateBloom
(
Receipts
{
receipts
[
1
]})
// Clear all the computed fields and re-derive them
number
:=
big
.
NewInt
(
1
)
hash
:=
common
.
BytesToHash
([]
byte
{
0x03
,
0x14
})
clearComputedFieldsOnReceipts
(
t
,
receipts
)
if
err
:=
receipts
.
DeriveFields
(
params
.
TestChainConfig
,
hash
,
number
.
Uint64
(),
txs
);
err
!=
nil
{
t
.
Fatalf
(
"DeriveFields(...) = %v, want <nil>"
,
err
)
}
// Iterate over all the computed fields and check that they're correct
signer
:=
MakeSigner
(
params
.
TestChainConfig
,
number
)
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
!=
hash
{
t
.
Errorf
(
"receipts[%d].BlockHash = %s, want %s"
,
i
,
receipts
[
i
]
.
BlockHash
.
String
(),
hash
.
String
())
}
if
receipts
[
i
]
.
BlockNumber
.
Cmp
(
number
)
!=
0
{
t
.
Errorf
(
"receipts[%c].BlockNumber = %s, want %s"
,
i
,
receipts
[
i
]
.
BlockNumber
.
String
(),
number
.
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
,
_
:=
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
!=
number
.
Uint64
()
{
t
.
Errorf
(
"receipts[%d].Logs[%d].BlockNumber = %d, want %d"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
BlockNumber
,
number
.
Uint64
())
}
if
receipts
[
i
]
.
Logs
[
j
]
.
BlockHash
!=
hash
{
t
.
Errorf
(
"receipts[%d].Logs[%d].BlockHash = %s, want %s"
,
i
,
j
,
receipts
[
i
]
.
Logs
[
j
]
.
BlockHash
.
String
(),
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
]
.
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
Receipts
)
{
t
.
Helper
()
for
_
,
receipt
:=
range
receipts
{
clearComputedFieldsOnReceipt
(
t
,
receipt
)
}
}
func
clearComputedFieldsOnReceipt
(
t
*
testing
.
T
,
receipt
*
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
[]
*
Log
)
{
t
.
Helper
()
for
_
,
log
:=
range
logs
{
clearComputedFieldsOnLog
(
t
,
log
)
}
}
func
clearComputedFieldsOnLog
(
t
*
testing
.
T
,
log
*
Log
)
{
t
.
Helper
()
log
.
BlockNumber
=
math
.
MaxUint32
log
.
BlockHash
=
common
.
Hash
{}
log
.
TxHash
=
common
.
Hash
{}
log
.
TxIndex
=
math
.
MaxUint32
log
.
Index
=
math
.
MaxUint32
}
eth/downloader/fakepeer.go
View file @
7221cb14
...
@@ -141,7 +141,7 @@ func (p *FakePeer) RequestBodies(hashes []common.Hash) error {
...
@@ -141,7 +141,7 @@ func (p *FakePeer) RequestBodies(hashes []common.Hash) error {
func
(
p
*
FakePeer
)
RequestReceipts
(
hashes
[]
common
.
Hash
)
error
{
func
(
p
*
FakePeer
)
RequestReceipts
(
hashes
[]
common
.
Hash
)
error
{
var
receipts
[][]
*
types
.
Receipt
var
receipts
[][]
*
types
.
Receipt
for
_
,
hash
:=
range
hashes
{
for
_
,
hash
:=
range
hashes
{
receipts
=
append
(
receipts
,
rawdb
.
ReadReceipts
(
p
.
db
,
hash
,
*
p
.
hc
.
GetBlockNumber
(
hash
)))
receipts
=
append
(
receipts
,
rawdb
.
ReadR
awR
eceipts
(
p
.
db
,
hash
,
*
p
.
hc
.
GetBlockNumber
(
hash
)))
}
}
p
.
dl
.
DeliverReceipts
(
p
.
id
,
receipts
)
p
.
dl
.
DeliverReceipts
(
p
.
id
,
receipts
)
return
nil
return
nil
...
...
eth/filters/filter_system_test.go
View file @
7221cb14
...
@@ -85,7 +85,7 @@ func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*type
...
@@ -85,7 +85,7 @@ func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*type
func
(
b
*
testBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
func
(
b
*
testBackend
)
GetReceipts
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
types
.
Receipts
,
error
)
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
b
.
db
,
hash
);
number
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
b
.
db
,
hash
);
number
!=
nil
{
return
rawdb
.
ReadReceipts
(
b
.
db
,
hash
,
*
number
),
nil
return
rawdb
.
ReadReceipts
(
b
.
db
,
hash
,
*
number
,
params
.
TestChainConfig
),
nil
}
}
return
nil
,
nil
return
nil
,
nil
}
}
...
@@ -95,7 +95,7 @@ func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types
...
@@ -95,7 +95,7 @@ func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types
if
number
==
nil
{
if
number
==
nil
{
return
nil
,
nil
return
nil
,
nil
}
}
receipts
:=
rawdb
.
ReadReceipts
(
b
.
db
,
hash
,
*
number
)
receipts
:=
rawdb
.
ReadReceipts
(
b
.
db
,
hash
,
*
number
,
params
.
TestChainConfig
)
logs
:=
make
([][]
*
types
.
Log
,
len
(
receipts
))
logs
:=
make
([][]
*
types
.
Log
,
len
(
receipts
))
for
i
,
receipt
:=
range
receipts
{
for
i
,
receipt
:=
range
receipts
{
...
...
les/handler.go
View file @
7221cb14
...
@@ -733,7 +733,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -733,7 +733,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Retrieve the requested block's receipts, skipping if unknown to us
// Retrieve the requested block's receipts, skipping if unknown to us
var
results
types
.
Receipts
var
results
types
.
Receipts
if
number
:=
rawdb
.
ReadHeaderNumber
(
pm
.
chainDb
,
hash
);
number
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
pm
.
chainDb
,
hash
);
number
!=
nil
{
results
=
rawdb
.
ReadReceipts
(
pm
.
chainDb
,
hash
,
*
number
)
results
=
rawdb
.
ReadR
awR
eceipts
(
pm
.
chainDb
,
hash
,
*
number
)
}
}
if
results
==
nil
{
if
results
==
nil
{
if
header
:=
pm
.
blockchain
.
GetHeaderByHash
(
hash
);
header
==
nil
||
header
.
ReceiptHash
!=
types
.
EmptyRootHash
{
if
header
:=
pm
.
blockchain
.
GetHeaderByHash
(
hash
);
header
==
nil
||
header
.
ReceiptHash
!=
types
.
EmptyRootHash
{
...
...
les/odr_test.go
View file @
7221cb14
...
@@ -60,7 +60,7 @@ func odrGetReceipts(ctx context.Context, db ethdb.Database, config *params.Chain
...
@@ -60,7 +60,7 @@ func odrGetReceipts(ctx context.Context, db ethdb.Database, config *params.Chain
var
receipts
types
.
Receipts
var
receipts
types
.
Receipts
if
bc
!=
nil
{
if
bc
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
);
number
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
);
number
!=
nil
{
receipts
=
rawdb
.
ReadReceipts
(
db
,
bhash
,
*
number
)
receipts
=
rawdb
.
ReadReceipts
(
db
,
bhash
,
*
number
,
config
)
}
}
}
else
{
}
else
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
);
number
!=
nil
{
if
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
);
number
!=
nil
{
...
@@ -159,6 +159,9 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
...
@@ -159,6 +159,9 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
client
.
pm
.
synchronise
(
client
.
rPeer
)
client
.
pm
.
synchronise
(
client
.
rPeer
)
test
:=
func
(
expFail
uint64
)
{
test
:=
func
(
expFail
uint64
)
{
// Mark this as a helper to put the failures at the correct lines
t
.
Helper
()
for
i
:=
uint64
(
0
);
i
<=
server
.
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
for
i
:=
uint64
(
0
);
i
<=
server
.
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
bhash
:=
rawdb
.
ReadCanonicalHash
(
server
.
db
,
i
)
bhash
:=
rawdb
.
ReadCanonicalHash
(
server
.
db
,
i
)
b1
:=
fn
(
light
.
NoOdr
,
server
.
db
,
server
.
pm
.
chainConfig
,
server
.
pm
.
blockchain
.
(
*
core
.
BlockChain
),
nil
,
bhash
)
b1
:=
fn
(
light
.
NoOdr
,
server
.
db
,
server
.
pm
.
chainConfig
,
server
.
pm
.
blockchain
.
(
*
core
.
BlockChain
),
nil
,
bhash
)
...
@@ -170,10 +173,10 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
...
@@ -170,10 +173,10 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
eq
:=
bytes
.
Equal
(
b1
,
b2
)
eq
:=
bytes
.
Equal
(
b1
,
b2
)
exp
:=
i
<
expFail
exp
:=
i
<
expFail
if
exp
&&
!
eq
{
if
exp
&&
!
eq
{
t
.
Errorf
(
"odr mismatch"
)
t
.
Fatalf
(
"odr mismatch: have %x, want %x"
,
b2
,
b1
)
}
}
if
!
exp
&&
eq
{
if
!
exp
&&
eq
{
t
.
Error
f
(
"unexpected odr match"
)
t
.
Fatal
f
(
"unexpected odr match"
)
}
}
}
}
}
}
...
@@ -182,6 +185,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
...
@@ -182,6 +185,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
client
.
peers
.
Unregister
(
client
.
rPeer
.
id
)
client
.
peers
.
Unregister
(
client
.
rPeer
.
id
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
test
(
expFail
)
test
(
expFail
)
// expect all retrievals to pass
// expect all retrievals to pass
client
.
peers
.
Register
(
client
.
rPeer
)
client
.
peers
.
Register
(
client
.
rPeer
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
...
@@ -189,6 +193,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
...
@@ -189,6 +193,7 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
client
.
rPeer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
,
bool
)
bool
{
return
true
}
client
.
rPeer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
,
bool
)
bool
{
return
true
}
client
.
peers
.
lock
.
Unlock
()
client
.
peers
.
lock
.
Unlock
()
test
(
5
)
test
(
5
)
// still expect all retrievals to pass, now data should be cached locally
// still expect all retrievals to pass, now data should be cached locally
client
.
peers
.
Unregister
(
client
.
rPeer
.
id
)
client
.
peers
.
Unregister
(
client
.
rPeer
.
id
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
...
...
light/odr_test.go
View file @
7221cb14
...
@@ -122,7 +122,7 @@ func odrGetReceipts(ctx context.Context, db ethdb.Database, bc *core.BlockChain,
...
@@ -122,7 +122,7 @@ func odrGetReceipts(ctx context.Context, db ethdb.Database, bc *core.BlockChain,
if
bc
!=
nil
{
if
bc
!=
nil
{
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
)
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
)
if
number
!=
nil
{
if
number
!=
nil
{
receipts
=
rawdb
.
ReadReceipts
(
db
,
bhash
,
*
number
)
receipts
=
rawdb
.
ReadReceipts
(
db
,
bhash
,
*
number
,
bc
.
Config
()
)
}
}
}
else
{
}
else
{
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
)
number
:=
rawdb
.
ReadHeaderNumber
(
db
,
bhash
)
...
...
light/odr_util.go
View file @
7221cb14
...
@@ -135,7 +135,6 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
...
@@ -135,7 +135,6 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
}
}
receipts
=
r
.
Receipts
receipts
=
r
.
Receipts
}
}
// If the receipts are incomplete, fill the derived fields
// If the receipts are incomplete, fill the derived fields
if
len
(
receipts
)
>
0
&&
receipts
[
0
]
.
TxHash
==
(
common
.
Hash
{})
{
if
len
(
receipts
)
>
0
&&
receipts
[
0
]
.
TxHash
==
(
common
.
Hash
{})
{
block
,
err
:=
GetBlock
(
ctx
,
odr
,
hash
,
number
)
block
,
err
:=
GetBlock
(
ctx
,
odr
,
hash
,
number
)
...
@@ -145,12 +144,11 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
...
@@ -145,12 +144,11 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
genesis
:=
rawdb
.
ReadCanonicalHash
(
odr
.
Database
(),
0
)
genesis
:=
rawdb
.
ReadCanonicalHash
(
odr
.
Database
(),
0
)
config
:=
rawdb
.
ReadChainConfig
(
odr
.
Database
(),
genesis
)
config
:=
rawdb
.
ReadChainConfig
(
odr
.
Database
(),
genesis
)
if
err
:=
r
awdb
.
SetReceiptsData
(
config
,
block
.
Hash
(),
block
.
Number
(),
block
.
Body
(),
receipts
);
err
!=
nil
{
if
err
:=
r
eceipts
.
DeriveFields
(
config
,
block
.
Hash
(),
block
.
NumberU64
(),
block
.
Transactions
()
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
rawdb
.
WriteReceipts
(
odr
.
Database
(),
hash
,
number
,
receipts
)
rawdb
.
WriteReceipts
(
odr
.
Database
(),
hash
,
number
,
receipts
)
}
}
return
receipts
,
nil
return
receipts
,
nil
}
}
...
@@ -162,7 +160,6 @@ func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number
...
@@ -162,7 +160,6 @@ func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// Return the logs without deriving any computed fields on the receipts
// Return the logs without deriving any computed fields on the receipts
logs
:=
make
([][]
*
types
.
Log
,
len
(
receipts
))
logs
:=
make
([][]
*
types
.
Log
,
len
(
receipts
))
for
i
,
receipt
:=
range
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