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
7399b138
Commit
7399b138
authored
Nov 19, 2015
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1923 from karalabe/cleanup-receipt-data-access
core, eth, miner, xeth: clean up tx/receipt db accessors
parents
65bb07fb
e86e0ecd
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
359 additions
and
235 deletions
+359
-235
block_validator_test.go
core/block_validator_test.go
+1
-1
blockchain.go
core/blockchain.go
+6
-6
blockchain_test.go
core/blockchain_test.go
+4
-4
database_util.go
core/database_util.go
+174
-4
database_util_test.go
core/database_util_test.go
+160
-2
genesis.go
core/genesis.go
+1
-1
transaction_util.go
core/transaction_util.go
+0
-171
backend_test.go
eth/backend_test.go
+2
-2
filter_test.go
eth/filters/filter_test.go
+4
-4
worker.go
miner/worker.go
+3
-3
xeth.go
xeth/xeth.go
+4
-37
No files found.
core/block_validator_test.go
View file @
7399b138
...
...
@@ -81,7 +81,7 @@ func TestPutReceipt(t *testing.T) {
Index
:
0
,
}}
Put
Receipts
(
db
,
types
.
Receipts
{
receipt
})
Write
Receipts
(
db
,
types
.
Receipts
{
receipt
})
receipt
=
GetReceipt
(
db
,
common
.
Hash
{})
if
receipt
==
nil
{
t
.
Error
(
"expected to get 1 receipt, got none."
)
...
...
core/blockchain.go
View file @
7399b138
...
...
@@ -972,7 +972,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
glog
.
Fatal
(
errs
[
index
])
return
}
if
err
:=
Put
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
if
err
:=
Write
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
errs
[
index
]
=
fmt
.
Errorf
(
"failed to write block receipts: %v"
,
err
)
atomic
.
AddInt32
(
&
failed
,
1
)
glog
.
Fatal
(
errs
[
index
])
...
...
@@ -1182,7 +1182,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
// coalesce logs for later processing
coalescedLogs
=
append
(
coalescedLogs
,
logs
...
)
if
err
:=
Put
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
if
err
:=
Write
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
return
i
,
err
}
...
...
@@ -1201,11 +1201,11 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
events
=
append
(
events
,
ChainEvent
{
block
,
block
.
Hash
(),
logs
})
// This puts transactions in a extra db for rpc
if
err
:=
PutTransactions
(
self
.
chainDb
,
block
,
block
.
Transactions
()
);
err
!=
nil
{
if
err
:=
WriteTransactions
(
self
.
chainDb
,
block
);
err
!=
nil
{
return
i
,
err
}
// store the receipts
if
err
:=
Put
Receipts
(
self
.
chainDb
,
receipts
);
err
!=
nil
{
if
err
:=
Write
Receipts
(
self
.
chainDb
,
receipts
);
err
!=
nil
{
return
i
,
err
}
// Write map map bloom filters
...
...
@@ -1294,12 +1294,12 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
// insert the block in the canonical way, re-writing history
self
.
insert
(
block
)
// write canonical receipts and transactions
if
err
:=
PutTransactions
(
self
.
chainDb
,
block
,
block
.
Transactions
()
);
err
!=
nil
{
if
err
:=
WriteTransactions
(
self
.
chainDb
,
block
);
err
!=
nil
{
return
err
}
receipts
:=
GetBlockReceipts
(
self
.
chainDb
,
block
.
Hash
())
// write receipts
if
err
:=
Put
Receipts
(
self
.
chainDb
,
receipts
);
err
!=
nil
{
if
err
:=
Write
Receipts
(
self
.
chainDb
,
receipts
);
err
!=
nil
{
return
err
}
// Write map map bloom filters
...
...
core/blockchain_test.go
View file @
7399b138
...
...
@@ -937,8 +937,8 @@ func TestChainTxReorgs(t *testing.T) {
// removed tx
for
i
,
tx
:=
range
(
types
.
Transactions
{
pastDrop
,
freshDrop
})
{
if
GetTransaction
(
db
,
tx
.
Hash
())
!=
nil
{
t
.
Errorf
(
"drop %d: tx
found while shouldn't have been"
,
i
)
if
txn
,
_
,
_
,
_
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
!=
nil
{
t
.
Errorf
(
"drop %d: tx
%v found while shouldn't have been"
,
i
,
txn
)
}
if
GetReceipt
(
db
,
tx
.
Hash
())
!=
nil
{
t
.
Errorf
(
"drop %d: receipt found while shouldn't have been"
,
i
)
...
...
@@ -946,7 +946,7 @@ func TestChainTxReorgs(t *testing.T) {
}
// added tx
for
i
,
tx
:=
range
(
types
.
Transactions
{
pastAdd
,
freshAdd
,
futureAdd
})
{
if
GetTransaction
(
db
,
tx
.
Hash
())
==
nil
{
if
txn
,
_
,
_
,
_
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
t
.
Errorf
(
"add %d: expected tx to be found"
,
i
)
}
if
GetReceipt
(
db
,
tx
.
Hash
())
==
nil
{
...
...
@@ -955,7 +955,7 @@ func TestChainTxReorgs(t *testing.T) {
}
// shared tx
for
i
,
tx
:=
range
(
types
.
Transactions
{
postponed
,
swapped
})
{
if
GetTransaction
(
db
,
tx
.
Hash
())
==
nil
{
if
txn
,
_
,
_
,
_
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
t
.
Errorf
(
"share %d: expected tx to be found"
,
i
)
}
if
GetReceipt
(
db
,
tx
.
Hash
())
==
nil
{
...
...
core/
chain
_util.go
→
core/
database
_util.go
View file @
7399b138
...
...
@@ -43,11 +43,15 @@ var (
bodySuffix
=
[]
byte
(
"-body"
)
tdSuffix
=
[]
byte
(
"-td"
)
ExpDiffPeriod
=
big
.
NewInt
(
100000
)
blockHashPre
=
[]
byte
(
"block-hash-"
)
// [deprecated by eth/63]
txMetaSuffix
=
[]
byte
{
0x01
}
receiptsPrefix
=
[]
byte
(
"receipts-"
)
blockReceiptsPrefix
=
[]
byte
(
"receipts-block-"
)
mipmapPre
=
[]
byte
(
"mipmap-log-bloom-"
)
MIPMapLevels
=
[]
uint64
{
1000000
,
500000
,
100000
,
50000
,
1000
}
ExpDiffPeriod
=
big
.
NewInt
(
100000
)
blockHashPrefix
=
[]
byte
(
"block-hash-"
)
// [deprecated by the header/block split, remove eventually]
)
// CalcDifficulty is the difficulty adjustment algorithm. It returns
...
...
@@ -234,6 +238,67 @@ func GetBlock(db ethdb.Database, hash common.Hash) *types.Block {
return
types
.
NewBlockWithHeader
(
header
)
.
WithBody
(
body
.
Transactions
,
body
.
Uncles
)
}
// GetBlockReceipts retrieves the receipts generated by the transactions included
// in a block given by its hash.
func
GetBlockReceipts
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
types
.
Receipts
{
data
,
_
:=
db
.
Get
(
append
(
blockReceiptsPrefix
,
hash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
}
storageReceipts
:=
[]
*
types
.
ReceiptForStorage
{}
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
storageReceipts
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"invalid receipt array RLP for hash %x: %v"
,
hash
,
err
)
return
nil
}
receipts
:=
make
(
types
.
Receipts
,
len
(
storageReceipts
))
for
i
,
receipt
:=
range
storageReceipts
{
receipts
[
i
]
=
(
*
types
.
Receipt
)(
receipt
)
}
return
receipts
}
// GetTransaction retrieves a specific transaction from the database, along with
// its added positional metadata.
func
GetTransaction
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
(
*
types
.
Transaction
,
common
.
Hash
,
uint64
,
uint64
)
{
// Retrieve the transaction itself from the database
data
,
_
:=
db
.
Get
(
hash
.
Bytes
())
if
len
(
data
)
==
0
{
return
nil
,
common
.
Hash
{},
0
,
0
}
var
tx
types
.
Transaction
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
tx
);
err
!=
nil
{
return
nil
,
common
.
Hash
{},
0
,
0
}
// Retrieve the blockchain positional metadata
data
,
_
=
db
.
Get
(
append
(
hash
.
Bytes
(),
txMetaSuffix
...
))
if
len
(
data
)
==
0
{
return
nil
,
common
.
Hash
{},
0
,
0
}
var
meta
struct
{
BlockHash
common
.
Hash
BlockIndex
uint64
Index
uint64
}
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
meta
);
err
!=
nil
{
return
nil
,
common
.
Hash
{},
0
,
0
}
return
&
tx
,
meta
.
BlockHash
,
meta
.
BlockIndex
,
meta
.
Index
}
// GetReceipt returns a receipt by hash
func
GetReceipt
(
db
ethdb
.
Database
,
txHash
common
.
Hash
)
*
types
.
Receipt
{
data
,
_
:=
db
.
Get
(
append
(
receiptsPrefix
,
txHash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
}
var
receipt
types
.
ReceiptForStorage
err
:=
rlp
.
DecodeBytes
(
data
,
&
receipt
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Core
)
.
Infoln
(
"GetReceipt err:"
,
err
)
}
return
(
*
types
.
Receipt
)(
&
receipt
)
}
// WriteCanonicalHash stores the canonical hash for the given block number.
func
WriteCanonicalHash
(
db
ethdb
.
Database
,
hash
common
.
Hash
,
number
uint64
)
error
{
key
:=
append
(
blockNumPrefix
,
big
.
NewInt
(
int64
(
number
))
.
Bytes
()
...
)
...
...
@@ -329,6 +394,94 @@ func WriteBlock(db ethdb.Database, block *types.Block) error {
return
nil
}
// WriteBlockReceipts stores all the transaction receipts belonging to a block
// as a single receipt slice. This is used during chain reorganisations for
// rescheduling dropped transactions.
func
WriteBlockReceipts
(
db
ethdb
.
Database
,
hash
common
.
Hash
,
receipts
types
.
Receipts
)
error
{
// Convert the receipts into their storage form and serialize them
storageReceipts
:=
make
([]
*
types
.
ReceiptForStorage
,
len
(
receipts
))
for
i
,
receipt
:=
range
receipts
{
storageReceipts
[
i
]
=
(
*
types
.
ReceiptForStorage
)(
receipt
)
}
bytes
,
err
:=
rlp
.
EncodeToBytes
(
storageReceipts
)
if
err
!=
nil
{
return
err
}
// Store the flattened receipt slice
if
err
:=
db
.
Put
(
append
(
blockReceiptsPrefix
,
hash
.
Bytes
()
...
),
bytes
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to store block receipts into database: %v"
,
err
)
return
err
}
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"stored block receipts [%x…]"
,
hash
.
Bytes
()[
:
4
])
return
nil
}
// WriteTransactions stores the transactions associated with a specific block
// into the given database. Beside writing the transaction, the function also
// stores a metadata entry along with the transaction, detailing the position
// of this within the blockchain.
func
WriteTransactions
(
db
ethdb
.
Database
,
block
*
types
.
Block
)
error
{
batch
:=
db
.
NewBatch
()
// Iterate over each transaction and encode it with its metadata
for
i
,
tx
:=
range
block
.
Transactions
()
{
// Encode and queue up the transaction for storage
data
,
err
:=
rlp
.
EncodeToBytes
(
tx
)
if
err
!=
nil
{
return
err
}
if
err
:=
batch
.
Put
(
tx
.
Hash
()
.
Bytes
(),
data
);
err
!=
nil
{
return
err
}
// Encode and queue up the transaction metadata for storage
meta
:=
struct
{
BlockHash
common
.
Hash
BlockIndex
uint64
Index
uint64
}{
BlockHash
:
block
.
Hash
(),
BlockIndex
:
block
.
NumberU64
(),
Index
:
uint64
(
i
),
}
data
,
err
=
rlp
.
EncodeToBytes
(
meta
)
if
err
!=
nil
{
return
err
}
if
err
:=
batch
.
Put
(
append
(
tx
.
Hash
()
.
Bytes
(),
txMetaSuffix
...
),
data
);
err
!=
nil
{
return
err
}
}
// Write the scheduled data into the database
if
err
:=
batch
.
Write
();
err
!=
nil
{
glog
.
Fatalf
(
"failed to store transactions into database: %v"
,
err
)
return
err
}
return
nil
}
// WriteReceipts stores a batch of transaction receipts into the database.
func
WriteReceipts
(
db
ethdb
.
Database
,
receipts
types
.
Receipts
)
error
{
batch
:=
db
.
NewBatch
()
// Iterate over all the receipts and queue them for database injection
for
_
,
receipt
:=
range
receipts
{
storageReceipt
:=
(
*
types
.
ReceiptForStorage
)(
receipt
)
data
,
err
:=
rlp
.
EncodeToBytes
(
storageReceipt
)
if
err
!=
nil
{
return
err
}
if
err
:=
batch
.
Put
(
append
(
receiptsPrefix
,
receipt
.
TxHash
.
Bytes
()
...
),
data
);
err
!=
nil
{
return
err
}
}
// Write the scheduled data into the database
if
err
:=
batch
.
Write
();
err
!=
nil
{
glog
.
Fatalf
(
"failed to store receipts into database: %v"
,
err
)
return
err
}
return
nil
}
// DeleteCanonicalHash removes the number to hash canonical mapping.
func
DeleteCanonicalHash
(
db
ethdb
.
Database
,
number
uint64
)
{
db
.
Delete
(
append
(
blockNumPrefix
,
big
.
NewInt
(
int64
(
number
))
.
Bytes
()
...
))
...
...
@@ -351,18 +504,35 @@ func DeleteTd(db ethdb.Database, hash common.Hash) {
// DeleteBlock removes all block data associated with a hash.
func
DeleteBlock
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
{
DeleteBlockReceipts
(
db
,
hash
)
DeleteHeader
(
db
,
hash
)
DeleteBody
(
db
,
hash
)
DeleteTd
(
db
,
hash
)
}
// [deprecated by eth/63]
// DeleteBlockReceipts removes all receipt data associated with a block hash.
func
DeleteBlockReceipts
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
{
db
.
Delete
(
append
(
blockReceiptsPrefix
,
hash
.
Bytes
()
...
))
}
// DeleteTransaction removes all transaction data associated with a hash.
func
DeleteTransaction
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
{
db
.
Delete
(
hash
.
Bytes
())
db
.
Delete
(
append
(
hash
.
Bytes
(),
txMetaSuffix
...
))
}
// DeleteReceipt removes all receipt data associated with a transaction hash.
func
DeleteReceipt
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
{
db
.
Delete
(
append
(
receiptsPrefix
,
hash
.
Bytes
()
...
))
}
// [deprecated by the header/block split, remove eventually]
// GetBlockByHashOld returns the old combined block corresponding to the hash
// or nil if not found. This method is only used by the upgrade mechanism to
// access the old combined block representation. It will be dropped after the
// network transitions to eth/63.
func
GetBlockByHashOld
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
*
types
.
Block
{
data
,
_
:=
db
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
data
,
_
:=
db
.
Get
(
append
(
blockHashPre
fix
,
hash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
}
...
...
core/
chain
_util_test.go
→
core/
database
_util_test.go
View file @
7399b138
...
...
@@ -17,6 +17,7 @@
package
core
import
(
"bytes"
"encoding/json"
"io/ioutil"
"math/big"
...
...
@@ -341,6 +342,163 @@ func TestHeadStorage(t *testing.T) {
}
}
// Tests that transactions and associated metadata can be stored and retrieved.
func
TestTransactionStorage
(
t
*
testing
.
T
)
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
tx1
:=
types
.
NewTransaction
(
1
,
common
.
BytesToAddress
([]
byte
{
0x11
}),
big
.
NewInt
(
111
),
big
.
NewInt
(
1111
),
big
.
NewInt
(
11111
),
[]
byte
{
0x11
,
0x11
,
0x11
})
tx2
:=
types
.
NewTransaction
(
2
,
common
.
BytesToAddress
([]
byte
{
0x22
}),
big
.
NewInt
(
222
),
big
.
NewInt
(
2222
),
big
.
NewInt
(
22222
),
[]
byte
{
0x22
,
0x22
,
0x22
})
tx3
:=
types
.
NewTransaction
(
3
,
common
.
BytesToAddress
([]
byte
{
0x33
}),
big
.
NewInt
(
333
),
big
.
NewInt
(
3333
),
big
.
NewInt
(
33333
),
[]
byte
{
0x33
,
0x33
,
0x33
})
txs
:=
[]
*
types
.
Transaction
{
tx1
,
tx2
,
tx3
}
block
:=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
314
)},
txs
,
nil
,
nil
)
// Check that no transactions entries are in a pristine database
for
i
,
tx
:=
range
txs
{
if
txn
,
_
,
_
,
_
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
!=
nil
{
t
.
Fatalf
(
"tx #%d [%x]: non existent transaction returned: %v"
,
i
,
tx
.
Hash
(),
txn
)
}
}
// Insert all the transactions into the database, and verify contents
if
err
:=
WriteTransactions
(
db
,
block
);
err
!=
nil
{
t
.
Fatalf
(
"failed to write transactions: %v"
,
err
)
}
for
i
,
tx
:=
range
txs
{
if
txn
,
hash
,
number
,
index
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
==
nil
{
t
.
Fatalf
(
"tx #%d [%x]: transaction not found"
,
i
,
tx
.
Hash
())
}
else
{
if
hash
!=
block
.
Hash
()
||
number
!=
block
.
NumberU64
()
||
index
!=
uint64
(
i
)
{
t
.
Fatalf
(
"tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v"
,
i
,
tx
.
Hash
(),
hash
,
number
,
index
,
block
.
Hash
(),
block
.
NumberU64
(),
i
)
}
if
tx
.
String
()
!=
txn
.
String
()
{
t
.
Fatalf
(
"tx #%d [%x]: transaction mismatch: have %v, want %v"
,
i
,
tx
.
Hash
(),
txn
,
tx
)
}
}
}
// Delete the transactions and check purge
for
i
,
tx
:=
range
txs
{
DeleteTransaction
(
db
,
tx
.
Hash
())
if
txn
,
_
,
_
,
_
:=
GetTransaction
(
db
,
tx
.
Hash
());
txn
!=
nil
{
t
.
Fatalf
(
"tx #%d [%x]: deleted transaction returned: %v"
,
i
,
tx
.
Hash
(),
txn
)
}
}
}
// Tests that receipts can be stored and retrieved.
func
TestReceiptStorage
(
t
*
testing
.
T
)
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
receipt1
:=
&
types
.
Receipt
{
PostState
:
[]
byte
{
0x01
},
CumulativeGasUsed
:
big
.
NewInt
(
1
),
Logs
:
vm
.
Logs
{
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x11
,
0x11
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
big
.
NewInt
(
111111
),
}
receipt2
:=
&
types
.
Receipt
{
PostState
:
[]
byte
{
0x02
},
CumulativeGasUsed
:
big
.
NewInt
(
2
),
Logs
:
vm
.
Logs
{
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x22
,
0x22
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
big
.
NewInt
(
222222
),
}
receipts
:=
[]
*
types
.
Receipt
{
receipt1
,
receipt2
}
// Check that no receipt entries are in a pristine database
for
i
,
receipt
:=
range
receipts
{
if
r
:=
GetReceipt
(
db
,
receipt
.
TxHash
);
r
!=
nil
{
t
.
Fatalf
(
"receipt #%d [%x]: non existent receipt returned: %v"
,
i
,
receipt
.
TxHash
,
r
)
}
}
// Insert all the receipts into the database, and verify contents
if
err
:=
WriteReceipts
(
db
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
"failed to write receipts: %v"
,
err
)
}
for
i
,
receipt
:=
range
receipts
{
if
r
:=
GetReceipt
(
db
,
receipt
.
TxHash
);
r
==
nil
{
t
.
Fatalf
(
"receipt #%d [%x]: receipt not found"
,
i
,
receipt
.
TxHash
)
}
else
{
rlpHave
,
_
:=
rlp
.
EncodeToBytes
(
r
)
rlpWant
,
_
:=
rlp
.
EncodeToBytes
(
receipt
)
if
bytes
.
Compare
(
rlpHave
,
rlpWant
)
!=
0
{
t
.
Fatalf
(
"receipt #%d [%x]: receipt mismatch: have %v, want %v"
,
i
,
receipt
.
TxHash
,
r
,
receipt
)
}
}
}
// Delete the receipts and check purge
for
i
,
receipt
:=
range
receipts
{
DeleteReceipt
(
db
,
receipt
.
TxHash
)
if
r
:=
GetReceipt
(
db
,
receipt
.
TxHash
);
r
!=
nil
{
t
.
Fatalf
(
"receipt #%d [%x]: deleted receipt returned: %v"
,
i
,
receipt
.
TxHash
,
r
)
}
}
}
// Tests that receipts associated with a single block can be stored and retrieved.
func
TestBlockReceiptStorage
(
t
*
testing
.
T
)
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
receipt1
:=
&
types
.
Receipt
{
PostState
:
[]
byte
{
0x01
},
CumulativeGasUsed
:
big
.
NewInt
(
1
),
Logs
:
vm
.
Logs
{
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x11
})},
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x11
,
0x11
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x01
,
0x11
,
0x11
}),
GasUsed
:
big
.
NewInt
(
111111
),
}
receipt2
:=
&
types
.
Receipt
{
PostState
:
[]
byte
{
0x02
},
CumulativeGasUsed
:
big
.
NewInt
(
2
),
Logs
:
vm
.
Logs
{
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x22
})},
&
vm
.
Log
{
Address
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
})},
},
TxHash
:
common
.
BytesToHash
([]
byte
{
0x22
,
0x22
}),
ContractAddress
:
common
.
BytesToAddress
([]
byte
{
0x02
,
0x22
,
0x22
}),
GasUsed
:
big
.
NewInt
(
222222
),
}
receipts
:=
[]
*
types
.
Receipt
{
receipt1
,
receipt2
}
// Check that no receipt entries are in a pristine database
hash
:=
common
.
BytesToHash
([]
byte
{
0x03
,
0x14
})
if
rs
:=
GetBlockReceipts
(
db
,
hash
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"non existent receipts returned: %v"
,
rs
)
}
// Insert the receipt slice into the database and check presence
if
err
:=
WriteBlockReceipts
(
db
,
hash
,
receipts
);
err
!=
nil
{
t
.
Fatalf
(
"failed to write block receipts: %v"
,
err
)
}
if
rs
:=
GetBlockReceipts
(
db
,
hash
);
len
(
rs
)
==
0
{
t
.
Fatalf
(
"no receipts returned"
)
}
else
{
for
i
:=
0
;
i
<
len
(
receipts
);
i
++
{
rlpHave
,
_
:=
rlp
.
EncodeToBytes
(
rs
[
i
])
rlpWant
,
_
:=
rlp
.
EncodeToBytes
(
receipts
[
i
])
if
bytes
.
Compare
(
rlpHave
,
rlpWant
)
!=
0
{
t
.
Fatalf
(
"receipt #%d: receipt mismatch: have %v, want %v"
,
i
,
rs
[
i
],
receipts
[
i
])
}
}
}
// Delete the receipt slice and check purge
DeleteBlockReceipts
(
db
,
hash
)
if
rs
:=
GetBlockReceipts
(
db
,
hash
);
len
(
rs
)
!=
0
{
t
.
Fatalf
(
"deleted receipts returned: %v"
,
rs
)
}
}
func
TestMipmapBloom
(
t
*
testing
.
T
)
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
...
...
@@ -425,7 +583,7 @@ func TestMipmapChain(t *testing.T) {
}
// store the receipts
err
:=
Put
Receipts
(
db
,
receipts
)
err
:=
Write
Receipts
(
db
,
receipts
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -439,7 +597,7 @@ func TestMipmapChain(t *testing.T) {
if
err
:=
WriteHeadBlockHash
(
db
,
block
.
Hash
());
err
!=
nil
{
t
.
Fatalf
(
"failed to insert block number: %v"
,
err
)
}
if
err
:=
Put
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
if
err
:=
Write
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
t
.
Fatal
(
"error writing block receipts:"
,
err
)
}
}
...
...
core/genesis.go
View file @
7399b138
...
...
@@ -103,7 +103,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
if
err
:=
WriteBlock
(
chainDb
,
block
);
err
!=
nil
{
return
nil
,
err
}
if
err
:=
Put
BlockReceipts
(
chainDb
,
block
.
Hash
(),
nil
);
err
!=
nil
{
if
err
:=
Write
BlockReceipts
(
chainDb
,
block
.
Hash
(),
nil
);
err
!=
nil
{
return
nil
,
err
}
if
err
:=
WriteCanonicalHash
(
chainDb
,
block
.
Hash
(),
block
.
NumberU64
());
err
!=
nil
{
...
...
core/transaction_util.go
deleted
100644 → 0
View file @
65bb07fb
// Copyright 2015 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
core
import
(
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
"github.com/syndtr/goleveldb/leveldb"
)
var
(
receiptsPre
=
[]
byte
(
"receipts-"
)
blockReceiptsPre
=
[]
byte
(
"receipts-block-"
)
)
// PutTransactions stores the transactions in the given database
func
PutTransactions
(
db
ethdb
.
Database
,
block
*
types
.
Block
,
txs
types
.
Transactions
)
error
{
batch
:=
db
.
NewBatch
()
for
i
,
tx
:=
range
block
.
Transactions
()
{
rlpEnc
,
err
:=
rlp
.
EncodeToBytes
(
tx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed encoding tx: %v"
,
err
)
}
batch
.
Put
(
tx
.
Hash
()
.
Bytes
(),
rlpEnc
)
var
txExtra
struct
{
BlockHash
common
.
Hash
BlockIndex
uint64
Index
uint64
}
txExtra
.
BlockHash
=
block
.
Hash
()
txExtra
.
BlockIndex
=
block
.
NumberU64
()
txExtra
.
Index
=
uint64
(
i
)
rlpMeta
,
err
:=
rlp
.
EncodeToBytes
(
txExtra
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed encoding tx meta data: %v"
,
err
)
}
batch
.
Put
(
append
(
tx
.
Hash
()
.
Bytes
(),
0x0001
),
rlpMeta
)
}
if
err
:=
batch
.
Write
();
err
!=
nil
{
return
fmt
.
Errorf
(
"failed writing tx to db: %v"
,
err
)
}
return
nil
}
func
DeleteTransaction
(
db
ethdb
.
Database
,
txHash
common
.
Hash
)
{
db
.
Delete
(
txHash
[
:
])
}
func
GetTransaction
(
db
ethdb
.
Database
,
txhash
common
.
Hash
)
*
types
.
Transaction
{
data
,
_
:=
db
.
Get
(
txhash
[
:
])
if
len
(
data
)
!=
0
{
var
tx
types
.
Transaction
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
tx
);
err
!=
nil
{
return
nil
}
return
&
tx
}
return
nil
}
// PutReceipts stores the receipts in the current database
func
PutReceipts
(
db
ethdb
.
Database
,
receipts
types
.
Receipts
)
error
{
batch
:=
new
(
leveldb
.
Batch
)
_
,
batchWrite
:=
db
.
(
*
ethdb
.
LDBDatabase
)
for
_
,
receipt
:=
range
receipts
{
storageReceipt
:=
(
*
types
.
ReceiptForStorage
)(
receipt
)
bytes
,
err
:=
rlp
.
EncodeToBytes
(
storageReceipt
)
if
err
!=
nil
{
return
err
}
if
batchWrite
{
batch
.
Put
(
append
(
receiptsPre
,
receipt
.
TxHash
[
:
]
...
),
bytes
)
}
else
{
err
=
db
.
Put
(
append
(
receiptsPre
,
receipt
.
TxHash
[
:
]
...
),
bytes
)
if
err
!=
nil
{
return
err
}
}
}
if
db
,
ok
:=
db
.
(
*
ethdb
.
LDBDatabase
);
ok
{
if
err
:=
db
.
LDB
()
.
Write
(
batch
,
nil
);
err
!=
nil
{
return
err
}
}
return
nil
}
// Delete a receipts from the database
func
DeleteReceipt
(
db
ethdb
.
Database
,
txHash
common
.
Hash
)
{
db
.
Delete
(
append
(
receiptsPre
,
txHash
[
:
]
...
))
}
// GetReceipt returns a receipt by hash
func
GetReceipt
(
db
ethdb
.
Database
,
txHash
common
.
Hash
)
*
types
.
Receipt
{
data
,
_
:=
db
.
Get
(
append
(
receiptsPre
,
txHash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
}
var
receipt
types
.
ReceiptForStorage
err
:=
rlp
.
DecodeBytes
(
data
,
&
receipt
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Core
)
.
Infoln
(
"GetReceipt err:"
,
err
)
}
return
(
*
types
.
Receipt
)(
&
receipt
)
}
// GetBlockReceipts returns the receipts generated by the transactions
// included in block's given hash.
func
GetBlockReceipts
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
types
.
Receipts
{
data
,
_
:=
db
.
Get
(
append
(
blockReceiptsPre
,
hash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
}
rs
:=
[]
*
types
.
ReceiptForStorage
{}
if
err
:=
rlp
.
DecodeBytes
(
data
,
&
rs
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"invalid receipt array RLP for hash %x: %v"
,
hash
,
err
)
return
nil
}
receipts
:=
make
(
types
.
Receipts
,
len
(
rs
))
for
i
,
receipt
:=
range
rs
{
receipts
[
i
]
=
(
*
types
.
Receipt
)(
receipt
)
}
return
receipts
}
// PutBlockReceipts stores the block's transactions associated receipts
// and stores them by block hash in a single slice. This is required for
// forks and chain reorgs
func
PutBlockReceipts
(
db
ethdb
.
Database
,
hash
common
.
Hash
,
receipts
types
.
Receipts
)
error
{
rs
:=
make
([]
*
types
.
ReceiptForStorage
,
len
(
receipts
))
for
i
,
receipt
:=
range
receipts
{
rs
[
i
]
=
(
*
types
.
ReceiptForStorage
)(
receipt
)
}
bytes
,
err
:=
rlp
.
EncodeToBytes
(
rs
)
if
err
!=
nil
{
return
err
}
err
=
db
.
Put
(
append
(
blockReceiptsPre
,
hash
[
:
]
...
),
bytes
)
if
err
!=
nil
{
return
err
}
return
nil
}
eth/backend_test.go
View file @
7399b138
...
...
@@ -32,7 +32,7 @@ func TestMipmapUpgrade(t *testing.T) {
}
// store the receipts
err
:=
core
.
Put
Receipts
(
db
,
receipts
)
err
:=
core
.
Write
Receipts
(
db
,
receipts
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -45,7 +45,7 @@ func TestMipmapUpgrade(t *testing.T) {
if
err
:=
core
.
WriteHeadBlockHash
(
db
,
block
.
Hash
());
err
!=
nil
{
t
.
Fatalf
(
"failed to insert block number: %v"
,
err
)
}
if
err
:=
core
.
Put
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
if
err
:=
core
.
Write
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
t
.
Fatal
(
"error writing block receipts:"
,
err
)
}
}
...
...
eth/filters/filter_test.go
View file @
7399b138
...
...
@@ -64,7 +64,7 @@ func BenchmarkMipmaps(b *testing.B) {
}
// store the receipts
err
:=
core
.
Put
Receipts
(
db
,
receipts
)
err
:=
core
.
Write
Receipts
(
db
,
receipts
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
...
...
@@ -78,7 +78,7 @@ func BenchmarkMipmaps(b *testing.B) {
if
err
:=
core
.
WriteHeadBlockHash
(
db
,
block
.
Hash
());
err
!=
nil
{
b
.
Fatalf
(
"failed to insert block number: %v"
,
err
)
}
if
err
:=
core
.
Put
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
if
err
:=
core
.
Write
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
b
.
Fatal
(
"error writing block receipts:"
,
err
)
}
}
...
...
@@ -163,7 +163,7 @@ func TestFilters(t *testing.T) {
}
// store the receipts
err
:=
core
.
Put
Receipts
(
db
,
receipts
)
err
:=
core
.
Write
Receipts
(
db
,
receipts
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -180,7 +180,7 @@ func TestFilters(t *testing.T) {
if
err
:=
core
.
WriteHeadBlockHash
(
db
,
block
.
Hash
());
err
!=
nil
{
t
.
Fatalf
(
"failed to insert block number: %v"
,
err
)
}
if
err
:=
core
.
Put
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
if
err
:=
core
.
Write
BlockReceipts
(
db
,
block
.
Hash
(),
receipts
[
i
]);
err
!=
nil
{
t
.
Fatal
(
"error writing block receipts:"
,
err
)
}
}
...
...
miner/worker.go
View file @
7399b138
...
...
@@ -305,9 +305,9 @@ func (self *worker) wait() {
// check if canon block and write transactions
if
stat
==
core
.
CanonStatTy
{
// This puts transactions in a extra db for rpc
core
.
PutTransactions
(
self
.
chainDb
,
block
,
block
.
Transactions
()
)
core
.
WriteTransactions
(
self
.
chainDb
,
block
)
// store the receipts
core
.
Put
Receipts
(
self
.
chainDb
,
work
.
receipts
)
core
.
Write
Receipts
(
self
.
chainDb
,
work
.
receipts
)
// Write map map bloom filters
core
.
WriteMipmapBloom
(
self
.
chainDb
,
block
.
NumberU64
(),
work
.
receipts
)
}
...
...
@@ -320,7 +320,7 @@ func (self *worker) wait() {
self
.
mux
.
Post
(
core
.
ChainHeadEvent
{
block
})
self
.
mux
.
Post
(
logs
)
}
if
err
:=
core
.
Put
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
if
err
:=
core
.
Write
BlockReceipts
(
self
.
chainDb
,
block
.
Hash
(),
receipts
);
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infoln
(
"error writing block receipts:"
,
err
)
}
}(
block
,
work
.
state
.
Logs
(),
work
.
receipts
)
...
...
xeth/xeth.go
View file @
7399b138
...
...
@@ -322,44 +322,11 @@ func (self *XEth) EthBlockByHash(strHash string) *types.Block {
return
block
}
func
(
self
*
XEth
)
EthTransactionByHash
(
hash
string
)
(
tx
*
types
.
Transaction
,
blhash
common
.
Hash
,
blnum
*
big
.
Int
,
txi
uint64
)
{
// Due to increasing return params and need to determine if this is from transaction pool or
// some chain, this probably needs to be refactored for more expressiveness
data
,
_
:=
self
.
backend
.
ChainDb
()
.
Get
(
common
.
FromHex
(
hash
))
if
len
(
data
)
!=
0
{
dtx
:=
new
(
types
.
Transaction
)
if
err
:=
rlp
.
DecodeBytes
(
data
,
dtx
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infoln
(
err
)
return
}
tx
=
dtx
}
else
{
// check pending transactions
tx
=
self
.
backend
.
TxPool
()
.
GetTransaction
(
common
.
HexToHash
(
hash
))
}
// meta
var
txExtra
struct
{
BlockHash
common
.
Hash
BlockIndex
uint64
Index
uint64
}
v
,
dberr
:=
self
.
backend
.
ChainDb
()
.
Get
(
append
(
common
.
FromHex
(
hash
),
0x0001
))
// TODO check specifically for ErrNotFound
if
dberr
!=
nil
{
return
func
(
self
*
XEth
)
EthTransactionByHash
(
hash
string
)
(
*
types
.
Transaction
,
common
.
Hash
,
uint64
,
uint64
)
{
if
tx
,
hash
,
number
,
index
:=
core
.
GetTransaction
(
self
.
backend
.
ChainDb
(),
common
.
HexToHash
(
hash
));
tx
!=
nil
{
return
tx
,
hash
,
number
,
index
}
r
:=
bytes
.
NewReader
(
v
)
err
:=
rlp
.
Decode
(
r
,
&
txExtra
)
if
err
==
nil
{
blhash
=
txExtra
.
BlockHash
blnum
=
big
.
NewInt
(
int64
(
txExtra
.
BlockIndex
))
txi
=
txExtra
.
Index
}
else
{
glog
.
V
(
logger
.
Error
)
.
Infoln
(
err
)
}
return
return
self
.
backend
.
TxPool
()
.
GetTransaction
(
common
.
HexToHash
(
hash
)),
common
.
Hash
{},
0
,
0
}
func
(
self
*
XEth
)
BlockByNumber
(
num
int64
)
*
Block
{
...
...
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