aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2014-07-03 22:08:13 +0800
committerzelig <viktor.tron@gmail.com>2014-07-03 22:08:13 +0800
commitde2da4fd19b53a541ffbddfa4360ceabef14f1a9 (patch)
treee1895a115645ae46b33ed33f5fcc148a1cd1a288
parent198e5eeab9e2a7c359c12cdd5c8782dc56ae54ec (diff)
parent5d6713920625b82df2b55728b2cbb9f7f3df2025 (diff)
downloaddexon-de2da4fd19b53a541ffbddfa4360ceabef14f1a9.tar.gz
dexon-de2da4fd19b53a541ffbddfa4360ceabef14f1a9.tar.zst
dexon-de2da4fd19b53a541ffbddfa4360ceabef14f1a9.zip
Merge branch 'develop' of github.com:ethereum/eth-go into feature/clientid
-rw-r--r--ethchain/state.go6
-rw-r--r--ethchain/state_manager.go9
-rw-r--r--ethchain/state_transition.go17
-rw-r--r--ethchain/vm.go62
-rw-r--r--ethcrypto/crypto.go8
-rw-r--r--ethtrie/trie.go14
6 files changed, 68 insertions, 48 deletions
diff --git a/ethchain/state.go b/ethchain/state.go
index 3d05ff582..7ddf7916f 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -93,10 +93,6 @@ func (self *State) ResetStateObject(stateObject *StateObject) {
func (self *State) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
- if self.stateObjects[string(addr)] == nil {
- self.stateObjects[string(addr)] = stateObject
- }
-
ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Script()), stateObject.Script())
self.trie.Update(string(addr), string(stateObject.RlpEncode()))
@@ -131,7 +127,7 @@ func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
}
func (self *State) NewStateObject(addr []byte) *StateObject {
- //statelogger.Infof("(+) %x\n", addr)
+ statelogger.Infof("(+) %x\n", addr)
stateObject := NewStateObject(addr)
self.stateObjects[string(addr)] = stateObject
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index babfbd061..cec424583 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
+ "github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"math/big"
@@ -205,7 +206,15 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return err
}
+ if ethutil.Config.Paranoia {
+ valid, _ := ethtrie.ParanoiaCheck(state.trie)
+ if !valid {
+ err = fmt.Errorf("PARANOIA: World state trie corruption")
+ }
+ }
+
if !block.State().Cmp(state) {
+
err = fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().trie.Root, state.trie.Root)
return
}
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 9e7ef3efd..31196d2d7 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -1,7 +1,6 @@
package ethchain
import (
- "bytes"
"fmt"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
@@ -54,6 +53,7 @@ func (self *StateTransition) Sender() *StateObject {
}
self.sen = self.state.GetAccount(self.tx.Sender())
+
return self.sen
}
func (self *StateTransition) Receiver() *StateObject {
@@ -264,23 +264,16 @@ func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error, deepErr
ret, _, err = closure.Call(vm, data)
deepErr = vm.err != nil
- Paranoia := ethutil.Config.Paranoia
- if Paranoia {
+ if ethutil.Config.Paranoia {
var (
context = closure.object
trie = context.state.trie
- trie2 = ethtrie.NewTrie(ethutil.Config.Db, "")
)
- trie.NewIterator().Each(func(key string, v *ethutil.Value) {
- trie2.Update(key, v.Str())
- })
-
- a := ethutil.NewValue(trie2.Root).Bytes()
- b := ethutil.NewValue(context.state.trie.Root).Bytes()
- if bytes.Compare(a, b) != 0 {
+ valid, t2 := ethtrie.ParanoiaCheck(trie)
+ if !valid {
// TODO FIXME ASAP
- context.state.trie = trie2
+ context.state.trie = t2
/*
statelogger.Debugf("(o): %x\n", trie.Root)
trie.NewIterator().Each(func(key string, v *ethutil.Value) {
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 909b375ae..35443a6ba 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -35,7 +35,6 @@ func CalculateTxGas(initSize *big.Int) *big.Int {
}
type Vm struct {
- txPool *TxPool
// Stack for processing contracts
stack *Stack
// non-persistent key/value memory storage
@@ -617,48 +616,59 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case CREATE:
require(3)
- value := stack.Pop()
- size, offset := stack.Popn()
+ var (
+ err error
+ value = stack.Pop()
+ size, offset = stack.Popn()
- // Snapshot the current stack so we are able to
- // revert back to it later.
- snapshot := vm.state.Copy()
+ // Snapshot the current stack so we are able to
+ // revert back to it later.
+ snapshot = vm.state.Copy()
+ )
// Generate a new address
- addr := ethcrypto.CreateAddress(closure.caller.Address(), closure.caller.N())
+ addr := ethcrypto.CreateAddress(closure.object.Address(), closure.object.Nonce)
+ for i := uint64(0); vm.state.GetStateObject(addr) != nil; i++ {
+ ethcrypto.CreateAddress(closure.object.Address(), closure.object.Nonce+i)
+ }
+ closure.object.Nonce++
vm.Printf(" (*) %x", addr).Endl()
// Create a new contract
contract := vm.state.NewStateObject(addr)
- contract.Amount = value
-
- // Set the init script
- contract.initScript = ethutil.BigD(mem.Get(offset.Int64(), size.Int64())).Bytes()
- // Transfer all remaining gas to the new
- // contract so it may run the init script
- gas := new(big.Int).Set(closure.Gas)
-
- // Create the closure
- c := NewClosure(closure.caller,
- closure.Object(),
- contract.initScript,
- vm.state,
- gas,
- closure.Price)
- // Call the closure and set the return value as
- // main script.
- var err error
- c.Script, gas, err = c.Call(vm, nil)
+ if contract.Amount.Cmp(value) >= 0 {
+ closure.object.SubAmount(value)
+ contract.AddAmount(value)
+
+ // Set the init script
+ contract.initScript = mem.Get(offset.Int64(), size.Int64())
+ // Transfer all remaining gas to the new
+ // contract so it may run the init script
+ gas := new(big.Int).Set(closure.Gas)
+ closure.UseGas(closure.Gas)
+
+ // Create the closure
+ c := NewClosure(closure, contract, contract.initScript, vm.state, gas, closure.Price)
+ // Call the closure and set the return value as
+ // main script.
+ contract.script, err, _ = Call(vm, c, nil)
+ } else {
+ err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
+ }
if err != nil {
stack.Push(ethutil.BigFalse)
// Revert the state as it was before.
vm.state.Set(snapshot)
+
+ vm.Printf("CREATE err %v", err)
} else {
stack.Push(ethutil.BigD(addr))
+ vm.Printf("CREATE success")
}
+ vm.Endl()
case CALL:
require(7)
diff --git a/ethcrypto/crypto.go b/ethcrypto/crypto.go
index 8cb0be88c..b4bb881a0 100644
--- a/ethcrypto/crypto.go
+++ b/ethcrypto/crypto.go
@@ -3,8 +3,8 @@ package ethcrypto
import (
"code.google.com/p/go.crypto/ripemd160"
"crypto/sha256"
+ "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/sha3"
- "math/big"
)
func Sha256Bin(data []byte) []byte {
@@ -28,8 +28,6 @@ func Sha3Bin(data []byte) []byte {
}
// Creates an ethereum address given the bytes and the nonce
-func CreateAddress(b []byte, nonce *big.Int) []byte {
- addrBytes := append(b, nonce.Bytes()...)
-
- return Sha3Bin(addrBytes)[12:]
+func CreateAddress(b []byte, nonce uint64) []byte {
+ return Sha3Bin(ethutil.NewValue([]interface{}{b, nonce}).Encode())[12:]
}
diff --git a/ethtrie/trie.go b/ethtrie/trie.go
index 194c98006..38c78e7f4 100644
--- a/ethtrie/trie.go
+++ b/ethtrie/trie.go
@@ -1,6 +1,7 @@
package ethtrie
import (
+ "bytes"
"fmt"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil"
@@ -8,6 +9,19 @@ import (
"sync"
)
+func ParanoiaCheck(t1 *Trie) (bool, *Trie) {
+ t2 := NewTrie(ethutil.Config.Db, "")
+
+ t1.NewIterator().Each(func(key string, v *ethutil.Value) {
+ t2.Update(key, v.Str())
+ })
+
+ a := ethutil.NewValue(t2.Root).Bytes()
+ b := ethutil.NewValue(t1.Root).Bytes()
+
+ return bytes.Compare(a, b) == 0, t2
+}
+
func (s *Cache) Len() int {
return len(s.nodes)
}