Commit 1c872ddf authored by obscuren's avatar obscuren

Changed how logs are being recorded

Logs are now recorded per transactions instead of tossing them out after
each transaction. This should also fix an issue with
`eth_getFilterLogs` (#629) Also now implemented are the `transactionHash,
blockHash, transactionIndex, logIndex` on logs. Closes #654.
parent 6284604b
...@@ -73,7 +73,7 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block ...@@ -73,7 +73,7 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
// If we are mining this block and validating we want to set the logs back to 0 // If we are mining this block and validating we want to set the logs back to 0
statedb.EmptyLogs() //statedb.EmptyLogs()
cb := statedb.GetStateObject(coinbase.Address()) cb := statedb.GetStateObject(coinbase.Address())
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb) _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
...@@ -89,7 +89,9 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -89,7 +89,9 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas)) cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative) receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative)
receipt.SetLogs(statedb.Logs())
logs := statedb.GetLogs(tx.Hash())
receipt.SetLogs(logs)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
glog.V(logger.Debug).Infoln(receipt) glog.V(logger.Debug).Infoln(receipt)
...@@ -97,7 +99,6 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -97,7 +99,6 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers // Notify all subscribers
if !transientProcess { if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(TxPostEvent{tx})
logs := statedb.Logs()
go self.eventMux.Post(logs) go self.eventMux.Post(logs)
} }
...@@ -115,7 +116,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state ...@@ -115,7 +116,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
cumulativeSum = new(big.Int) cumulativeSum = new(big.Int)
) )
for _, tx := range txs { for i, tx := range txs {
statedb.StartRecord(tx.Hash(), block.Hash(), i)
receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess) receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, err return nil, err
......
...@@ -124,17 +124,17 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { ...@@ -124,17 +124,17 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
// Filter the logs for interesting stuff // Filter the logs for interesting stuff
Logs: Logs:
for _, log := range logs { for _, log := range logs {
if len(self.address) > 0 && !includes(self.address, log.Address()) { if len(self.address) > 0 && !includes(self.address, log.Address) {
continue continue
} }
logTopics := make([]common.Hash, len(self.topics)) logTopics := make([]common.Hash, len(self.topics))
copy(logTopics, log.Topics()) copy(logTopics, log.Topics)
for i, topics := range self.topics { for i, topics := range self.topics {
for _, topic := range topics { for _, topic := range topics {
var match bool var match bool
if log.Topics()[i] == topic { if log.Topics[i] == topic {
match = true match = true
} }
if !match { if !match {
......
...@@ -8,87 +8,31 @@ import ( ...@@ -8,87 +8,31 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
type Log interface { type Log struct {
Address() common.Address Address common.Address
Topics() []common.Hash Topics []common.Hash
Data() []byte Data []byte
Number uint64
Number() uint64 TxHash common.Hash
TxIndex uint
BlockHash common.Hash
Index uint
} }
type StateLog struct { func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *Log {
address common.Address return &Log{Address: address, Topics: topics, Data: data, Number: number}
topics []common.Hash
data []byte
number uint64
} }
func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *StateLog { func (self *Log) EncodeRLP(w io.Writer) error {
return &StateLog{address, topics, data, number} return rlp.Encode(w, []interface{}{self.Address, self.Topics, self.Data})
} }
func (self *StateLog) Address() common.Address { func (self *Log) String() string {
return self.address return fmt.Sprintf(`log: %x %x %x`, self.Address, self.Topics, self.Data)
} }
func (self *StateLog) Topics() []common.Hash { type Logs []*Log
return self.topics
}
func (self *StateLog) Data() []byte {
return self.data
}
func (self *StateLog) Number() uint64 {
return self.number
}
/*
func NewLogFromValue(decoder *common.Value) *StateLog {
var extlog struct {
}
log := &StateLog{
address: decoder.Get(0).Bytes(),
data: decoder.Get(2).Bytes(),
}
it := decoder.Get(1).NewIterator()
for it.Next() {
log.topics = append(log.topics, it.Value().Bytes())
}
return log
}
*/
func (self *StateLog) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, []interface{}{self.address, self.topics, self.data})
}
/*
func (self *StateLog) RlpData() interface{} {
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
}
*/
func (self *StateLog) String() string {
return fmt.Sprintf(`log: %x %x %x`, self.address, self.topics, self.data)
}
type Logs []Log
/*
func (self Logs) RlpData() interface{} {
data := make([]interface{}, len(self))
for i, log := range self {
data[i] = log.RlpData()
}
return data
}
*/
func (self Logs) String() (ret string) { func (self Logs) String() (ret string) {
for _, log := range self { for _, log := range self {
......
...@@ -23,30 +23,53 @@ type StateDB struct { ...@@ -23,30 +23,53 @@ type StateDB struct {
refund map[string]*big.Int refund map[string]*big.Int
logs Logs thash, bhash common.Hash
txIndex int
logs map[common.Hash]Logs
} }
// Create a new state from a given trie // Create a new state from a given trie
func New(root common.Hash, db common.Database) *StateDB { func New(root common.Hash, db common.Database) *StateDB {
trie := trie.NewSecure(root[:], db) trie := trie.NewSecure(root[:], db)
return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int)} return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int), logs: make(map[common.Hash]Logs)}
} }
func (self *StateDB) PrintRoot() { func (self *StateDB) PrintRoot() {
self.trie.Trie.PrintRoot() self.trie.Trie.PrintRoot()
} }
func (self *StateDB) EmptyLogs() { func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
self.logs = nil self.thash = thash
self.bhash = bhash
self.txIndex = ti
} }
func (self *StateDB) AddLog(log Log) { func (self *StateDB) AddLog(log *Log) {
self.logs = append(self.logs, log) log.TxHash = self.thash
log.BlockHash = self.bhash
log.TxIndex = uint(self.txIndex)
self.logs[self.thash] = append(self.logs[self.thash], log)
}
func (self *StateDB) GetLogs(hash common.Hash) Logs {
return self.logs[hash]
} }
func (self *StateDB) Logs() Logs { func (self *StateDB) Logs() Logs {
var logs Logs
for _, lgs := range self.logs {
logs = append(logs, lgs...)
}
return logs
}
/*
func (self *StateDB) Logs(txHash, blockHash common.Hash, txIndex uint) Logs {
self.logs.SetInfo(txHash, blockHash, txIndex)
return self.logs return self.logs
} }
*/
func (self *StateDB) Refund(address common.Address, gas *big.Int) { func (self *StateDB) Refund(address common.Address, gas *big.Int) {
addr := address.Str() addr := address.Str()
...@@ -253,9 +276,10 @@ func (self *StateDB) Copy() *StateDB { ...@@ -253,9 +276,10 @@ func (self *StateDB) Copy() *StateDB {
state.refund[addr] = new(big.Int).Set(refund) state.refund[addr] = new(big.Int).Set(refund)
} }
logs := make(Logs, len(self.logs)) for hash, logs := range self.logs {
copy(logs, self.logs) state.logs[hash] = make(Logs, len(logs))
state.logs = logs copy(state.logs[hash], logs)
}
return state return state
} }
......
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
) )
func CreateBloom(receipts Receipts) Bloom { func CreateBloom(receipts Receipts) Bloom {
...@@ -20,10 +20,10 @@ func CreateBloom(receipts Receipts) Bloom { ...@@ -20,10 +20,10 @@ func CreateBloom(receipts Receipts) Bloom {
func LogsBloom(logs state.Logs) *big.Int { func LogsBloom(logs state.Logs) *big.Int {
bin := new(big.Int) bin := new(big.Int)
for _, log := range logs { for _, log := range logs {
data := make([]common.Hash, len(log.Topics())) data := make([]common.Hash, len(log.Topics))
bin.Or(bin, bloom9(log.Address().Bytes())) bin.Or(bin, bloom9(log.Address.Bytes()))
for i, topic := range log.Topics() { for i, topic := range log.Topics {
data[i] = topic data[i] = topic
} }
......
...@@ -7,8 +7,8 @@ import ( ...@@ -7,8 +7,8 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/rlp"
) )
type Receipt struct { type Receipt struct {
...@@ -30,12 +30,6 @@ func (self *Receipt) EncodeRLP(w io.Writer) error { ...@@ -30,12 +30,6 @@ 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) RlpData() interface{} {
return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()}
}
*/
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 {
...@@ -58,17 +52,6 @@ func (self *Receipt) String() string { ...@@ -58,17 +52,6 @@ func (self *Receipt) String() string {
type Receipts []*Receipt type Receipts []*Receipt
/*
func (self Receipts) RlpData() interface{} {
data := make([]interface{}, len(self))
for i, receipt := range self {
data[i] = receipt.RlpData()
}
return data
}
*/
func (self Receipts) RlpEncode() []byte { func (self Receipts) RlpEncode() []byte {
bytes, err := rlp.EncodeToBytes(self) bytes, err := rlp.EncodeToBytes(self)
if err != nil { if err != nil {
......
...@@ -22,7 +22,7 @@ type Environment interface { ...@@ -22,7 +22,7 @@ type Environment interface {
Difficulty() *big.Int Difficulty() *big.Int
GasLimit() *big.Int GasLimit() *big.Int
Transfer(from, to Account, amount *big.Int) error Transfer(from, to Account, amount *big.Int) error
AddLog(state.Log) AddLog(*state.Log)
VmType() Type VmType() Type
......
...@@ -557,7 +557,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { ...@@ -557,7 +557,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
} }
data := mem.Get(mStart.Int64(), mSize.Int64()) data := mem.Get(mStart.Int64(), mSize.Int64())
log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()} log := state.NewLog(context.Address(), topics, data, self.env.BlockNumber().Uint64())
//log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()}
self.env.AddLog(log) self.env.AddLog(log)
self.Printf(" => %v", log) self.Printf(" => %v", log)
......
...@@ -47,7 +47,7 @@ func (self *VMEnv) GetHash(n uint64) common.Hash { ...@@ -47,7 +47,7 @@ func (self *VMEnv) GetHash(n uint64) common.Hash {
return common.Hash{} return common.Hash{}
} }
func (self *VMEnv) AddLog(log state.Log) { func (self *VMEnv) AddLog(log *state.Log) {
self.state.AddLog(log) self.state.AddLog(log)
} }
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error { func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
......
...@@ -266,6 +266,8 @@ func (self *worker) commitNewWork() { ...@@ -266,6 +266,8 @@ func (self *worker) commitNewWork() {
) )
gasLimit: gasLimit:
for i, tx := range transactions { for i, tx := range transactions {
self.current.state.StartRecord(tx.Hash(), common.Hash{}, 0)
err := self.commitTransaction(tx) err := self.commitTransaction(tx)
switch { switch {
case core.IsNonceErr(err) || core.IsInvalidTxErr(err): case core.IsNonceErr(err) || core.IsInvalidTxErr(err):
......
...@@ -284,15 +284,19 @@ type LogRes struct { ...@@ -284,15 +284,19 @@ type LogRes struct {
TransactionIndex *hexnum `json:"transactionIndex"` TransactionIndex *hexnum `json:"transactionIndex"`
} }
func NewLogRes(log state.Log) LogRes { func NewLogRes(log *state.Log) LogRes {
var l LogRes var l LogRes
l.Topics = make([]*hexdata, len(log.Topics())) l.Topics = make([]*hexdata, len(log.Topics))
for j, topic := range log.Topics() { for j, topic := range log.Topics {
l.Topics[j] = newHexData(topic) l.Topics[j] = newHexData(topic)
} }
l.Address = newHexData(log.Address()) l.Address = newHexData(log.Address)
l.Data = newHexData(log.Data()) l.Data = newHexData(log.Data)
l.BlockNumber = newHexNum(log.Number()) l.BlockNumber = newHexNum(log.Number)
l.LogIndex = newHexNum(log.Index)
l.TransactionHash = newHexData(log.TxHash)
l.TransactionIndex = newHexNum(log.TxIndex)
l.BlockHash = newHexData(log.BlockHash)
return l return l
} }
......
...@@ -393,7 +393,7 @@ func (self *XEth) NewFilterString(word string) int { ...@@ -393,7 +393,7 @@ func (self *XEth) NewFilterString(word string) int {
self.logMut.Lock() self.logMut.Lock()
defer self.logMut.Unlock() defer self.logMut.Unlock()
self.logs[id].add(&state.StateLog{}) self.logs[id].add(&state.Log{})
} }
case "latest": case "latest":
filter.BlockCallback = func(block *types.Block, logs state.Logs) { filter.BlockCallback = func(block *types.Block, logs state.Logs) {
...@@ -403,7 +403,7 @@ func (self *XEth) NewFilterString(word string) int { ...@@ -403,7 +403,7 @@ func (self *XEth) NewFilterString(word string) int {
for _, log := range logs { for _, log := range logs {
self.logs[id].add(log) self.logs[id].add(log)
} }
self.logs[id].add(&state.StateLog{}) self.logs[id].add(&state.Log{})
} }
} }
...@@ -729,7 +729,7 @@ type logFilter struct { ...@@ -729,7 +729,7 @@ type logFilter struct {
id int id int
} }
func (l *logFilter) add(logs ...state.Log) { func (l *logFilter) add(logs ...*state.Log) {
l.logs = append(l.logs, logs...) l.logs = append(l.logs, logs...)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment