aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/mist/assets/examples/coin.js1
-rw-r--r--core/block_processor.go43
-rw-r--r--state/manifest.go61
-rw-r--r--state/statedb.go51
-rw-r--r--vm/vm.go11
5 files changed, 36 insertions, 131 deletions
diff --git a/cmd/mist/assets/examples/coin.js b/cmd/mist/assets/examples/coin.js
new file mode 100644
index 000000000..ada9d196c
--- /dev/null
+++ b/cmd/mist/assets/examples/coin.js
@@ -0,0 +1 @@
+var contract = web3.eth.contractFromAbi([{"constant":false,"inputs":[{"name":"_h","type":"hash256"}],"name":"confirm","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"execute","outputs":[{"name":"_r","type":"hash256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"}],"name":"kill","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"}],"name":"changeOwner","outputs":[],"type":"function"},{"inputs":[{"indexed":false,"name":"value","type":"uint256"}],"name":"CashIn","type":"event"},{"inputs":[{"indexed":true,"name":"out","type":"string32"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"to","type":"address"}],"name":"SingleTransact","type":"event"},{"inputs":[{"indexed":true,"name":"out","type":"string32"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"operation","type":"hash256"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"to","type":"address"}],"name":"MultiTransact","type":"event"}]);
diff --git a/core/block_processor.go b/core/block_processor.go
index 0eb3f8920..c360273da 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -143,6 +143,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
return receipts, handled, unhandled, erroneous, err
}
+// Process block will attempt to process the given block's transactions and applies them
+// on top of the block's parent state (given it exists) and will return wether it was
+// successful or not.
func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) {
// Processing a blocks may never happen simultaneously
sm.mutex.Lock()
@@ -158,14 +161,14 @@ func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) {
}
parent := sm.bc.GetBlock(header.ParentHash)
- return sm.ProcessWithParent(block, parent)
+ return sm.processWithParent(block, parent)
}
-func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, err error) {
+func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big.Int, err error) {
sm.lastAttemptedBlock = block
+ // 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.Trie().Copy())
// Block validation
if err = sm.ValidateBlock(block, parent); err != nil {
@@ -179,18 +182,23 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big
header := block.Header()
+ // Validate the received block's bloom with the one derived from the generated receipts.
+ // For valid blocks this should always validate to true.
rbloom := types.CreateBloom(receipts)
if bytes.Compare(rbloom, header.Bloom) != 0 {
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return
}
+ // The transactions Trie's root (R = (Tr [[H1, T1], [H2, T2], ... [Hn, Tn]]))
+ // can be used by light clients to make sure they've received the correct Txs
txSha := types.DeriveSha(block.Transactions())
if bytes.Compare(txSha, header.TxHash) != 0 {
err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha)
return
}
+ // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
receiptSha := types.DeriveSha(receipts)
if bytes.Compare(receiptSha, header.ReceiptHash) != 0 {
fmt.Println("receipts", receipts)
@@ -198,12 +206,14 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big
return
}
+ // Accumulate static rewards; block reward, uncle's and uncle inclusion.
if err = sm.AccumulateRewards(state, block, parent); err != nil {
return
}
+ // Commit state objects/accounts to a temporary trie (does not save)
+ // used to calculate the state root.
state.Update(ethutil.Big0)
-
if !bytes.Equal(header.Root, state.Root()) {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return
@@ -213,10 +223,6 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big
td = CalculateTD(block, parent)
// Sync the current block's state to the database
state.Sync()
- // Set the block hashes for the current messages
- state.Manifest().SetHash(block.Hash())
- // Reset the manifest XXX We need this?
- state.Manifest().Reset()
// Remove transactions from the pool
sm.txpool.RemoveSet(block.Transactions())
@@ -296,27 +302,6 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
return nil
}
-func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Message, err error) {
- if !sm.bc.HasBlock(block.Header().ParentHash) {
- return nil, ParentError(block.Header().ParentHash)
- }
-
- sm.lastAttemptedBlock = block
-
- var (
- parent = sm.bc.GetBlock(block.Header().ParentHash)
- //state = state.New(parent.Trie().Copy())
- state = state.New(parent.Root(), sm.db)
- )
-
- defer state.Reset()
-
- sm.TransitionState(state, parent, block)
- sm.AccumulateRewards(state, block, parent)
-
- return state.Manifest().Messages, nil
-}
-
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
if !sm.bc.HasBlock(block.Header().ParentHash) {
return nil, ParentError(block.Header().ParentHash)
diff --git a/state/manifest.go b/state/manifest.go
deleted file mode 100644
index 994019a08..000000000
--- a/state/manifest.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package state
-
-import (
- "fmt"
- "math/big"
-)
-
-// 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 {
- Messages Messages
-}
-
-func NewManifest() *Manifest {
- m := &Manifest{}
- m.Reset()
-
- return m
-}
-
-func (m *Manifest) Reset() {
- m.Messages = nil
-}
-
-func (self *Manifest) AddMessage(msg *Message) *Message {
- self.Messages = append(self.Messages, msg)
-
- return msg
-}
-
-func (self *Manifest) SetHash(hash []byte) {
- for _, message := range self.Messages {
- message.Block = hash
- }
-}
-
-type Messages []*Message
-type Message struct {
- To, From []byte
- Input []byte
- Output []byte
- Path int
- Origin []byte
- Timestamp int64
- Coinbase []byte
- Block []byte
- Number *big.Int
- Value *big.Int
-
- ChangedAddresses [][]byte
-}
-
-func (self *Message) AddStorageChange(addr []byte) {
- self.ChangedAddresses = append(self.ChangedAddresses, addr)
-}
-
-func (self *Message) String() string {
- return fmt.Sprintf("Message{to: %x from: %x input: %x output: %x origin: %x coinbase: %x block: %x number: %v timestamp: %d path: %d value: %v", self.To, self.From, self.Input, self.Output, self.Origin, self.Coinbase, self.Block, self.Number, self.Timestamp, self.Path, self.Value)
-}
diff --git a/state/statedb.go b/state/statedb.go
index af054ff09..c83d59ed7 100644
--- a/state/statedb.go
+++ b/state/statedb.go
@@ -22,8 +22,6 @@ type StateDB struct {
stateObjects map[string]*StateObject
- manifest *Manifest
-
refund map[string]*big.Int
logs Logs
@@ -32,7 +30,7 @@ type StateDB struct {
// Create a new state from a given trie
func New(root []byte, db ethutil.Database) *StateDB {
trie := trie.New(ethutil.CopyBytes(root), db)
- return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)}
+ return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int)}
}
func (self *StateDB) EmptyLogs() {
@@ -47,6 +45,13 @@ func (self *StateDB) Logs() Logs {
return self.logs
}
+func (self *StateDB) Refund(addr []byte, gas *big.Int) {
+ if self.refund[string(addr)] == nil {
+ self.refund[string(addr)] = new(big.Int)
+ }
+ self.refund[string(addr)].Add(self.refund[string(addr)], gas)
+}
+
// Retrieve the balance from the given address or 0 if object not found
func (self *StateDB) GetBalance(addr []byte) *big.Int {
stateObject := self.GetStateObject(addr)
@@ -57,13 +62,6 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
return ethutil.Big0
}
-func (self *StateDB) Refund(addr []byte, gas *big.Int) {
- if self.refund[string(addr)] == nil {
- self.refund[string(addr)] = new(big.Int)
- }
- self.refund[string(addr)].Add(self.refund[string(addr)], gas)
-}
-
func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
@@ -103,6 +101,7 @@ func (self *StateDB) SetCode(addr, code []byte) {
}
}
+// TODO vars
func (self *StateDB) GetState(a, b []byte) []byte {
stateObject := self.GetStateObject(a)
if stateObject != nil {
@@ -212,25 +211,21 @@ func (s *StateDB) Cmp(other *StateDB) bool {
}
func (self *StateDB) Copy() *StateDB {
- if self.trie != nil {
- state := New(nil, self.db)
- state.trie = self.trie.Copy()
- for k, stateObject := range self.stateObjects {
- state.stateObjects[k] = stateObject.Copy()
- }
-
- for addr, refund := range self.refund {
- state.refund[addr] = new(big.Int).Set(refund)
- }
-
- logs := make(Logs, len(self.logs))
- copy(logs, self.logs)
- state.logs = logs
+ state := New(nil, self.db)
+ state.trie = self.trie.Copy()
+ for k, stateObject := range self.stateObjects {
+ state.stateObjects[k] = stateObject.Copy()
+ }
- return state
+ for addr, refund := range self.refund {
+ state.refund[addr] = new(big.Int).Set(refund)
}
- return nil
+ logs := make(Logs, len(self.logs))
+ copy(logs, self.logs)
+ state.logs = logs
+
+ return state
}
func (self *StateDB) Set(state *StateDB) {
@@ -301,10 +296,6 @@ func (self *StateDB) Update(gasUsed *big.Int) {
}
}
-func (self *StateDB) Manifest() *Manifest {
- return self.manifest
-}
-
// Debug stuff
func (self *StateDB) CreateOutputForDiff() {
for _, stateObject := range self.stateObjects {
diff --git a/vm/vm.go b/vm/vm.go
index 2b8c90428..29e1ade54 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -38,13 +38,6 @@ func New(env Environment) *Vm {
func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
self.env.SetDepth(self.env.Depth() + 1)
- msg := self.env.State().Manifest().AddMessage(&state.Message{
- To: me.Address(), From: caller.Address(),
- Input: callData,
- Origin: self.env.Origin(),
- Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
- Value: value,
- })
context := NewContext(caller, me, code, gas, price)
vmlogger.Debugf("(%d) (%x) %x (code=%d) gas: %v (d) %x\n", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData)
@@ -618,8 +611,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
val, loc := stack.Popn()
statedb.SetState(context.Address(), loc.Bytes(), val)
- msg.AddStorageChange(loc.Bytes())
-
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP:
jump(pc, stack.Pop())
@@ -670,7 +661,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
dataGas.Mul(dataGas, GasCreateByte)
if context.UseGas(dataGas) {
ref.SetCode(ret)
- msg.Output = ret
}
addr = ref.Address()
@@ -713,7 +703,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
vmlogger.Debugln(err)
} else {
stack.Push(ethutil.BigTrue)
- msg.Output = ret
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}