mirror of https://github.com/status-im/op-geth.git
Merge pull request #1132 from obscuren/log_optimisations
core: log optimisations
This commit is contained in:
commit
03178a77b6
|
@ -102,7 +102,7 @@ window.filter = filter;
|
||||||
var amount = parseInt( value.value );
|
var amount = parseInt( value.value );
|
||||||
console.log("transact: ", to.value, " => ", amount)
|
console.log("transact: ", to.value, " => ", amount)
|
||||||
|
|
||||||
contract.sendTransaction({from: eth.accounts[0]}).send( to.value, amount );
|
contract.send.sendTransaction(to.value, amount ,{from: eth.accounts[0]});
|
||||||
|
|
||||||
to.value = "";
|
to.value = "";
|
||||||
value.value = "";
|
value.value = "";
|
||||||
|
|
|
@ -40,11 +40,6 @@ type BlockProcessor struct {
|
||||||
|
|
||||||
txpool *TxPool
|
txpool *TxPool
|
||||||
|
|
||||||
// The last attempted block is mainly used for debugging purposes
|
|
||||||
// This does not have to be a valid block and will be set during
|
|
||||||
// 'Process' & canonical validation.
|
|
||||||
lastAttemptedBlock *types.Block
|
|
||||||
|
|
||||||
events event.Subscription
|
events event.Subscription
|
||||||
|
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
|
@ -188,8 +183,6 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) {
|
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) {
|
||||||
sm.lastAttemptedBlock = block
|
|
||||||
|
|
||||||
// Create a new state based on the parent's root (e.g., create copy)
|
// Create a new state based on the parent's root (e.g., create copy)
|
||||||
state := state.New(parent.Root(), sm.db)
|
state := state.New(parent.Root(), sm.db)
|
||||||
|
|
||||||
|
@ -255,6 +248,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store the receipts
|
||||||
|
err = putReceipts(sm.extraDb, block.Hash(), receipts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the td for this block
|
// Calculate the td for this block
|
||||||
//td = CalculateTD(block, parent)
|
//td = CalculateTD(block, parent)
|
||||||
// Sync the current block's state to the database
|
// Sync the current block's state to the database
|
||||||
|
@ -268,23 +267,9 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
|
||||||
putTx(sm.extraDb, tx, block, uint64(i))
|
putTx(sm.extraDb, tx, block, uint64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
receiptsRlp := block.Receipts().RlpEncode()
|
|
||||||
sm.extraDb.Put(append(receiptsPre, block.Hash().Bytes()...), receiptsRlp)
|
|
||||||
|
|
||||||
return state.Logs(), nil
|
return state.Logs(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) {
|
|
||||||
var rdata []byte
|
|
||||||
rdata, err = self.extraDb.Get(append(receiptsPre, bhash[:]...))
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
err = rlp.DecodeBytes(rdata, &receipts)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// See YP section 4.3.4. "Block Header Validity"
|
// See YP section 4.3.4. "Block Header Validity"
|
||||||
// Validates a block. Returns an error if the block is invalid.
|
// Validates a block. Returns an error if the block is invalid.
|
||||||
func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error {
|
func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error {
|
||||||
|
@ -391,13 +376,25 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlockReceipts returns the receipts beloniging to the block hash
|
||||||
|
func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) {
|
||||||
|
return getBlockReceipts(sm.extraDb, bhash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLogs returns the logs of the given block. This method is using a two step approach
|
||||||
|
// where it tries to get it from the (updated) method which gets them from the receipts or
|
||||||
|
// the depricated way by re-processing the block.
|
||||||
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
|
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
|
||||||
if !sm.bc.HasBlock(block.Header().ParentHash) {
|
receipts, err := sm.GetBlockReceipts(block.Hash())
|
||||||
return nil, ParentError(block.Header().ParentHash)
|
if err == nil && len(receipts) > 0 {
|
||||||
|
// coalesce logs
|
||||||
|
for _, receipt := range receipts {
|
||||||
|
logs = append(logs, receipt.Logs()...)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sm.lastAttemptedBlock = block
|
// TODO: remove backward compatibility
|
||||||
|
|
||||||
var (
|
var (
|
||||||
parent = sm.bc.GetBlock(block.Header().ParentHash)
|
parent = sm.bc.GetBlock(block.Header().ParentHash)
|
||||||
state = state.New(parent.Root(), sm.db)
|
state = state.New(parent.Root(), sm.db)
|
||||||
|
@ -408,6 +405,16 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
|
||||||
return state.Logs(), nil
|
return state.Logs(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) {
|
||||||
|
var rdata []byte
|
||||||
|
rdata, err = db.Get(append(receiptsPre, bhash[:]...))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
err = rlp.DecodeBytes(rdata, &receipts)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) {
|
func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) {
|
||||||
rlpEnc, err := rlp.EncodeToBytes(tx)
|
rlpEnc, err := rlp.EncodeToBytes(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -431,3 +438,19 @@ func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint
|
||||||
}
|
}
|
||||||
db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
|
db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func putReceipts(db common.Database, hash common.Hash, receipts types.Receipts) error {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Put(append(receiptsPre, hash[:]...), bytes)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"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/pow/ezp"
|
"github.com/ethereum/go-ethereum/pow/ezp"
|
||||||
|
@ -35,3 +37,33 @@ func TestNumber(t *testing.T) {
|
||||||
t.Errorf("didn't expect block number error")
|
t.Errorf("didn't expect block number error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPutReceipt(t *testing.T) {
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
|
var addr common.Address
|
||||||
|
addr[0] = 1
|
||||||
|
var hash common.Hash
|
||||||
|
hash[0] = 2
|
||||||
|
|
||||||
|
receipt := new(types.Receipt)
|
||||||
|
receipt.SetLogs(state.Logs{&state.Log{
|
||||||
|
Address: addr,
|
||||||
|
Topics: []common.Hash{hash},
|
||||||
|
Data: []byte("hi"),
|
||||||
|
Number: 42,
|
||||||
|
TxHash: hash,
|
||||||
|
TxIndex: 0,
|
||||||
|
BlockHash: hash,
|
||||||
|
Index: 0,
|
||||||
|
}})
|
||||||
|
|
||||||
|
putReceipts(db, hash, types.Receipts{receipt})
|
||||||
|
receipts, err := getBlockReceipts(db, hash)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("got err:", err)
|
||||||
|
}
|
||||||
|
if len(receipts) != 1 {
|
||||||
|
t.Error("expected to get 1 receipt, got", len(receipts))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,15 +29,22 @@ func (self *Log) EncodeRLP(w io.Writer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Log) String() string {
|
func (self *Log) String() string {
|
||||||
return fmt.Sprintf(`log: %x %x %x`, self.Address, self.Topics, self.Data)
|
return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, self.Address, self.Topics, self.Data, self.TxHash, self.TxIndex, self.BlockHash, self.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Logs []*Log
|
type Logs []*Log
|
||||||
|
|
||||||
func (self Logs) String() (ret string) {
|
type LogForStorage Log
|
||||||
for _, log := range self {
|
|
||||||
ret += fmt.Sprintf("%v", log)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "[" + ret + "]"
|
func (self *LogForStorage) EncodeRLP(w io.Writer) error {
|
||||||
|
return rlp.Encode(w, []interface{}{
|
||||||
|
self.Address,
|
||||||
|
self.Topics,
|
||||||
|
self.Data,
|
||||||
|
self.Number,
|
||||||
|
self.TxHash,
|
||||||
|
self.TxIndex,
|
||||||
|
self.BlockHash,
|
||||||
|
self.Index,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,39 @@ func (self *Receipt) SetLogs(logs state.Logs) {
|
||||||
self.logs = logs
|
self.logs = logs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Receipt) Logs() state.Logs {
|
||||||
|
return self.logs
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Receipt) EncodeRLP(w io.Writer) error {
|
func (self *Receipt) EncodeRLP(w io.Writer) error {
|
||||||
return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs})
|
return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
var r struct {
|
||||||
|
PostState []byte
|
||||||
|
CumulativeGasUsed *big.Int
|
||||||
|
Bloom Bloom
|
||||||
|
Logs state.Logs
|
||||||
|
}
|
||||||
|
if err := s.Decode(&r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs = r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReceiptForStorage Receipt
|
||||||
|
|
||||||
|
func (self *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
||||||
|
storageLogs := make([]*state.LogForStorage, len(self.logs))
|
||||||
|
for i, log := range self.logs {
|
||||||
|
storageLogs[i] = (*state.LogForStorage)(log)
|
||||||
|
}
|
||||||
|
return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, storageLogs})
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Receipt) RlpEncode() []byte {
|
func (self *Receipt) RlpEncode() []byte {
|
||||||
bytes, err := rlp.EncodeToBytes(self)
|
bytes, err := rlp.EncodeToBytes(self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue