From df5603de0a34e80a1af6ad03e37ce43728baad35 Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Thu, 30 Oct 2014 13:32:50 +0100
Subject: [PATCH] Moved logging to state, proper structured block

* Moved logs to state so it's subject to snapshotting
* Split up block header
* Removed logs from transactions and made them receipts only
---
 ethchain/block.go            | 42 ++++++++++++------------------------
 ethchain/bloom9.go           |  8 +++----
 ethchain/state_manager.go    |  7 ++++--
 ethchain/state_transition.go |  2 +-
 ethchain/transaction.go      | 13 +++--------
 ethchain/vm_env.go           |  4 ++--
 ethminer/miner.go            |  2 +-
 ethpipe/vm_env.go            |  2 +-
 {vm => ethstate}/log.go      |  2 +-
 ethstate/state.go            | 19 ++++++++++++++++
 utils/vm_env.go              |  2 +-
 vm/environment.go            |  6 +++++-
 vm/vm_debug.go               |  3 ++-
 13 files changed, 59 insertions(+), 53 deletions(-)
 rename {vm => ethstate}/log.go (97%)

diff --git a/ethchain/block.go b/ethchain/block.go
index b31d68e4d..a10da97ec 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -149,10 +149,7 @@ func (block *Block) Hash() ethutil.Bytes {
 }
 
 func (block *Block) HashNoNonce() []byte {
-	return ethcrypto.Sha3(ethutil.Encode([]interface{}{block.PrevHash,
-		block.UncleSha, block.Coinbase, block.state.Trie.Root,
-		block.ReceiptSha, block.Difficulty, block.Number, block.MinGasPrice,
-		block.GasLimit, block.GasUsed, block.Time, block.Extra}))
+	return ethcrypto.Sha3(ethutil.Encode(block.miningHeader()))
 }
 
 func (block *Block) State() *ethstate.State {
@@ -235,31 +232,18 @@ func (block *Block) rlpUncles() interface{} {
 
 func (block *Block) SetUncles(uncles []*Block) {
 	block.Uncles = uncles
-
 	block.UncleSha = ethcrypto.Sha3(ethutil.Encode(block.rlpUncles()))
 }
 
 func (self *Block) SetReceipts(receipts Receipts) {
 	self.receipts = receipts
-	self.SetReceiptHash(receipts)
+	self.ReceiptSha = DeriveSha(receipts)
+	self.LogsBloom = CreateBloom(self)
 }
 
 func (self *Block) SetTransactions(txs Transactions) {
-	self.setTransactions(txs)
-	self.SetTransactionHash(txs)
-}
-
-func (block *Block) setTransactions(txs Transactions) {
-	block.transactions = txs
-	block.LogsBloom = CreateBloom(block)
-}
-
-func (self *Block) SetTransactionHash(transactions Transactions) {
-	self.TxSha = DeriveSha(transactions)
-}
-
-func (self *Block) SetReceiptHash(receipts Receipts) {
-	self.ReceiptSha = DeriveSha(receipts)
+	self.transactions = txs
+	self.TxSha = DeriveSha(txs)
 }
 
 func (block *Block) Value() *ethutil.Value {
@@ -285,10 +269,10 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
 	if decoder.Get(1).IsNil() == false { // Yes explicitness
 		//receipts := decoder.Get(1)
 		//block.receipts = make([]*Receipt, receipts.Len())
-		it := decoder.Get(1).NewIterator()
-		block.transactions = make(Transactions, it.Len())
-		for it.Next() {
-			block.transactions[it.Idx()] = NewTransactionFromValue(it.Value())
+		txs := decoder.Get(1)
+		block.transactions = make(Transactions, txs.Len())
+		for i := 0; i < txs.Len(); i++ {
+			block.transactions[i] = NewTransactionFromValue(txs.Get(i))
 			//receipt := NewRecieptFromValue(receipts.Get(i))
 			//block.transactions[i] = receipt.Tx
 			//block.receipts[i] = receipt
@@ -347,7 +331,7 @@ func (self *Block) Receipts() []*Receipt {
 	return self.receipts
 }
 
-func (block *Block) header() []interface{} {
+func (block *Block) miningHeader() []interface{} {
 	return []interface{}{
 		// Sha of the previous block
 		block.PrevHash,
@@ -377,11 +361,13 @@ func (block *Block) header() []interface{} {
 		block.Time,
 		// Extra data
 		block.Extra,
-		// Block's Nonce for validation
-		block.Nonce,
 	}
 }
 
+func (block *Block) header() []interface{} {
+	return append(block.miningHeader(), block.Nonce)
+}
+
 func (block *Block) String() string {
 	return fmt.Sprintf(`
 	BLOCK(%x): Size: %v
diff --git a/ethchain/bloom9.go b/ethchain/bloom9.go
index 4028231a3..8fa7b6339 100644
--- a/ethchain/bloom9.go
+++ b/ethchain/bloom9.go
@@ -3,21 +3,21 @@ package ethchain
 import (
 	"math/big"
 
+	"github.com/ethereum/go-ethereum/ethstate"
 	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/ethereum/go-ethereum/vm"
 )
 
 func CreateBloom(block *Block) []byte {
 	bin := new(big.Int)
 	bin.Or(bin, bloom9(block.Coinbase))
-	for _, tx := range block.Transactions() {
-		bin.Or(bin, LogsBloom(tx.logs))
+	for _, receipt := range block.Receipts() {
+		bin.Or(bin, LogsBloom(receipt.logs))
 	}
 
 	return bin.Bytes()
 }
 
-func LogsBloom(logs []vm.Log) *big.Int {
+func LogsBloom(logs ethstate.Logs) *big.Int {
 	bin := new(big.Int)
 	for _, log := range logs {
 		data := [][]byte{log.Address}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 0fe7001c6..62970f621 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -145,6 +145,9 @@ func (self *StateManager) ProcessTransactions(coinbase *ethstate.StateObject, st
 
 done:
 	for i, tx := range txs {
+		// If we are mining this block and validating we want to set the logs back to 0
+		state.EmptyLogs()
+
 		txGas := new(big.Int).Set(tx.Gas)
 
 		cb := state.GetStateObject(coinbase.Address())
@@ -175,7 +178,7 @@ done:
 		txGas.Sub(txGas, st.gas)
 		cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
 		//receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
-		receipt := &Receipt{ethutil.CopyBytes(state.Root().([]byte)), cumulative, LogsBloom(tx.logs).Bytes(), tx.logs}
+		receipt := &Receipt{ethutil.CopyBytes(state.Root().([]byte)), cumulative, LogsBloom(state.Logs()).Bytes(), state.Logs()}
 
 		if i < len(block.Receipts()) {
 			original := block.Receipts()[i]
@@ -238,7 +241,7 @@ func (sm *StateManager) Process(block *Block) (err error) {
 
 	txSha := DeriveSha(block.transactions)
 	if bytes.Compare(txSha, block.TxSha) != 0 {
-		return fmt.Errorf("Error validating transaction sha. Received %x, got %x", block.ReceiptSha, txSha)
+		return fmt.Errorf("Error validating transaction sha. Received %x, got %x", block.TxSha, txSha)
 	}
 
 	receipts, err := sm.ApplyDiff(state, parent, block)
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 809e5ad6a..ad7b320c4 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -232,7 +232,7 @@ func (self *StateTransition) TransitionState() (err error) {
 		} else {
 			// Add default LOG. Default = big(sender.addr) + 1
 			addr := ethutil.BigD(receiver.Address())
-			tx.addLog(vm.Log{sender.Address(), [][]byte{addr.Add(addr, ethutil.Big1).Bytes()}, nil})
+			self.state.AddLog(ethstate.Log{sender.Address(), [][]byte{ethutil.U256(addr.Add(addr, ethutil.Big1)).Bytes()}, nil})
 		}
 	}
 
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index 10bf5bc8e..331f44b55 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -8,7 +8,6 @@ import (
 	"github.com/ethereum/go-ethereum/ethcrypto"
 	"github.com/ethereum/go-ethereum/ethstate"
 	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/ethereum/go-ethereum/vm"
 	"github.com/obscuren/secp256k1-go"
 )
 
@@ -29,8 +28,6 @@ type Transaction struct {
 	v         byte
 	r, s      []byte
 
-	logs []vm.Log
-
 	// Indicates whether this tx is a contract creation transaction
 	contractCreation bool
 }
@@ -57,10 +54,6 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
 	return tx
 }
 
-func (self *Transaction) addLog(log vm.Log) {
-	self.logs = append(self.logs, log)
-}
-
 func (self *Transaction) GasValue() *big.Int {
 	return new(big.Int).Mul(self.Gas, self.GasPrice)
 }
@@ -212,7 +205,7 @@ type Receipt struct {
 	PostState         []byte
 	CumulativeGasUsed *big.Int
 	Bloom             []byte
-	Logs              vm.Logs
+	logs              ethstate.Logs
 }
 
 func NewRecieptFromValue(val *ethutil.Value) *Receipt {
@@ -229,12 +222,12 @@ func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) {
 
 	it := decoder.Get(3).NewIterator()
 	for it.Next() {
-		self.Logs = append(self.Logs, vm.NewLogFromValue(it.Value()))
+		self.logs = append(self.logs, ethstate.NewLogFromValue(it.Value()))
 	}
 }
 
 func (self *Receipt) RlpData() interface{} {
-	return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.Logs.RlpData()}
+	return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()}
 }
 
 func (self *Receipt) RlpEncode() []byte {
diff --git a/ethchain/vm_env.go b/ethchain/vm_env.go
index 4dc96e8b1..1bb67dbd0 100644
--- a/ethchain/vm_env.go
+++ b/ethchain/vm_env.go
@@ -31,8 +31,8 @@ func (self *VMEnv) BlockHash() []byte      { return self.block.Hash() }
 func (self *VMEnv) Value() *big.Int        { return self.tx.Value }
 func (self *VMEnv) State() *ethstate.State { return self.state }
 func (self *VMEnv) GasLimit() *big.Int     { return self.block.GasLimit }
-func (self *VMEnv) AddLog(log vm.Log) {
-	self.tx.addLog(log)
+func (self *VMEnv) AddLog(log ethstate.Log) {
+	self.state.AddLog(log)
 }
 func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
 	return vm.Transfer(from, to, amount)
diff --git a/ethminer/miner.go b/ethminer/miner.go
index 57cf0cd57..571b92ce0 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -185,8 +185,8 @@ func (self *Miner) mineNewBlock() {
 	self.ethereum.TxPool().RemoveSet(erroneous)
 	self.txs = append(txs, unhandledTxs...)
 
-	self.block.SetReceipts(receipts)
 	self.block.SetTransactions(txs)
+	self.block.SetReceipts(receipts)
 
 	// Accumulate the rewards included for this block
 	stateManager.AccumelateRewards(self.block.State(), self.block, parent)
diff --git a/ethpipe/vm_env.go b/ethpipe/vm_env.go
index 9d11ecf34..eb1190cf1 100644
--- a/ethpipe/vm_env.go
+++ b/ethpipe/vm_env.go
@@ -34,7 +34,7 @@ func (self *VMEnv) BlockHash() []byte      { return self.block.Hash() }
 func (self *VMEnv) Value() *big.Int        { return self.value }
 func (self *VMEnv) State() *ethstate.State { return self.state }
 func (self *VMEnv) GasLimit() *big.Int     { return self.block.GasLimit }
-func (self *VMEnv) AddLog(vm.Log)          {}
+func (self *VMEnv) AddLog(ethstate.Log)    {}
 func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
 	return vm.Transfer(from, to, amount)
 }
diff --git a/vm/log.go b/ethstate/log.go
similarity index 97%
rename from vm/log.go
rename to ethstate/log.go
index bc72a0423..a2e9ca041 100644
--- a/vm/log.go
+++ b/ethstate/log.go
@@ -1,4 +1,4 @@
-package vm
+package ethstate
 
 import "github.com/ethereum/go-ethereum/ethutil"
 
diff --git a/ethstate/state.go b/ethstate/state.go
index 97958cc0a..48efeae46 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -24,6 +24,8 @@ type State struct {
 	manifest *Manifest
 
 	refund map[string]*big.Int
+
+	logs Logs
 }
 
 // Create a new state from a given trie
@@ -31,6 +33,18 @@ func New(trie *ethtrie.Trie) *State {
 	return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)}
 }
 
+func (self *State) EmptyLogs() {
+	self.logs = nil
+}
+
+func (self *State) AddLog(log Log) {
+	self.logs = append(self.logs, log)
+}
+
+func (self *State) Logs() Logs {
+	return self.logs
+}
+
 // Retrieve the balance from the given address or 0 if object not found
 func (self *State) GetBalance(addr []byte) *big.Int {
 	stateObject := self.GetStateObject(addr)
@@ -202,6 +216,10 @@ func (self *State) Copy() *State {
 			state.refund[addr] = refund
 		}
 
+		logs := make(Logs, len(self.logs))
+		copy(logs, self.logs)
+		state.logs = logs
+
 		return state
 	}
 
@@ -216,6 +234,7 @@ func (self *State) Set(state *State) {
 	self.Trie = state.Trie
 	self.stateObjects = state.stateObjects
 	self.refund = state.refund
+	self.logs = state.logs
 }
 
 func (s *State) Root() interface{} {
diff --git a/utils/vm_env.go b/utils/vm_env.go
index 034d4a16e..9d9bbf4ec 100644
--- a/utils/vm_env.go
+++ b/utils/vm_env.go
@@ -35,7 +35,7 @@ func (self *VMEnv) BlockHash() []byte      { return self.block.Hash() }
 func (self *VMEnv) Value() *big.Int        { return self.value }
 func (self *VMEnv) State() *ethstate.State { return self.state }
 func (self *VMEnv) GasLimit() *big.Int     { return self.block.GasLimit }
-func (self *VMEnv) AddLog(vm.Log)          {}
+func (self *VMEnv) AddLog(ethstate.Log)    {}
 func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
 	return vm.Transfer(from, to, amount)
 }
diff --git a/vm/environment.go b/vm/environment.go
index b8013856e..deb46b77f 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -20,7 +20,7 @@ type Environment interface {
 	BlockHash() []byte
 	GasLimit() *big.Int
 	Transfer(from, to Account, amount *big.Int) error
-	AddLog(Log)
+	AddLog(ethstate.Log)
 }
 
 type Object interface {
@@ -43,5 +43,9 @@ func Transfer(from, to Account, amount *big.Int) error {
 	from.SubBalance(amount)
 	to.AddBalance(amount)
 
+	// Add default LOG. Default = big(sender.addr) + 1
+	//addr := ethutil.BigD(receiver.Address())
+	//tx.addLog(vm.Log{sender.Address(), [][]byte{ethutil.U256(addr.Add(addr, ethutil.Big1)).Bytes()}, nil})
+
 	return nil
 }
diff --git a/vm/vm_debug.go b/vm/vm_debug.go
index b3fbfe341..7afc7e79a 100644
--- a/vm/vm_debug.go
+++ b/vm/vm_debug.go
@@ -5,6 +5,7 @@ import (
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/ethcrypto"
+	"github.com/ethereum/go-ethereum/ethstate"
 	"github.com/ethereum/go-ethereum/ethutil"
 )
 
@@ -710,7 +711,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
 			for i := 0; i < n; i++ {
 				topics[i] = stack.Pop().Bytes()
 			}
-			self.env.AddLog(Log{closure.Address(), topics, data})
+			self.env.AddLog(ethstate.Log{closure.Address(), topics, data})
 		case MLOAD:
 			offset := stack.Pop()
 			val := ethutil.BigD(mem.Get(offset.Int64(), 32))
-- 
GitLab