Documented methods & removed old manifest

pull/265/head^2
obscuren 10 years ago
parent 558c67d392
commit 3f6baa45a7
  1. 1
      cmd/mist/assets/examples/coin.js
  2. 43
      core/block_processor.go
  3. 61
      state/manifest.go
  4. 51
      state/statedb.go
  5. 11
      vm/vm.go

@ -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"}]);

@ -143,6 +143,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
return receipts, handled, unhandled, erroneous, err 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) { func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) {
// Processing a blocks may never happen simultaneously // Processing a blocks may never happen simultaneously
sm.mutex.Lock() 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) 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 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.Root(), sm.db)
//state := state.New(parent.Trie().Copy())
// Block validation // Block validation
if err = sm.ValidateBlock(block, parent); err != nil { 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() 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) rbloom := types.CreateBloom(receipts)
if bytes.Compare(rbloom, header.Bloom) != 0 { if bytes.Compare(rbloom, header.Bloom) != 0 {
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return 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()) txSha := types.DeriveSha(block.Transactions())
if bytes.Compare(txSha, header.TxHash) != 0 { if bytes.Compare(txSha, header.TxHash) != 0 {
err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha) err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha)
return return
} }
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
receiptSha := types.DeriveSha(receipts) receiptSha := types.DeriveSha(receipts)
if bytes.Compare(receiptSha, header.ReceiptHash) != 0 { if bytes.Compare(receiptSha, header.ReceiptHash) != 0 {
fmt.Println("receipts", receipts) fmt.Println("receipts", receipts)
@ -198,12 +206,14 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big
return return
} }
// Accumulate static rewards; block reward, uncle's and uncle inclusion.
if err = sm.AccumulateRewards(state, block, parent); err != nil { if err = sm.AccumulateRewards(state, block, parent); err != nil {
return return
} }
// Commit state objects/accounts to a temporary trie (does not save)
// used to calculate the state root.
state.Update(ethutil.Big0) state.Update(ethutil.Big0)
if !bytes.Equal(header.Root, state.Root()) { if !bytes.Equal(header.Root, state.Root()) {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return return
@ -213,10 +223,6 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big
td = CalculateTD(block, parent) td = CalculateTD(block, parent)
// Sync the current block's state to the database // Sync the current block's state to the database
state.Sync() 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 // Remove transactions from the pool
sm.txpool.RemoveSet(block.Transactions()) sm.txpool.RemoveSet(block.Transactions())
@ -296,27 +302,6 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
return nil 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) { func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
if !sm.bc.HasBlock(block.Header().ParentHash) { if !sm.bc.HasBlock(block.Header().ParentHash) {
return nil, ParentError(block.Header().ParentHash) return nil, ParentError(block.Header().ParentHash)

@ -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)
}

@ -22,8 +22,6 @@ type StateDB struct {
stateObjects map[string]*StateObject stateObjects map[string]*StateObject
manifest *Manifest
refund map[string]*big.Int refund map[string]*big.Int
logs Logs logs Logs
@ -32,7 +30,7 @@ type StateDB struct {
// Create a new state from a given trie // Create a new state from a given trie
func New(root []byte, db ethutil.Database) *StateDB { func New(root []byte, db ethutil.Database) *StateDB {
trie := trie.New(ethutil.CopyBytes(root), db) 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() { func (self *StateDB) EmptyLogs() {
@ -47,6 +45,13 @@ func (self *StateDB) Logs() Logs {
return self.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 // Retrieve the balance from the given address or 0 if object not found
func (self *StateDB) GetBalance(addr []byte) *big.Int { func (self *StateDB) GetBalance(addr []byte) *big.Int {
stateObject := self.GetStateObject(addr) stateObject := self.GetStateObject(addr)
@ -57,13 +62,6 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
return ethutil.Big0 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) { func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
stateObject := self.GetStateObject(addr) stateObject := self.GetStateObject(addr)
if stateObject != nil { if stateObject != nil {
@ -103,6 +101,7 @@ func (self *StateDB) SetCode(addr, code []byte) {
} }
} }
// TODO vars
func (self *StateDB) GetState(a, b []byte) []byte { func (self *StateDB) GetState(a, b []byte) []byte {
stateObject := self.GetStateObject(a) stateObject := self.GetStateObject(a)
if stateObject != nil { if stateObject != nil {
@ -212,25 +211,21 @@ func (s *StateDB) Cmp(other *StateDB) bool {
} }
func (self *StateDB) Copy() *StateDB { func (self *StateDB) Copy() *StateDB {
if self.trie != nil { state := New(nil, self.db)
state := New(nil, self.db) state.trie = self.trie.Copy()
state.trie = self.trie.Copy() for k, stateObject := range self.stateObjects {
for k, stateObject := range self.stateObjects { state.stateObjects[k] = stateObject.Copy()
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
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) { 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 // Debug stuff
func (self *StateDB) CreateOutputForDiff() { func (self *StateDB) CreateOutputForDiff() {
for _, stateObject := range self.stateObjects { for _, stateObject := range self.stateObjects {

@ -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) { 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) 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) 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) 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() val, loc := stack.Popn()
statedb.SetState(context.Address(), loc.Bytes(), val) statedb.SetState(context.Address(), loc.Bytes(), val)
msg.AddStorageChange(loc.Bytes())
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP: case JUMP:
jump(pc, stack.Pop()) 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) dataGas.Mul(dataGas, GasCreateByte)
if context.UseGas(dataGas) { if context.UseGas(dataGas) {
ref.SetCode(ret) ref.SetCode(ret)
msg.Output = ret
} }
addr = ref.Address() addr = ref.Address()
@ -713,7 +703,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
vmlogger.Debugln(err) vmlogger.Debugln(err)
} else { } else {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
msg.Output = ret
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret) mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
} }

Loading…
Cancel
Save