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
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
statedb.EmptyLogs()
//statedb.EmptyLogs()
cb := statedb.GetStateObject(coinbase.Address())
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
......@@ -89,7 +89,9 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
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})
glog.V(logger.Debug).Infoln(receipt)
......@@ -97,7 +99,6 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers
if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx})
logs := statedb.Logs()
go self.eventMux.Post(logs)
}
......@@ -115,7 +116,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
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)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, err
......
......@@ -124,17 +124,17 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
// Filter the logs for interesting stuff
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
}
logTopics := make([]common.Hash, len(self.topics))
copy(logTopics, log.Topics())
copy(logTopics, log.Topics)
for i, topics := range self.topics {
for _, topic := range topics {
var match bool
if log.Topics()[i] == topic {
if log.Topics[i] == topic {
match = true
}
if !match {
......
......@@ -8,87 +8,31 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
type Log interface {
Address() common.Address
Topics() []common.Hash
Data() []byte
type Log struct {
Address common.Address
Topics []common.Hash
Data []byte
Number uint64
Number() uint64
TxHash common.Hash
TxIndex uint
BlockHash common.Hash
Index uint
}
type StateLog struct {
address common.Address
topics []common.Hash
data []byte
number uint64
func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *Log {
return &Log{Address: address, Topics: topics, Data: data, Number: number}
}
func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *StateLog {
return &StateLog{address, topics, data, number}
func (self *Log) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, []interface{}{self.Address, self.Topics, self.Data})
}
func (self *StateLog) Address() common.Address {
return self.address
func (self *Log) String() string {
return fmt.Sprintf(`log: %x %x %x`, self.Address, self.Topics, self.Data)
}
func (self *StateLog) Topics() []common.Hash {
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
}
*/
type Logs []*Log
func (self Logs) String() (ret string) {
for _, log := range self {
......
......@@ -23,30 +23,53 @@ type StateDB struct {
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
func New(root common.Hash, db common.Database) *StateDB {
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() {
self.trie.Trie.PrintRoot()
}
func (self *StateDB) EmptyLogs() {
self.logs = nil
func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
self.thash = thash
self.bhash = bhash
self.txIndex = ti
}
func (self *StateDB) AddLog(log Log) {
self.logs = append(self.logs, log)
func (self *StateDB) AddLog(log *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 {
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
}
*/
func (self *StateDB) Refund(address common.Address, gas *big.Int) {
addr := address.Str()
......@@ -253,9 +276,10 @@ func (self *StateDB) Copy() *StateDB {
state.refund[addr] = new(big.Int).Set(refund)
}
logs := make(Logs, len(self.logs))
copy(logs, self.logs)
state.logs = logs
for hash, logs := range self.logs {
state.logs[hash] = make(Logs, len(logs))
copy(state.logs[hash], logs)
}
return state
}
......
......@@ -4,8 +4,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
)
func CreateBloom(receipts Receipts) Bloom {
......@@ -20,10 +20,10 @@ func CreateBloom(receipts Receipts) Bloom {
func LogsBloom(logs state.Logs) *big.Int {
bin := new(big.Int)
for _, log := range logs {
data := make([]common.Hash, len(log.Topics()))
bin.Or(bin, bloom9(log.Address().Bytes()))
data := make([]common.Hash, len(log.Topics))
bin.Or(bin, bloom9(log.Address.Bytes()))
for i, topic := range log.Topics() {
for i, topic := range log.Topics {
data[i] = topic
}
......
......@@ -7,8 +7,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/rlp"
)
type Receipt struct {
......@@ -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})
}
/*
func (self *Receipt) RlpData() interface{} {
return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()}
}
*/
func (self *Receipt) RlpEncode() []byte {
bytes, err := rlp.EncodeToBytes(self)
if err != nil {
......@@ -58,17 +52,6 @@ func (self *Receipt) String() string {
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 {
bytes, err := rlp.EncodeToBytes(self)
if err != nil {
......
......@@ -22,7 +22,7 @@ type Environment interface {
Difficulty() *big.Int
GasLimit() *big.Int
Transfer(from, to Account, amount *big.Int) error
AddLog(state.Log)
AddLog(*state.Log)
VmType() Type
......
......@@ -557,7 +557,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
}
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.Printf(" => %v", log)
......
......@@ -47,7 +47,7 @@ func (self *VMEnv) GetHash(n uint64) common.Hash {
return common.Hash{}
}
func (self *VMEnv) AddLog(log state.Log) {
func (self *VMEnv) AddLog(log *state.Log) {
self.state.AddLog(log)
}
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
......
......@@ -266,6 +266,8 @@ func (self *worker) commitNewWork() {
)
gasLimit:
for i, tx := range transactions {
self.current.state.StartRecord(tx.Hash(), common.Hash{}, 0)
err := self.commitTransaction(tx)
switch {
case core.IsNonceErr(err) || core.IsInvalidTxErr(err):
......
......@@ -284,15 +284,19 @@ type LogRes struct {
TransactionIndex *hexnum `json:"transactionIndex"`
}
func NewLogRes(log state.Log) LogRes {
func NewLogRes(log *state.Log) LogRes {
var l LogRes
l.Topics = make([]*hexdata, len(log.Topics()))
for j, topic := range log.Topics() {
l.Topics = make([]*hexdata, len(log.Topics))
for j, topic := range log.Topics {
l.Topics[j] = newHexData(topic)
}
l.Address = newHexData(log.Address())
l.Data = newHexData(log.Data())
l.BlockNumber = newHexNum(log.Number())
l.Address = newHexData(log.Address)
l.Data = newHexData(log.Data)
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
}
......
......@@ -393,7 +393,7 @@ func (self *XEth) NewFilterString(word string) int {
self.logMut.Lock()
defer self.logMut.Unlock()
self.logs[id].add(&state.StateLog{})
self.logs[id].add(&state.Log{})
}
case "latest":
filter.BlockCallback = func(block *types.Block, logs state.Logs) {
......@@ -403,7 +403,7 @@ func (self *XEth) NewFilterString(word string) int {
for _, log := range logs {
self.logs[id].add(log)
}
self.logs[id].add(&state.StateLog{})
self.logs[id].add(&state.Log{})
}
}
......@@ -729,7 +729,7 @@ type logFilter struct {
id int
}
func (l *logFilter) add(logs ...state.Log) {
func (l *logFilter) add(logs ...*state.Log) {
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