diff --git a/cmd/mist/assets/examples/coin.js b/cmd/mist/assets/examples/coin.js new file mode 100644 index 0000000000..ada9d196c0 --- /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 0eb3f89201..c360273da8 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 994019a086..0000000000 --- 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 af054ff09a..c83d59ed77 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 - - return state + state := New(nil, self.db) + state.trie = self.trie.Copy() + for k, stateObject := range self.stateObjects { + state.stateObjects[k] = stateObject.Copy() } - return nil + 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 } 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 2b8c904289..29e1ade543 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) }