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 (
...
@@ -35,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
...
@@ -43,7 +42,7 @@ import (
...
@@ -43,7 +42,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie"
lru
"github.com/hashicorp/golang-lru"
"github.com/hashicorp/golang-lru"
)
)
var
(
var
(
...
@@ -79,12 +78,19 @@ const (
...
@@ -79,12 +78,19 @@ const (
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
//
//
// During the process of upgrading the database version from 3 to 4,
// Changelog:
// the following incompatible database changes were added.
//
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
// - Version 4
// * the `Bloom` field of receipt is deleted
// The following incompatible database changes were added:
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
BlockChainVersion
uint64
=
4
// * 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
// CacheConfig contains the configuration values for the trie caching/pruning
...
@@ -784,49 +790,6 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
...
@@ -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
// InsertReceiptChain attempts to complete an already existing header chain with
// transaction and receipt data.
// transaction and receipt data.
func
(
bc
*
BlockChain
)
InsertReceiptChain
(
blockChain
types
.
Blocks
,
receiptChain
[]
types
.
Receipts
)
(
int
,
error
)
{
func
(
bc
*
BlockChain
)
InsertReceiptChain
(
blockChain
types
.
Blocks
,
receiptChain
[]
types
.
Receipts
)
(
int
,
error
)
{
...
@@ -865,7 +828,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
...
@@ -865,7 +828,7 @@ 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
:=
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
)
return
i
,
fmt
.
Errorf
(
"failed to set receipts data: %v"
,
err
)
}
}
// Write all the data out into the database
// 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) {
...
@@ -104,6 +104,15 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b
.
receipts
=
append
(
b
.
receipts
,
receipt
)
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.
// Number returns the block number of the block being generated.
func
(
b
*
BlockGen
)
Number
()
*
big
.
Int
{
func
(
b
*
BlockGen
)
Number
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
b
.
header
.
Number
)
return
new
(
big
.
Int
)
.
Set
(
b
.
header
.
Number
)
...
...
core/rawdb/accessors_chain.go
View file @
6b0ddd14
...
@@ -19,12 +19,15 @@ package rawdb
...
@@ -19,12 +19,15 @@ 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/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -299,39 +302,112 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
...
@@ -299,39 +302,112 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
return
data
return
data
}
}
// ReadReceipts retrieves all the transaction receipts belonging to a block.
// ReadRawReceipts retrieves all the transaction receipts belonging to a block.
func
ReadReceipts
(
db
ethdb
.
Reader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
// 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
// Retrieve the flattened receipt slice
data
:=
ReadReceiptsRLP
(
db
,
hash
,
number
)
data
:=
ReadReceiptsRLP
(
db
,
hash
,
number
)
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
))
logIndex
:=
uint
(
0
)
var
receipts
types
.
Receipts
for
i
,
receipt
:=
range
storageReceipts
{
for
_
,
storageReceipt
:=
range
storageReceipts
{
// Assemble deriving fields for log.
receipt
:=
(
*
types
.
Receipt
)(
storageReceipt
)
for
_
,
log
:=
range
receipt
.
Logs
{
receipts
=
append
(
receipts
,
receipt
)
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
)
}
}
return
receipts
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.
// 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 @
6b0ddd14
...
@@ -18,6 +18,11 @@ package rawdb
...
@@ -18,6 +18,11 @@ package rawdb
import
(
import
(
"bytes"
"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"
"math/big"
"testing"
"testing"
...
@@ -267,6 +272,11 @@ func TestHeadStorage(t *testing.T) {
...
@@ -267,6 +272,11 @@ func TestHeadStorage(t *testing.T) {
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
db
:=
NewMemoryDatabase
()
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
{
receipt1
:=
&
types
.
Receipt
{
Status
:
types
.
ReceiptStatusFailed
,
Status
:
types
.
ReceiptStatusFailed
,
CumulativeGasUsed
:
1
,
CumulativeGasUsed
:
1
,
...
@@ -274,7 +284,7 @@ func TestBlockReceiptStorage(t *testing.T) {
...
@@ -274,7 +284,7 @@ func TestBlockReceiptStorage(t *testing.T) {
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x11
,
0x11
}
),
TxHash
:
tx1
.
Hash
(
),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
111111
,
GasUsed
:
111111
,
}
}
...
@@ -286,7 +296,7 @@ func TestBlockReceiptStorage(t *testing.T) {
...
@@ -286,7 +296,7 @@ func TestBlockReceiptStorage(t *testing.T) {
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x22
,
0x22
}
),
TxHash
:
tx2
.
Hash
(
),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
222222
,
GasUsed
:
222222
,
}
}
...
@@ -298,23 +308,205 @@ func TestBlockReceiptStorage(t *testing.T) {
...
@@ -298,23 +308,205 @@ func TestBlockReceiptStorage(t *testing.T) {
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
!=
0
{
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
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.
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.
WriteCanonicalHash
(
db
,
hash
,
0
)
// Insert the chain configuration.
WriteChainConfig
(
db
,
hash
,
params
.
MainnetChainConfig
)
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
==
0
{
if
rs
:=
ReadReceipts
(
db
,
hash
,
0
);
len
(
rs
)
==
0
{
t
.
Fatalf
(
"no receipts returned"
)
t
.
Fatalf
(
"no receipts returned"
)
}
else
{
}
else
{
for
i
:=
0
;
i
<
len
(
receipts
);
i
++
{
if
err
:=
checkReceiptsRLP
(
rs
,
receipts
);
err
!=
nil
{
rlpHave
,
_
:=
rlp
.
EncodeToBytes
(
rs
[
i
])
t
.
Fatalf
(
err
.
Error
())
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
])
}
}
}
}
}
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
// 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
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"deleted receipts returned: %v"
,
rs
)
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 {
...
@@ -71,8 +71,8 @@ type rlpLog struct {
// rlpStorageLog is the storage encoding of a log.
// rlpStorageLog is the storage encoding of a log.
type
rlpStorageLog
rlpLog
type
rlpStorageLog
rlpLog
//
L
egacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
//
l
egacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
type
L
egacyRlpStorageLog
struct
{
type
l
egacyRlpStorageLog
struct
{
Address
common
.
Address
Address
common
.
Address
Topics
[]
common
.
Hash
Topics
[]
common
.
Hash
Data
[]
byte
Data
[]
byte
...
@@ -129,7 +129,7 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
...
@@ -129,7 +129,7 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
}
}
}
else
{
}
else
{
// Try to decode log with previous definition.
// Try to decode log with previous definition.
var
dec
L
egacyRlpStorageLog
var
dec
l
egacyRlpStorageLog
err
=
rlp
.
DecodeBytes
(
blob
,
&
dec
)
err
=
rlp
.
DecodeBytes
(
blob
,
&
dec
)
if
err
==
nil
{
if
err
==
nil
{
*
l
=
LogForStorage
{
*
l
=
LogForStorage
{
...
...
core/types/receipt.go
View file @
6b0ddd14
...
@@ -82,8 +82,15 @@ type receiptRLP struct {
...
@@ -82,8 +82,15 @@ type receiptRLP struct {
Logs
[]
*
Log
Logs
[]
*
Log
}
}
// receiptStorageRLP is the storage encoding of a receipt.
// storedReceiptRLP is the storage encoding of a receipt.
type
receiptStorageRLP
struct
{
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
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
CumulativeGasUsed
uint64
TxHash
common
.
Hash
TxHash
common
.
Hash
...
@@ -92,8 +99,8 @@ type receiptStorageRLP struct {
...
@@ -92,8 +99,8 @@ type receiptStorageRLP struct {
GasUsed
uint64
GasUsed
uint64
}
}
//
LegacyReceiptStorageRLP is the previous
storage encoding of a receipt including some unnecessary fields.
//
legacyStoredReceiptRLP is the original
storage encoding of a receipt including some unnecessary fields.
type
LegacyReceiptStorage
RLP
struct
{
type
legacyStoredReceipt
RLP
struct
{
PostStateOrStatus
[]
byte
PostStateOrStatus
[]
byte
CumulativeGasUsed
uint64
CumulativeGasUsed
uint64
Bloom
Bloom
Bloom
Bloom
...
@@ -177,13 +184,10 @@ type ReceiptForStorage Receipt
...
@@ -177,13 +184,10 @@ type ReceiptForStorage Receipt
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
// into an RLP stream.
// into an RLP stream.
func
(
r
*
ReceiptForStorage
)
EncodeRLP
(
w
io
.
Writer
)
error
{
func
(
r
*
ReceiptForStorage
)
EncodeRLP
(
w
io
.
Writer
)
error
{
enc
:=
&
receiptStorage
RLP
{
enc
:=
&
storedReceipt
RLP
{
PostStateOrStatus
:
(
*
Receipt
)(
r
)
.
statusEncoding
(),
PostStateOrStatus
:
(
*
Receipt
)(
r
)
.
statusEncoding
(),
CumulativeGasUsed
:
r
.
CumulativeGasUsed
,
CumulativeGasUsed
:
r
.
CumulativeGasUsed
,
TxHash
:
r
.
TxHash
,
ContractAddress
:
r
.
ContractAddress
,
Logs
:
make
([]
*
LogForStorage
,
len
(
r
.
Logs
)),
Logs
:
make
([]
*
LogForStorage
,
len
(
r
.
Logs
)),
GasUsed
:
r
.
GasUsed
,
}
}
for
i
,
log
:=
range
r
.
Logs
{
for
i
,
log
:=
range
r
.
Logs
{
enc
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
enc
.
Logs
[
i
]
=
(
*
LogForStorage
)(
log
)
...
@@ -198,32 +202,81 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
...
@@ -198,32 +202,81 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
var
dec
receiptStorageRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
dec
);
err
!=
nil
{
if
err
:=
decodeStoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
var
sdec
LegacyReceiptStorageRLP
return
nil
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
sdec
);
err
!=
nil
{
}
return
err
}
if
err
:=
decodeV4StoredReceiptRLP
(
r
,
blob
);
err
==
nil
{
dec
.
PostStateOrStatus
=
common
.
CopyBytes
(
sdec
.
PostStateOrStatus
)
return
nil
dec
.
CumulativeGasUsed
=
sdec
.
CumulativeGasUsed
}
dec
.
TxHash
=
sdec
.
TxHash
dec
.
ContractAddress
=
sdec
.
ContractAddress
return
decodeLegacyStoredReceiptRLP
(
r
,
blob
)
dec
.
Logs
=
sdec
.
Logs
}
dec
.
GasUsed
=
sdec
.
GasUsed
}
func
decodeStoredReceiptRLP
(
r
*
ReceiptForStorage
,
blob
[]
byte
)
error
{
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
dec
.
PostStateOrStatus
);
err
!=
nil
{
var
stored
storedReceiptRLP
if
err
:=
rlp
.
DecodeBytes
(
blob
,
&
stored
);
err
!=
nil
{
return
err
}
if
err
:=
(
*
Receipt
)(
r
)
.
setStatus
(
stored
.
PostStateOrStatus
);
err
!=
nil
{
return
err
return
err
}
}
// Assign the consensus fields
r
.
CumulativeGasUsed
=
dec
.
CumulativeGasUsed
r
.
CumulativeGasUsed
=
stored
.
CumulativeGasUsed
r
.
Logs
=
make
([]
*
Log
,
len
(
dec
.
Logs
))
r
.
Logs
=
make
([]
*
Log
,
len
(
stored
.
Logs
))
for
i
,
log
:=
range
dec
.
Logs
{
for
i
,
log
:=
range
stored
.
Logs
{
r
.
Logs
[
i
]
=
(
*
Log
)(
log
)
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
)})
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
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) {
...
@@ -138,6 +138,7 @@ func TestFilters(t *testing.T) {
},
},
}
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
1
,
common
.
HexToAddress
(
"0x1"
),
big
.
NewInt
(
1
),
1
,
big
.
NewInt
(
1
),
nil
))
case
2
:
case
2
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
receipt
.
Logs
=
[]
*
types
.
Log
{
...
@@ -147,6 +148,8 @@ func TestFilters(t *testing.T) {
...
@@ -147,6 +148,8 @@ func TestFilters(t *testing.T) {
},
},
}
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
2
,
common
.
HexToAddress
(
"0x2"
),
big
.
NewInt
(
2
),
2
,
big
.
NewInt
(
2
),
nil
))
case
998
:
case
998
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
receipt
.
Logs
=
[]
*
types
.
Log
{
...
@@ -156,6 +159,7 @@ func TestFilters(t *testing.T) {
...
@@ -156,6 +159,7 @@ func TestFilters(t *testing.T) {
},
},
}
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
998
,
common
.
HexToAddress
(
"0x998"
),
big
.
NewInt
(
998
),
998
,
big
.
NewInt
(
998
),
nil
))
case
999
:
case
999
:
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
:=
types
.
NewReceipt
(
nil
,
false
,
0
)
receipt
.
Logs
=
[]
*
types
.
Log
{
receipt
.
Logs
=
[]
*
types
.
Log
{
...
@@ -165,6 +169,7 @@ func TestFilters(t *testing.T) {
...
@@ -165,6 +169,7 @@ func TestFilters(t *testing.T) {
},
},
}
}
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedReceipt
(
receipt
)
gen
.
AddUncheckedTx
(
types
.
NewTransaction
(
999
,
common
.
HexToAddress
(
"0x999"
),
big
.
NewInt
(
999
),
999
,
big
.
NewInt
(
999
),
nil
))
}
}
})
})
for
i
,
block
:=
range
chain
{
for
i
,
block
:=
range
chain
{
...
...
les/handler_test.go
View file @
6b0ddd14
...
@@ -292,7 +292,7 @@ func testGetReceipt(t *testing.T, protocol int) {
...
@@ -292,7 +292,7 @@ func testGetReceipt(t *testing.T, protocol int) {
block
:=
bc
.
GetBlockByNumber
(
i
)
block
:=
bc
.
GetBlockByNumber
(
i
)
hashes
=
append
(
hashes
,
block
.
Hash
())
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
// Send the hash request and verify the response
cost
:=
server
.
tPeer
.
GetRequestCost
(
GetReceiptsMsg
,
len
(
hashes
))
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 {
...
@@ -79,7 +79,7 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
case
*
ReceiptsRequest
:
case
*
ReceiptsRequest
:
number
:=
rawdb
.
ReadHeaderNumber
(
odr
.
sdb
,
req
.
Hash
)
number
:=
rawdb
.
ReadHeaderNumber
(
odr
.
sdb
,
req
.
Hash
)
if
number
!=
nil
{
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
:
case
*
TrieRequest
:
t
,
_
:=
trie
.
New
(
req
.
Id
.
Root
,
trie
.
NewDatabase
(
odr
.
sdb
))
t
,
_
:=
trie
.
New
(
req
.
Id
.
Root
,
trie
.
NewDatabase
(
odr
.
sdb
))
...
...
light/odr_util.go
View file @
6b0ddd14
...
@@ -21,7 +21,6 @@ import (
...
@@ -21,7 +21,6 @@ import (
"context"
"context"
"github.com/ethereum/go-ethereum/common"
"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/rawdb"
"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/crypto"
...
@@ -127,8 +126,8 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint
...
@@ -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
// GetBlockReceipts retrieves the receipts generated by the transactions included
// in a block given by its hash.
// in a block given by its hash.
func
GetBlockReceipts
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
(
types
.
Receipts
,
error
)
{
func
GetBlockReceipts
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
(
types
.
Receipts
,
error
)
{
//
Retrieve the potentially incomplete receipts from disk or network
//
Assume receipts are already stored locally and attempt to retrieve.
receipts
:=
rawdb
.
ReadReceipts
(
odr
.
Database
(),
hash
,
number
)
receipts
:=
rawdb
.
ReadR
awR
eceipts
(
odr
.
Database
(),
hash
,
number
)
if
receipts
==
nil
{
if
receipts
==
nil
{
r
:=
&
ReceiptsRequest
{
Hash
:
hash
,
Number
:
number
}
r
:=
&
ReceiptsRequest
{
Hash
:
hash
,
Number
:
number
}
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
...
@@ -136,6 +135,7 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
...
@@ -136,6 +135,7 @@ 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,11 +145,12 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
...
@@ -145,11 +145,12 @@ 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
:=
core
.
SetReceiptsData
(
config
,
block
,
receipts
);
err
!=
nil
{
if
err
:=
rawdb
.
SetReceiptsData
(
config
,
block
.
Hash
(),
block
.
Number
(),
block
.
Body
()
,
receipts
);
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
}
}
...
@@ -157,14 +158,11 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
...
@@ -157,14 +158,11 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num
// block given by its hash.
// block given by its hash.
func
GetBlockLogs
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
([][]
*
types
.
Log
,
error
)
{
func
GetBlockLogs
(
ctx
context
.
Context
,
odr
OdrBackend
,
hash
common
.
Hash
,
number
uint64
)
([][]
*
types
.
Log
,
error
)
{
// Retrieve the potentially incomplete receipts from disk or network
// Retrieve the potentially incomplete receipts from disk or network
receipts
:=
rawdb
.
ReadReceipts
(
odr
.
Database
(),
hash
,
number
)
receipts
,
err
:=
GetBlockReceipts
(
ctx
,
odr
,
hash
,
number
)
if
receipts
==
nil
{
if
err
!=
nil
{
r
:=
&
ReceiptsRequest
{
Hash
:
hash
,
Number
:
number
}
return
nil
,
err
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
return
nil
,
err
}
receipts
=
r
.
Receipts
}
}
// 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