aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-08-11 22:23:38 +0800
committerobscuren <geffobscura@gmail.com>2014-08-11 22:23:38 +0800
commita760ce05b948e89bc564af20599dcf95698ac0eb (patch)
treee9a1f0161521bc895de45e683ba6904a0d4923f9
parent2e5d28c73f1d97865def3ffe8c7ad0a4819f15f3 (diff)
downloaddexon-a760ce05b948e89bc564af20599dcf95698ac0eb.tar.gz
dexon-a760ce05b948e89bc564af20599dcf95698ac0eb.tar.zst
dexon-a760ce05b948e89bc564af20599dcf95698ac0eb.zip
Updated chain for filtering
-rw-r--r--ethchain/block.go13
-rw-r--r--ethchain/block_chain.go2
-rw-r--r--ethchain/block_chain_test.go23
-rw-r--r--ethchain/state_manager.go70
-rw-r--r--ethchain/state_transition.go12
-rw-r--r--ethchain/vm_env.go4
-rw-r--r--ethereum.go5
-rw-r--r--ethpipe/vm_env.go1
-rw-r--r--ethstate/state.go45
-rw-r--r--ethutil/rlp.go9
-rw-r--r--ethutil/value.go24
-rw-r--r--ethvm/closure.go3
-rw-r--r--ethvm/vm.go22
-rw-r--r--ethwire/messaging.go5
14 files changed, 164 insertions, 74 deletions
diff --git a/ethchain/block.go b/ethchain/block.go
index 5b06fd58d..5765abd51 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -142,19 +142,6 @@ func (block *Block) CalcGasLimit(parent *Block) *big.Int {
min := big.NewInt(125000)
return ethutil.BigMax(min, result)
- /*
- base := new(big.Int)
- base2 := new(big.Int)
- parentGL := bc.CurrentBlock.GasLimit
- parentUsed := bc.CurrentBlock.GasUsed
-
- base.Mul(parentGL, big.NewInt(1024-1))
- base2.Mul(parentUsed, big.NewInt(6))
- base2.Div(base2, big.NewInt(5))
- base.Add(base, base2)
- base.Div(base, big.NewInt(1024))
- */
-
}
func (block *Block) BlockInfo() BlockInfo {
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 3eba90fca..611735707 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -300,6 +300,8 @@ func (bc *BlockChain) setLastBlock() {
bc.genesisBlock.state.Trie.Sync()
// Prepare the genesis block
bc.Add(bc.genesisBlock)
+ fk := append([]byte("bloom"), bc.genesisBlock.Hash()...)
+ bc.Ethereum.Db().Put(fk, make([]byte, 255))
}
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
diff --git a/ethchain/block_chain_test.go b/ethchain/block_chain_test.go
index bbc96c823..1edcf9c7b 100644
--- a/ethchain/block_chain_test.go
+++ b/ethchain/block_chain_test.go
@@ -3,16 +3,19 @@ package ethchain
import (
"container/list"
"fmt"
+ "testing"
+
+ "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethdb"
+ "github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
- "testing"
)
// Implement our EthTest Manager
type TestManager struct {
stateManager *StateManager
- reactor *ethutil.ReactorEngine
+ reactor *ethreact.ReactorEngine
txPool *TxPool
blockChain *BlockChain
@@ -47,16 +50,24 @@ func (tm *TestManager) StateManager() *StateManager {
return tm.stateManager
}
-func (tm *TestManager) Reactor() *ethutil.ReactorEngine {
+func (tm *TestManager) Reactor() *ethreact.ReactorEngine {
return tm.reactor
}
func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) {
fmt.Println("Broadcast not implemented")
}
-func NewTestManager() *TestManager {
+func (tm *TestManager) ClientIdentity() ethwire.ClientIdentity {
+ return nil
+}
+func (tm *TestManager) KeyManager() *ethcrypto.KeyManager {
+ return nil
+}
- ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "", "ETH")
+func (tm *TestManager) Db() ethutil.Database { return nil }
+
+func NewTestManager() *TestManager {
+ ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "ETH")
db, err := ethdb.NewMemDatabase()
if err != nil {
@@ -66,7 +77,7 @@ func NewTestManager() *TestManager {
ethutil.Config.Db = db
testManager := &TestManager{}
- testManager.reactor = ethutil.NewReactorEngine()
+ testManager.reactor = ethreact.New()
testManager.txPool = NewTxPool(testManager)
testManager.blockChain = NewBlockChain(testManager)
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index f06622fcb..a60b28b3f 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -45,6 +45,7 @@ type EthManager interface {
Peers() *list.List
KeyManager() *ethcrypto.KeyManager
ClientIdentity() ethwire.ClientIdentity
+ Db() ethutil.Database
}
type StateManager struct {
@@ -235,7 +236,12 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// Add the block to the chain
sm.bc.Add(block)
- sm.notifyChanges(state)
+
+ // Create a bloom bin for this block
+ filter := sm.createBloomFilter(state)
+ // Persist the data
+ fk := append([]byte("bloom"), block.Hash()...)
+ sm.Ethereum.Db().Put(fk, filter.Bin())
statelogger.Infof("Added block #%d (%x)\n", block.Number, block.Hash())
if dontReact == false {
@@ -363,14 +369,74 @@ func (sm *StateManager) Stop() {
sm.bc.Stop()
}
-func (sm *StateManager) notifyChanges(state *ethstate.State) {
+// Manifest will handle both creating notifications and generating bloom bin data
+func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
+ bloomf := NewBloomFilter(nil)
+
for addr, stateObject := range state.Manifest().ObjectChanges {
+ // Set the bloom filter's bin
+ bloomf.Set([]byte(addr))
+
sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
}
for stateObjectAddr, mappedObjects := range state.Manifest().StorageChanges {
for addr, value := range mappedObjects {
+ // Set the bloom filter's bin
+ bloomf.Set(ethcrypto.Sha3Bin([]byte(stateObjectAddr + addr)))
+
sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &ethstate.StorageState{[]byte(stateObjectAddr), []byte(addr), value})
}
}
+
+ return bloomf
+}
+
+func (sm *StateManager) GetMessages(block *Block) (messages []*ethstate.Message, err error) {
+ if !sm.bc.HasBlock(block.PrevHash) {
+ return nil, ParentError(block.PrevHash)
+ }
+
+ sm.lastAttemptedBlock = block
+
+ var (
+ parent = sm.bc.GetBlock(block.PrevHash)
+ state = parent.State().Copy()
+ )
+
+ defer state.Reset()
+
+ if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
+ fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
+ }
+
+ receipts, err := sm.ApplyDiff(state, parent, block)
+ if err != nil {
+ return nil, err
+ }
+
+ txSha := CreateTxSha(receipts)
+ if bytes.Compare(txSha, block.TxSha) != 0 {
+ return nil, fmt.Errorf("Error validating tx sha. Received %x, got %x", block.TxSha, txSha)
+ }
+
+ // Block validation
+ if err = sm.ValidateBlock(block); err != nil {
+ statelogger.Errorln("Error validating block:", err)
+ return nil, err
+ }
+
+ // I'm not sure, but I don't know if there should be thrown
+ // any errors at this time.
+ if err = sm.AccumelateRewards(state, block); err != nil {
+ statelogger.Errorln("Error accumulating reward", err)
+ return nil, err
+ }
+
+ if !block.State().Cmp(state) {
+ err = fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().Trie.Root, state.Trie.Root)
+ return nil, err
+ }
+
+ return state.Manifest().Messages, nil
}
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index dfcbfcc04..489ff2b6a 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -211,6 +211,13 @@ func (self *StateTransition) TransitionState() (err error) {
snapshot = self.state.Copy()
}
+ msg := self.state.Manifest().AddMessage(&ethstate.Message{
+ To: receiver.Address(), From: sender.Address(),
+ Input: self.tx.Data,
+ Origin: sender.Address(),
+ Block: self.block.Hash(), Timestamp: self.block.Time, Coinbase: self.block.Coinbase, Number: self.block.Number,
+ })
+
// Process the init code and create 'valid' contract
if IsContractAddr(self.receiver) {
// Evaluate the initialization script
@@ -226,14 +233,17 @@ func (self *StateTransition) TransitionState() (err error) {
}
receiver.Code = code
+ msg.Output = code
} else {
if len(receiver.Code) > 0 {
- _, err = self.Eval(receiver.Code, receiver, "code")
+ ret, err := self.Eval(receiver.Code, receiver, "code")
if err != nil {
self.state.Set(snapshot)
return fmt.Errorf("Error during code execution %v", err)
}
+
+ msg.Output = ret
}
}
diff --git a/ethchain/vm_env.go b/ethchain/vm_env.go
index ddead77fd..30f9497fa 100644
--- a/ethchain/vm_env.go
+++ b/ethchain/vm_env.go
@@ -1,8 +1,9 @@
package ethchain
import (
- "github.com/ethereum/eth-go/ethstate"
"math/big"
+
+ "github.com/ethereum/eth-go/ethstate"
)
type VMEnv struct {
@@ -25,5 +26,6 @@ func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
+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 }
diff --git a/ethereum.go b/ethereum.go
index 69bb93cff..c1c4c2f2f 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -44,8 +44,8 @@ type Ethereum struct {
// Channel for shutting down the ethereum
shutdownChan chan bool
quit chan bool
+
// DB interface
- //db *ethdb.LDBDatabase
db ethutil.Database
// State manager for processing new blocks and managing the over all states
stateManager *ethchain.StateManager
@@ -149,6 +149,9 @@ func (s *Ethereum) StateManager() *ethchain.StateManager {
func (s *Ethereum) TxPool() *ethchain.TxPool {
return s.txPool
}
+func (self *Ethereum) Db() ethutil.Database {
+ return self.db
+}
func (s *Ethereum) ServerCaps() Caps {
return s.serverCaps
diff --git a/ethpipe/vm_env.go b/ethpipe/vm_env.go
index c06a2a763..822a9e5c7 100644
--- a/ethpipe/vm_env.go
+++ b/ethpipe/vm_env.go
@@ -29,5 +29,6 @@ func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
+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 }
diff --git a/ethstate/state.go b/ethstate/state.go
index 10bcf6335..19210916e 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -211,50 +211,13 @@ func (self *State) Update() {
}
}
-// Debug stuff
-func (self *State) CreateOutputForDiff() {
- for _, stateObject := range self.stateObjects {
- stateObject.CreateOutputForDiff()
- }
-}
-
func (self *State) Manifest() *Manifest {
return self.manifest
}
-// Object manifest
-//
-// The object manifest is used to keep changes to the state so we can keep track of the changes
-// that occurred during a state transitioning phase.
-type Manifest struct {
- // XXX These will be handy in the future. Not important for now.
- objectAddresses map[string]bool
- storageAddresses map[string]map[string]bool
-
- ObjectChanges map[string]*StateObject
- StorageChanges map[string]map[string]*big.Int
-}
-
-func NewManifest() *Manifest {
- m := &Manifest{objectAddresses: make(map[string]bool), storageAddresses: make(map[string]map[string]bool)}
- m.Reset()
-
- return m
-}
-
-func (m *Manifest) Reset() {
- m.ObjectChanges = make(map[string]*StateObject)
- m.StorageChanges = make(map[string]map[string]*big.Int)
-}
-
-func (m *Manifest) AddObjectChange(stateObject *StateObject) {
- m.ObjectChanges[string(stateObject.Address())] = stateObject
-}
-
-func (m *Manifest) AddStorageChange(stateObject *StateObject, storageAddr []byte, storage *big.Int) {
- if m.StorageChanges[string(stateObject.Address())] == nil {
- m.StorageChanges[string(stateObject.Address())] = make(map[string]*big.Int)
+// Debug stuff
+func (self *State) CreateOutputForDiff() {
+ for _, stateObject := range self.stateObjects {
+ stateObject.CreateOutputForDiff()
}
-
- m.StorageChanges[string(stateObject.Address())][string(storageAddr)] = storage
}
diff --git a/ethutil/rlp.go b/ethutil/rlp.go
index cf7f97ffd..17ff627eb 100644
--- a/ethutil/rlp.go
+++ b/ethutil/rlp.go
@@ -2,15 +2,16 @@ package ethutil
import (
"bytes"
- _ "encoding/binary"
"fmt"
- _ "log"
- _ "math"
"math/big"
)
-type RlpEncodable interface {
+type RlpEncode interface {
RlpEncode() []byte
+}
+
+type RlpEncodeDecode interface {
+ RlpEncode
RlpValue() []interface{}
}
diff --git a/ethutil/value.go b/ethutil/value.go
index 2233b978c..608d332ba 100644
--- a/ethutil/value.go
+++ b/ethutil/value.go
@@ -74,6 +74,30 @@ func (val *Value) Uint() uint64 {
return 0
}
+func (val *Value) Int() int64 {
+ if Val, ok := val.Val.(int8); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int16); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int32); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int64); ok {
+ return Val
+ } else if Val, ok := val.Val.(int); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(float32); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(float64); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.([]byte); ok {
+ return new(big.Int).SetBytes(Val).Int64()
+ } else if Val, ok := val.Val.(*big.Int); ok {
+ return Val.Int64()
+ }
+
+ return 0
+}
+
func (val *Value) Byte() byte {
if Val, ok := val.Val.(byte); ok {
return Val
diff --git a/ethvm/closure.go b/ethvm/closure.go
index 505fd43fb..f9be952d4 100644
--- a/ethvm/closure.go
+++ b/ethvm/closure.go
@@ -3,9 +3,10 @@ package ethvm
// TODO Re write VM to use values instead of big integers?
import (
+ "math/big"
+
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
- "math/big"
)
type ClosureRef interface {
diff --git a/ethvm/vm.go b/ethvm/vm.go
index a3c273f62..a0d4db591 100644
--- a/ethvm/vm.go
+++ b/ethvm/vm.go
@@ -52,6 +52,7 @@ type Environment interface {
Time() int64
Difficulty() *big.Int
Value() *big.Int
+ BlockHash() []byte
}
type Object interface {
@@ -696,6 +697,12 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" (*) %x", addr).Endl()
+ msg := self.env.State().Manifest().AddMessage(&ethstate.Message{
+ To: addr, From: closure.Address(),
+ Origin: self.env.Origin(),
+ Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
+ })
+
// Create a new contract
contract := self.env.State().NewStateObject(addr)
if contract.Balance.Cmp(value) >= 0 {
@@ -704,7 +711,8 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
// Set the init script
initCode := mem.Get(offset.Int64(), size.Int64())
- //fmt.Printf("%x\n", initCode)
+ msg.Input = initCode
+
// Transfer all remaining gas to the new
// contract so it may run the init script
gas := new(big.Int).Set(closure.Gas)
@@ -728,7 +736,8 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf("CREATE err %v", err)
} else {
stack.Push(ethutil.BigD(addr))
- self.Printf("CREATE success")
+
+ msg.Output = contract.Code
}
self.Endl()
@@ -752,6 +761,13 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
// Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64())
+ msg := self.env.State().Manifest().AddMessage(&ethstate.Message{
+ To: addr.Bytes(), From: closure.Address(),
+ Input: args,
+ Origin: self.env.Origin(),
+ Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
+ })
+
if closure.object.Balance.Cmp(value) < 0 {
vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance)
@@ -782,6 +798,8 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
+ msg.Output = ret
+
// Debug hook
if self.Dbg != nil {
self.Dbg.SetCode(closure.Code)
diff --git a/ethwire/messaging.go b/ethwire/messaging.go
index f13b72353..d114a1c9d 100644
--- a/ethwire/messaging.go
+++ b/ethwire/messaging.go
@@ -6,9 +6,10 @@ import (
"bytes"
"errors"
"fmt"
- "github.com/ethereum/eth-go/ethutil"
"net"
"time"
+
+ "github.com/ethereum/eth-go/ethutil"
)
// Connection interface describing the methods required to implement the wire protocol.
@@ -109,7 +110,7 @@ func (self *Connection) Write(typ MsgType, v ...interface{}) error {
slice := [][]interface{}{[]interface{}{byte(typ)}}
for _, value := range v {
- if encodable, ok := value.(ethutil.RlpEncodable); ok {
+ if encodable, ok := value.(ethutil.RlpEncodeDecode); ok {
slice = append(slice, encodable.RlpValue())
} else if raw, ok := value.([]interface{}); ok {
slice = append(slice, raw)